Linux でファイルを参照できる **出力** には 4 つの種類があるという結論は本当でしょうか?

Linux でファイルを参照できる **出力** には 4 つの種類があるという結論は本当でしょうか?

4つのタイプがあるというのは本当でしょうか?ストリーム出力コマンドを実行した後に CLI にファイルを表示したくない場合は、Linux でファイルを参照できますか?

ファイルへの参照の可能性:

  1. すべてのストリーム出力
  2. stderrのみ
  3. stdout のみ (stdout の最終結果を含む)。
  4. stdout と stderr (stdout の最終結果は除く)。

ノート:

4番の例は ですfind / -type f -name php.ini 2>/dev/null。私が理解している限り、このコマンドではstderrもstdoutも出力されません(stdoutの最終結果この場合、見つかった場合は検索したファイルになります。

答え1

Unix システム上の各プロセスには 2 つの出力ストリームが接続されています。標準出力(stdout、ファイル記述子1)および標準誤差(stderr、ファイル記述子 2)。これらは互いに独立してリダイレクトされる場合があります。標準入力ファイル記述子 0 を使用します。

  • 標準出力をファイル にリダイレクトするにはfile>fileまたはより明示的な を使用します1>file。データを破棄するにfileは に置き換えます。/dev/null
  • 標準エラーをファイルにリダイレクトするにはfile、 を使用します2>file
  • 標準エラーを標準出力の送信先にリダイレクトするには、 を使用します2>&1
  • 標準出力を標準エラーの出力先にリダイレクトするには、 を使用します1>&2

ストリームやプロセスには「最終結果」という概念はありません。プロセス自体が開いたファイルにデータを出力する場合や、他の副作用 ( の場合、ディレクトリからファイルのリンクを解除する、 の場合、複数rmのネットワーク接続を処理するなどsshd) がない限り、標準出力に送信されるものはすべてプロセスの「結果」と見なすことができます。プロセスは、そのプロセスの「結果」と見なすことができる終了ステータス (「成功」の場合はゼロ、「失敗」の場合はゼロ以外) も返しますが、これは必ずしもプロセスの出力ストリームに関連しているわけではありません。

ストリームはリダイレクトされる場合もあります追加モードでは、リダイレクト先がファイルの場合、そのファイルは最初は切り捨てられず、ストリーム上のデータはファイルの末尾に追加されます。これを行うには、>>fileの代わりにを使用します>file

質問のメモでは、コマンド

find / -type f -name php.ini 2>/dev/null

が与えられます。これはリダイレクト(破棄)しますのみ標準エラー。標準出力ストリームはまったくリダイレ​​クトされないため、コンソールまたはターミナルで全体が表示されます。パイプラインの中間部分である場合、標準出力ストリームはパイプラインの次のコマンドの標準入力に送られます。

結論として、(4 つではありません) 出力ストリーム。これらは、その内容を破棄するなど、さまざまな方法で個別にリダイレクトできます。

答え2

プロセス慣例により、 は 3 つの標準ファイル記述子を使用できます。これらのファイル記述子は、、、および のストリームとして使用stdinできstdoutますstderr

デフォルトでは、シェル (CLI) からプロセスを開始すると、最初のプロセスは端末 (または xterm などの端末エミュレーター) の入力に接続され、他の 2 つは端末の出力に接続されます。

シェルに、それらを他の場所、たとえば/dev/null(そこではそれらは単に飲み込まれる)にリダイレクトするように指示することができます。そして、 と に対して独立してこれを行うことができますstdoutstderrしたがって、この場合、実際には 4 つの可能性があります。

command 
command > /dev/null
command 2> /dev/null
command > /dev/null 2> /dev/null

ただし、いずれかまたは両方を他の場所にリダイレクトすることを妨げるものは何もありません。

command > /tmp/myout 2> /tmp/myerr

その場合、ターミナルにも出力は表示されませんが、後でファイル/tmp/myoutおよびで読み取ることができます/tmp/myerr

答え3

状況はあなたの質問が示唆するよりも単純であり、複雑です。言い換えると、クサラナンダ言う彼の答え、出力用に従来どおりに設定され使用される 2 つの標準 (従来の) I/O ストリーム (ファイル記述子) があります: stdout (ファイル記述子 1) と stderr (ファイル記述子 2)。標準的な質問は、 シェルの制御演算子とリダイレクト演算子とは何ですか?では、リダイレクトの方法について説明しています。単純に考えると、5 つの異なる組み合わせを列挙できます。

╔══════════════════════════════╦═════════════════════════════════════════════╗
║                              ║                   stderr                    ║
║                              ╟─────────────────────┬───────────────────────╢
║                              ║       default       │                       ║
║                              ║ (same as the shell) │       redirected      ║
╠════════╤═════════════════════╬═════════════════════╦═══════════════════════╣
║        │       default       ║                     ║                       ║
║        │ (same as the shell) ║          1          ║           2           ║
║        ├─────────────────────╠═════════════════════╬═══════════════════════╣
║ stdout │                     ║                     ║ 4. redirected         ║
║        │                     ║                     ║    to the same file   ║
║        │      redirected     ║          3          ╟───────────────────────╢
║        │                     ║                     ║ 5. redirected         ║
║        │                     ║                     ║    to different files ║
╚════════╧═════════════════════╩═════════════════════╩═══════════════════════╝

しかし、ファイルとは異なるものとして数え、追加モードを特別なケースとして数え/dev/null、読み取り/書き込みモードを書き込み専用モードとは異なるものとして数え、パイプをファイルとは異なるものとして数えると、組み合わせの数は指数関数的に増加します。ただし、繰り返し述べられているように、「stdout の最終結果」は標準的な Unix/Linux/bash のフレーズではありません。

たった2つ?

他の回答は(おそらく賢明なことに)stdoutとstderr(ファイル記述子1と2)に限定されています。私は(無謀にも?)この質問に対する完全な回答は、他のファイル記述子が数百、数千、あるいはそれ以上存在するという事実に言及すべきだと考えています。100万以上たとえば、 のようなコマンドを実行するとdiff file1 file2diffプログラムはfile1と を開きfile2、カーネルはおそらくファイル記述子 3 と 4 を割り当てます。違いは、ファイル記述子 0、1、2 のみが事前に定義されていることです。2 より大きいファイル記述子のリダイレクトについては、次の場所で説明されています。

たとえば、高ファイル記述子の次の例を参照してください。

$ 猫犬.c
#include <stdio.h>
#include <文字列.h>

主要()
{
        int i, 長さ;
        char msg[] = "こんにちは、犬。\n";

        len = strlen(メッセージ);
        i = write(17, メッセージ, 長さ);
        (i == 長さ)の場合
                printf("成功! i = %d = len\n", i);
        そうでない場合 (i == -1)
            {
                printf("エラー! i = %d (len = %d)\n", i, len);
                エラー("");
            }
        それ以外
                printf("予期しない結果: i = %d、len = %d\n", i, len);
}

$ 犬を作る
cc 犬.c -o 犬

$ ./犬
エラー! i = -1 (len = 12)
ファイル記述子が不正です

$ ./犬 17> 動物
成功しました! i = 12 = len

$ ls -l
合計70
-rw-r--r-- 1私のユーザー名 私のグループ名    12 4月 12 13:36 動物
-rwxr-xr-x 1私のユーザー名 私のグループ名67067 4月12日 13:36 犬
-rw-r--r-- 1私のユーザー名 私のグループ名   358 4月12日 13:36 canine.c

$ 猫 動物
こんにちは、犬さん。

警告: 上記の方法がすべてのシェルのすべてのバージョンで機能するかどうかはわかりません。

標準プログラムは、2 より大きいファイル記述子に書き込みません (ファイルを開いたり、ネットワーク接続を行ったり、またはそれに類する何らかの方法でカーネルからそのファイル記述子を取得しない限り)。ただし、それを実行する (非標準の) プログラムがある場合は、それらのファイル記述子をリダイレクトできます。

また、ファイル記述子が 100 個だけあり、それぞれがリダイレクトされるかどうかだけを考慮すると、1,000,000,000,000,000,000,000,000,000,000,000 の 10 億通りを超える組み合わせが考えられます。

関連情報