「リダイレクト」と「パイプ」の違いは何ですか?


204

この質問は少しばかげているように聞こえるかもしれませんが、リダイレクトとパイプの違いを実際に見ることはできません。

リダイレクトは、stdout / stdin / stderrのリダイレクトに使用されます(例:)ls > log.txt

パイプは、コマンドの出力を別のコマンドへの入力として与えるために使用されますls | grep file.txt

しかし、同じことに対して2つの演算子があるのはなぜですか?

単にls > grep出力を渡すために書くのではなく、これも一種のリダイレクトではありませんか?私は何が欠けていますか?

回答:


223

パイプは、別のプログラムまたはユーティリティに出力を渡すために使用されます

リダイレクトは、出力をファイルまたはストリームに渡すために使用されます

例:thing1 > thing2vsthing1 | thing2

thing1 > thing2

  1. シェルは次の名前のプログラムを実行します thing1
  2. thing1出力するものはすべて、というファイルに配置されますthing2。(注- thing2存在する場合、上書きされます)

プログラムthing1からの出力をというプログラムに渡す場合thing2は、次のことができます。

thing1 > temp_file && thing2 < temp_file

どちらだろう

  1. という名前のプログラムを実行 thing1
  2. 出力を次の名前のファイルに保存します temp_file
  3. という名前のプログラムを実行します。これthing2は、キーボードの人物temp_fileが入力としての内容を入力したことを装います。

しかし、それは不格好なので、彼らはそれを行う簡単な方法としてパイプを作成しました。thing1 | thing2と同じことをするthing1 > temp_file && thing2 < temp_file

コメントで質問する詳細を提供するために編集:

場合>も、両方の「プログラムに渡す」と「ファイルに書き込め」しようとした、それは両方向の問題を引き起こす可能性があります。

最初の例:ファイルに書き込もうとしています。上書きしたい名前のファイルが既に存在します。ただし、ファイルは実行可能です。おそらく、入力を渡してこのファイルを実行しようとします。出力を新しいファイル名に書き込んでから、ファイルの名前を変更する必要があります。

2番目の例: Florian Dieschが指摘したように、同じ名前の別のコマンドがシステムのどこかにある場合(実行パスにある場合)現在のフォルダにその名前のファイルを作成するつもりだった場合は、行き詰まってしまいます。

第三に、コマンドを誤って入力しても、そのコマンドが存在しないことを警告することはありません。今、あなたがタイプすればls | gerp log.txtそれはあなたに言うでしょうbash: gerp: command not found>両方を意味する場合、それは単にあなたのために新しいファイルを作成します(そして、それがどうするべきかを知らないことを警告しますlog.txt)。


ありがとうございました。あなたthing1 > temp_file && thing2 < temp_fileはパイプでもっと簡単にやれると言った。しかし、コマンドやなどに>これを行うために演算子を再利用しないのはなぜですか?なぜ余分な演算子ですか?thing1 > thing2thing1thing2|
ジョン

1
「出力を取得してファイルに書き込む」は、「出力を取得して別のプログラムに渡す」とは異なるアクションです。私は...私の答えに多くの思考を編集します
デヴィッド・オニール

1
@JohnThreepwood彼らは異なる意味を持っています。lessたとえば、という名前のファイルに何かをリダイレクトしたい場合はどうしますか?thing | lessそして thing > less、彼らは別のことを行うよう、完全に異なっています。あなたが提案するものはあいまいさを作成します。
ダークホッグ

「thing1> temp_file」は単に「thing1 | tee temp_file」の構文上の砂糖であると言うのは正確ですか?Tシャツについて知って以来、私はほとんどリダイレクトを使用しません。
Sridhar Sarnobat 14年

