単純なPythonスクリプトがあります。
#!/usr/bin/python
import os, sys
sys.stderr.write('I am %s' % os.getpid())
sys.stderr.flush()
print "hello"
sys.stderr.write('I am done')
Bashでこのスクリプトを実行し、標準出力をFIFOにリダイレクトすると、次のようになります。
$ mkfifo fifo
$ /pyscript > fifo
奇妙なことは、FIFOを読み取る前に次のようなことです。
「I am (PID)」というメッセージは表示されません。
使用されたスクリプトを表示できません。
ps -ef
そして使用ラソフ、そんな人はいないと思います。先入選出ファイルオープン!
FIFOを読むとすぐにstderrに書き込んだ2つのメッセージがすぐに表示されます。
何が問題なの?
背景:私はFIFOを生成し、ここに「hello」を書くテストを書いています。その後、テストを実行し、SUTを期待します。いいえIEで読みます。ただファイルを無視してください。私はこれを試しましたが、mkfifo test_fifo; /bin/echo hello > test_fifo &; run_the_test; killall echo
驚くべきことに、そのecho
プロセスは存在しませんでした!このようなテストの後、どのように「クリーンアップ」(除外)する必要がありますかrm test_fifo
?
答え1
シェルは、ファイルのリダイレクトが正常に完了するまでプログラムを実行しません。このコマンドはpyscript > fifo
シェルをフォークしてから開こうとします。これは、一部のプロセスがすでに読み取り用にfifo
開いている場合にのみ成功します。fifo
それまで、サブシェルはパイプライン待機状態にあります。
$ (sleep 10;ps -l -t pts/0)&
[1] 2574
$ pyscript > fifo
F S UID PID PPID WCHAN TTY CMD
0 S 1000 2554 2535 wait pts/0 bash //interactive shell
1 S 1000 2574 2554 wait pts/0 bash //fork of shell, parent of sleep and ps
1 S 1000 2576 2554 pipe_w pts/0 bash //fork of shell, waiting to open fifo
0 R 1000 2577 2574 - pts/0 ps
答え2
パイプまたはFIFOの両端を同時に開く必要があります。プロセスが作成されていないパイプまたはFIFOファイルから読み取られた場合(おそらくすべてがファイルが閉じられたか終了したため)、読み取り時にファイルの終わりが返されます。読み取りプロセスなしでパイプまたはFIFOへの書き込みはエラー条件と見なされ、SIGPIPE信号を生成し、信号が処理またはブロックされるとエラーコードEPIPEで失敗します。
http://www.gnu.org/software/libc/manual/html_node/Pipes-and-FIFOs.html