2
@ Sridhar-Sarnobatいいえ、teeコマンドは何か違うことをします。 tee画面(stdoutファイルの両方に出力を書き込みます。リダイレクトはファイルのみを実行します。
デビッドオニール14年

22

の意味がリダイレクトを使用するのがはるかに難しく、よりエラーが発生しやすいfoo > barという名前のコマンドがあるかどうかに依存する場合bar:ファイルにリダイレクトするたびに、最初に宛先ファイルのような名前のコマンドがあるかどうかを確認する必要がありました。


これはbar$PATHenv変数の一部であるディレクトリに書き込む場合にのみ問題になります。/ binのような場所にいる場合は、otが問題になる可能性があります。ただし、それでも、bar実行可能権限を設定する必要があるため、シェルは実行可能ファイルを見つけるだけでbarなく、実際に実行できるようにチェックします。また、既存のファイルの上書きに関する懸念がある場合は、nocloberシェルオプションを使用して、リダイレクト中の既存のファイルの上書きを防ぐ必要があります。
セルギーKolodyazhnyy

13

UnixおよびLinuxシステム管理ハンドブックから:

リダイレクション

シェルは、シンボル<、>、および>>を、コマンドの入力または出力をfileに、またはfileから再ルーティングする指示として解釈します

パイプ

あるコマンドのSTDOUT を別のコマンドのSTDINに接続するには、|を使用します。一般にパイプとして知られるシンボル。

だから私の解釈は次のとおりです。コマンドするコマンドの場合、パイプを使用します。ファイルに出力する場合、またはファイルから出力する場合は、リダイレクトを使用します。


12

2つの演算子には重大な違いがあります。

  1. ls > log.txt ->このコマンドは、出力をlog.txtファイルに送信します。

  2. ls | grep file.txt->このコマンドは、パイプ(|)を使用してlsの出力をgrepコマンドに送信します。grepコマンドは、前のコマンドで指定された入力でfile.txtを検索します。

最初のシナリオを使用して同じタスクを実行する必要がある場合、次のようになります。

ls > log.txt; grep 'file.txt' log.txt

その|ため、出力を他のコマンドに送信するためにパイプ(with )が使用さ>れ、出力をファイルにリダイレクトするためにリダイレクト(with )が使用されます。


3

2つの間に大きな構文上の違いがあります。

  1. リダイレクトはプログラムへの引数です
  2. パイプは2つのコマンドを分離します

次のようなリダイレクトを考えることができますcat [<infile] [>outfile]。これcat <infile >outfileは、順序は重要ではないことを意味しcat >outfile <infileます。はと同じです。リダイレクトと他の引数を混在させることもできます。両方とも完全に問題cat >outfile <infile -bありcat <infile -b >outfileません。また、複数の入力または出力をつなぎ合わせることができます(入力は順番に読み込まれ、すべての出力は各出力ファイルに書き込まれます)cat >outfile1 >outfile2 <infile1 <infile2。リダイレクトのターゲットまたはソースは、ファイル名またはストリームの名前(少なくともbashでは&1など)のいずれかです。

しかし、パイプは1つのコマンドを別のコマンドから完全に分離します。それらを引数と混在させることはできません。

[command1] | [command2]

パイプは、command1から標準出力に書き込まれたすべてを取得し、command2の標準入力に送信します。

パイピングとリダイレクトを組み合わせることもできます。例えば:

cat <infile >outfile | cat <infile2 >outfile2

1番目catはinfileから行を読み取り、同時に各行をoutfileに書き込み、2番目に送信しcatます。

2番目ではcat、標準入力は最初にパイプ(infileの内容)から読み取り、次にinfile2から読み取り、各行をoutfile2に書き込みます。これを実行すると、outfileはinfileのコピーになり、outfile2にはinfileの後にinfile2が含まれます。

最後に、「here string」リダイレクト(bashファミリのみ)とバックティックを使用して、実際にあなたの例に本当に似たようなことをします:

grep blah <<<`ls`

と同じ結果が得られます

ls | grep blah

しかし、リダイレクションバージョンは最初にlsのすべての出力を(メモリ内の)バッファーに読み込んでから、そのバッファーを一度に1行ずつgrepにフィードしますが、パイプバージョンではlsから各行が出現すると、その行をgrepに渡します。


1
Nitpick:あるfdを別のfdにリダイレクトする場合、リダイレクトの順序は重要です。echo yes 1>&2 2>/tmp/blah; wc -l /tmp/blah; echo yes 2>/tmp/blah 1>&2; wc -l /tmp/blahさらに、ファイルへのリダイレクトは最後のリダイレクトのみを使用します。echo yes >/tmp/blah >/tmp/blah2のみに書き込み/tmp/blah2ます。
ムル14

2
リダイレクトは、実際にはプログラムへの引数ではありません。プログラムは、出力がどこに行くか(または入力がどこから来るか)を知りません。これは、プログラムを実行する前に物事を整理する方法をbashに伝えるための単なる方法です。
アロイスマーダル

3

注:回答は、このサイトおよびunix.stackexchange.comのピアによる調査と回答の読み取りを通じて蓄積された、これらのメカニズムの最新の私自身の理解を反映しており、今後更新されます。質問をするか、コメントの改善を提案することをheしないでください。また、straceコマンドを使用してシェルでsyscallがどのように機能するかを確認することもお勧めします。また、内部やsyscallの概念に怖がらないでください。シェルがどのように物事を行うのかを理解するためにそれらを知ったり使用したりする必要はありませんが、それらは間違いなく理解に役立ちます。

TL; DR

  • |パイプはディスク上のエントリに関連付けられていないため、ディスクファイルシステムのinode番号はありません(ただし、カーネル空間のpipefs仮想ファイルシステムにinode があります) iノード。
  • パイプはlseek()「使用できないため、コマンドは一部のデータを読み取って巻き戻すことはできませんが、リダイレクトする>場合<、または通常はファイルがlseek()有効なオブジェクトであるため、コマンドは好きなようにナビゲートできます。
  • リダイレクションは、ファイル記述子の操作であり、多くの場合があります。パイプには2つのファイル記述子しかありません-1つは左コマンド用、もう1つは右コマンド用です
  • 標準ストリームとパイプのリダイレクトは両方ともバッファリングされます。
  • パイプにはほとんどの場合フォークが関係するため、プロセスのペアが関係します。リダイレクト-常にではありませんが、どちらの場合も、結果のファイル記述子はサブプロセスに継承されます。
  • パイプは常にファイル記述子(ペア)、リダイレクトを接続します-パス名またはファイル記述子を使用します。
  • パイプはプロセス間通信の方法ですが、リダイレクトは開いているファイルまたはファイルのようなオブジェクトに対する単なる操作です
  • どちらもdup2()、実際のデータフローが発生するファイル記述子のコピーを提供するために、フードの下にsyscallを採用しています。
  • リダイレクトはexec組み込みコマンドで「グローバルに」適用できます(thisおよびthisを参照)。したがって、exec > output.txtすべてのコマンドを実行するoutput.txtとそれ以降に書き込みが行われます。|パイプは、現在のコマンドにのみ適用されます(これは、単純なコマンド、サブシェルのような、seq 5 | (head -n1; head -n2)または複合コマンドを意味します。
  • ファイルでリダイレクションが行われるecho "TEST" > fileと、などのecho "TEST" >> file両方open()がそのファイルでsyscallを使用し(を参照)、ファイル記述子を取得してに渡しdup2()ます。パイプ|pipe()dup2()syscall のみを使用します。

  • 実行されるコマンドに関しては、パイプとリダイレクトはファイル記述子にすぎません-盲目的に書き込むか、内部で操作するファイルのようなオブジェクト(予期しない動作を引き起こす可能性があります; aptたとえば、stdoutに書き込みさえしない傾向があります)リダイレクトがあることがわかっている場合)。

前書き

これら2つのメカニズムがどのように異なるかを理解するには、それらの本質的な特性、2つの背後にある歴史、およびCプログラミング言語のルーツを理解する必要があります。実際、ファイル記述子が何であるかdup2()、およびpipe()システムコールがどのように機能するかを知ることは不可欠lseek()です。シェルは、これらのメカニズムをユーザーに抽象化する方法として意図されていますが、抽象化よりも深く掘り下げると、シェルの動作の本質を理解するのに役立ちます。

リダイレクションとパイプの起源

Dennis Ritcheの記事「Prophetic Petroglyphs」によると、パイプはMulticsオペレーティングシステムで作業していたときのMalcolm Douglas McIlroyによる1964年の内部メモに由来しています。見積もり:

私の最も強い懸念を簡単に言えば:

  1. ガーデンホースのようなプログラムを接続するいくつかの方法が必要です。別の方法でデータをマッサージする必要が生じたときに、別のセグメントにねじを締めてください。これもIOの方法です。

明らかなことは、その時点ではプログラムはディスクに書き込むことができましたが、出力が大きい場合は非効率的でした。Unix PipelineビデオでのBrian Kernighanの説明を引用するには:

まず、1つの大きな大規模なプログラムを作成する必要はありません-すでに仕事の一部を実行している既存の小さなプログラムを持っています...もう1つは、処理しているデータの量が次の場合に収まらない可能性があることですファイルに保存しました...幸運だったら、これらのディスクがあった時代に戻ったのを思い出してください、もし運がよければ、メガバイトまたは2つのデータを...パイプラインは出力全体をインスタンス化する必要がありませんでした。

したがって、概念的な違いは明らかです。パイプは、プログラムが互いに対話するメカニズムです。リダイレクト-基本レベルでファイルに書き込む方法です。どちらの場合も、シェルはこれらの2つのことを簡単にしますが、ボンネットの下には多くのことが行われています。

さらに深く:システムコールとシェルの内部動作

ファイル記述子の概念から始めます。ファイル記述子は、基本的に開いているファイル(ディスク上のファイル、メモリ内のファイル、または匿名ファイル)を表し、整数で表されます。2つの標準データストリーム (stdin、stdout、stderr)は、それぞれファイル記述子0、1、および2です。彼らはどこから来たのか ?さて、シェルコマンドでは、ファイル記述子は親-シェルから継承されます。そして、それは一般的にすべてのプロセスに当てはまります-子プロセスは親のファイル記述子を継承します。以下のためのデーモンは、すべての継承されたファイル記述子を閉じ、および/または他の場所にリダイレクトするのが一般的です。

リダイレクトに戻ります。それは本当に何ですか?これは、コマンドのファイル記述子を準備するようシェルに指示し(コマンドの実行前にシェルによってリダイレクトが行われるため)、ユーザーが提案した場所をポイントするメカニズムです。出力リダイレクトの標準定義

[n]>word

その[n]ファイルディスクリプタの数があります。するとecho "Something" > /dev/null、1が暗示され、そしてecho 2> /dev/null

内部では、これはdup2()システムコールを介してファイル記述子を複製することによって行われます。取りましょうdf > /dev/null。シェルは、どこの子プロセスを作成しますdf実行されますが、それが開きますその前に、/dev/nullファイルディスクリプタ#3として、およびdup2(3,1)ファイルディスクリプタ3のコピーを作成し、コピーが1になります。これは、発行されますあなたは2つのファイルを持っているか知っているfile1.txtfile2.txtcp file1.txt file2.txt同じファイルを2つ作成しますが、それらを個別に操作できますか?ここでも同じことが起こっています。多くの場合、あなたは実行する前に、ことがわかりますbashでしょうdup(1,10)でコピーファイルディスクリプタ#1を作るためにstdout(とそのコピーは#10のfdになります)、後でそれを復元するために。重要なのは、組み込みコマンドを検討する際に注意することです(シェル自体の一部であり、ファイルは/binどこにもありません)または非対話型シェルの単純なコマンド、シェルは子プロセスを作成しません。

そして、のようなものが[n]>&[m]あり[n]&<[m]ます。これはファイル記述子の複製です。これはdup2()、シェル構文の場合と同じメカニズムであり、ユーザーが便利に利用できます。

リダイレクトに関して注意すべき重要なことの1つは、その順序が固定されていないことですが、シェルがユーザーの希望を解釈する方法にとって重要です。以下を比較してください。

# Make copy of where fd 2 points , then redirect fd 2
$ ls -l /proc/self/fd/  3>&2  2> /dev/null
total 0
lrwx------ 1 user user 64 Sep 13 00:08 0 -> /dev/pts/0
lrwx------ 1 user user 64 Sep 13 00:08 1 -> /dev/pts/0
l-wx------ 1 user user 64 Sep 13 00:08 2 -> /dev/null
lrwx------ 1 runner user 64 Sep 13 00:08 3 -> /dev/pts/0
lr-x------ 1 user user 64 Sep 13 00:08 4 -> /proc/29/fd

# redirect fd #2 first, then clone it
$ ls -l /proc/self/fd/    2> /dev/null 3>&2
total 0
lrwx------ 1 user user 64 Sep 13 00:08 0 -> /dev/pts/0
lrwx------ 1 user user 64 Sep 13 00:08 1 -> /dev/pts/0
l-wx------ 1 user user 64 Sep 13 00:08 2 -> /dev/null
l-wx------ 1 user user 64 Sep 13 00:08 3 -> /dev/null
lr-x------ 1 user user 64 Sep 13 00:08 4 -> /proc/31/fd

シェルスクリプトでのこれらの実用的な用途は多岐にわたります。

その他多数。

配管pipe()dup2()

それでは、パイプはどのように作成されますか?pipe()syscallを介してpipefd、タイプint(整数)の2つの項目で呼び出される配列(別名リスト)を入力として受け取ります。これらの2つの整数はファイル記述子です。pipefd[0]パイプの読み出し側となり、pipefd[1]書き込み終了となります。そうでdf | grep 'foo'grepのコピーを取得するpipefd[0]dfのコピーを取得しますpipefd[1]。しかし、どのように?もちろん、dup2()syscall の魔法で。このdf例でpipefd[1]は、#4があるとしましょう。したがって、シェルは子を作成し、do dup2(4,1)(私のcp例を覚えてい ますか?)、do execve()を実際に実行しdfます。当然、dfはファイル記述子#1を継承しますが、もはや端末を指していないことを認識しませんが、実際にはfd#4(実際にはパイプの書き込み側)です。当然、grep 'foo'ファイル記述子の数が異なる場合を除き、同じことが起こります。

さて、興味深い質問:fd#1だけでなくfd#2もリダイレクトするパイプを作成できますか?はい、実際、それ|&はbashで行われます。POSIX標準ではdf 2>&1 | grep 'foo'、そのための構文をサポートするためにシェルコマンド言語が必要ですbash|&、同様にサポートされています。

重要なのは、パイプが常にファイル記述子を処理することです。が存在するFIFOか、名前付きパイプ、ディスク上のファイル名を持っており、あなたはファイルとしてそれを使用してみましょう、しかし、パイプのように振る舞います。しかし、|パイプのタイプは匿名パイプと呼ばれるものです-実際には2つのオブジェクトが接続されているだけなので、ファイル名はありません。ファイルを扱っていないという事実も重要な意味を持っています。パイプは使用できませんlseek()メモリまたはディスク上のファイルは静的です-プログラムはlseek()syscallを使用してバイト120にジャンプし、次にバイト10に戻り、最後まで転送できます。パイプは静的ではありません-連続しているため、パイプから取得したデータを巻き戻すことはできませんlseek()。これにより、一部のプログラムがファイルまたはパイプから読み取りを行っているかどうかを認識できるため、効率的なパフォーマンスのために必要な調整を行うことができます。言い換えれば、prog私がしなければ検出することができますcat file.txt | progprog < input.txt。その実際の作業例はtailです。

パイプのその他の2つの非常に興味深い特性は、Linuxで4096バイトのバッファーがあり、実際にLinuxソースコードで定義されているファイルシステムがあることです!それらはデータを渡すための単なるオブジェクトではなく、データ構造そのものです!実際、パイプとFIFOの両方を管理するpipefsファイルシステムが存在するため、 パイプにはそれぞれのファイルシステムにiノード番号があります。

# Stdout of ls is wired to pipe
$ ls -l /proc/self/fd/  | cat  
lrwx------ 1 user user 64 Sep 13 00:02 0 -> /dev/pts/0
l-wx------ 1 user user 64 Sep 13 00:02 1 -> pipe:[15655630]
lrwx------ 1 user user 64 Sep 13 00:02 2 -> /dev/pts/0
lr-x------ 1 user user 64 Sep 13 00:02 3 -> /proc/22/fd
# stdin of ls is wired to pipe
$ true | ls -l /proc/self/fd/0
lr-x------ 1 user user 64 Sep 13 03:58 /proc/self/fd/0 -> 'pipe:[54741]'

Linuxでは、パイプはリダイレクトと同じように単方向です。Unixライクな実装では、双方向パイプがあります。シェルスクリプトの魔法がありますが、Linuxでも双方向パイプを作成できます。

参照:


2

他の答えに追加するために、微妙な意味の違いもあります-例えば、パイプはリダイレクトよりもすぐに閉じます:

seq 5 | (head -n1; head -n1)                # just 1
seq 5 > tmp5; (head -n1; head -n1) < tmp5   # 1 and 2
seq 5 | (read LINE; echo $LINE; head -n1)   # 1 and 2

最初の例では、最初の呼び出しがhead終了すると、パイプを閉じてseq終了するため、2番目の呼び出しには入力がありませんhead

2番目の例では、headは最初の行を消費しますが、headがそれ自身のstdin pipeを閉じると、ファイルは次に使用する呼び出しのために開いたままになります。

3番目の例はread、パイプのクローズを回避するために使用する場合、サブプロセス内で引き続き使用できることを示しています。

そのため、「ストリーム」はデータをシャントするもの(stdinなど)であり、どちらの場合も同じですが、パイプは2つのプロセスからのストリームを接続します。類似点と相違点の両方の原因を確認できます。

PS私がそうであるようにそれらの例に興味があり、そして/または驚いているなら、あなたtrapはプロセスがどのように解決するかを見るためにさらに掘り下げることができます、例えば:

(trap 'echo seq EXITed >&2' EXIT; seq 5) | (trap 'echo all done' EXIT; (trap 'echo first head exited' EXIT; head -n1)
echo '.'
(trap 'echo second head exited' EXIT; head -n1))

時々、最初のプロセスが終了する前1に印刷されることがあります。

またexec <&-、リダイレクションからのストリームを閉じてパイプの動作を近似するのに使用するのも興味深いことがわかりました(エラーはありますが)。

seq 5 > tmp5
(trap 'echo all done' EXIT
(trap 'echo first head exited' EXIT; head -n1)
echo '.'
exec <&-
(trap 'echo second head exited' EXIT; head -n1)) < tmp5`

「headへの最初の呼び出しが終了すると、パイプを閉じます」これは、実際には2つの理由で不正確です。1つ(head -n1; head -n1)は2つのコマンドを持つサブシェルであり、それぞれがパイプの読み取り終了を記述子0として継承するため、サブシェルAND各コマンドはそのファイル記述子を開きます。2番目の理由は、strace -f bash -c 'seq 5 | (head -n1; head -n1) '。したがって、最初のヘッドはファイル記述子のコピーのみを閉じます
Sergiy Kolodyazhnyy

3番目の例も不正確です。これreadは、最初の行のみを消費するためです(1バイトで1あり、改行です)。seq合計10バイトで送信(5つの数字と5つの改行)。したがって、パイプバッファーには8バイトが残っています。そのため、2番目がhead機能します。パイプバッファーにはまだデータがあります。ところで、0バイトが読み取られた場合にのみヘッドが終了します。ちょっとしたようにhead /dev/null
Sergiy Kolodyazhnyy

説明をありがとう。私seq 5 | (head -n1; head -n1)は最初の呼び出しでパイプを空にするので、パイプはまだ開いた状態で存在していますが、2番目の呼び出しのデータがないことを正しく理解していheadますか?だから、パイプとリダイレクトの動作の違いは、headがパイプからすべてのデータを引き出しますが、ファイルハンドルからは2行だけだからです?
ジュリアンデバル

そのとおりです。そして、それはstrace私が最初のコメントで与えたコマンドで見ることができるものです。リダイレクトでは、tmpファイルがディスク上にあり、シーク可能になりlseek()ます(syscall を使用するため、コマンドはファイルを最初から最後まで自由にジャンプできます。しかし、パイプはシーケンシャルでシーク可能ではありません。ジョブが最初にすべてを読み取ることで、またはファイルが大きい場合-を経由してRAMにそれのいくつかをマップmmap()コール私はかつて自分をしました。tailPythonで、まったく同じ問題に遭遇した。
Sergiy Kolodyazhnyy

また、パイプの読み取り終了(ファイル記述子)が最初にサブシェルに渡され(...)、サブシェルが内部の各コマンドに独自のstdinのコピーを作成することを覚えておくことも重要(...)です。したがって、技術的には同じオブジェクトから読み取られます。最初head は、それが独自の標準入力から読み取っていると考えています。第二にhead、独自の標準入力があると考えています。しかし、実際には、それらのfd#1(stdin)は同じfdのコピーであり、パイプの最後に読み込まれます。また、答えを投稿しましたので、物事を明確にするのに役立つかもしれません。
セルギーKolodyazhnyy

1

今日、Cでこれに問題があります。基本的に、Pipeは、に送信された場合でも、リダイレクトするセマンティクスも異なりstdinます。本当に違いがあるので、パイプは以外の場所に行くべきだと思うstdinので、それをstdin呼び出してstdpipe(任意の差分を作るために)さまざまな方法で処理できます。

このことを考慮。あるプログラムの出力を別のプログラムにパイピングすると、ファイルがあることを示しているにもかかわらずfstat、ゼロを返すように見えます。ファイルをリダイレクトする場合、これは当てはまりません(少なくともdebian 、およびvanillaおよびubuntu 、vanillaでは。st_sizels -lha /proc/{PID}/fdwheezystretchjessie14.0416.04

cat /proc/{PID}/fd/0リダイレクションを使用すると、何度でも繰り返し読むことができます。パイプを使用してこれを行うと、タスクを連続して2回実行すると、同じ出力が得られないことがわかります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.