14
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

名前付きパイプからリダイレクトする時のワナ

Last updated at Posted at 2013-12-28

いきなり問題

さて問題です。次のコードを実行した時、どうなるでしょうか?

問題
$ mkfifo "HOGEPIPE"
$ { cat < "HOGEPIPE" >/dev/null; } &
$ killall cat
  1. catコマンドプロセスが終了され、サブシェルとなっている括弧プロセスが終了する。(その結果、[1]+ Done { cat < "HOGEPIPE"; }などのメッセージが出る)

  2. catコマンドプロセスが見つからず、killallコマンドがエラーを返す。

  3. 名前付きパイプ"HOGEPIPE"が使えなくなり、一旦削除して作り直すしかなくなる。

正解

1番、と見せかけて、実は2番です。あたりましたか?

理由

2番の「killallコマンドがエラーを返す」とは一体どういうことでしょう?catコマンドが名前付きパイプからデータが流れてくるのを今か今かと待ち構えているのではないのでしょうか。

じつはこの時、catコマンドはまだ起動していないのです。いくら待とうがダメです。後で"HOGEPIPE"にデータを流し込むその時、はじめて起動するのです。

名前付きパイプが空のうちは、シェルはリダイレクション先のプロセスを起動しない

では名前付きパイプにまだデータが流し込まれていない時、
{ cat < "HOGEPIPE" >/dev/null; } &
はどういう状態なのでしょうか?

上記のサブシェル{ cat < "HOGEPIPE" >/dev/null; }自体は立ち上がっています。しかしそのサブシェルが、catコマンドをまだ起動していないのです。リダイレクションなので、サブシェルがまず名前付きパイプ"HOGEPIPE"を開こうとしますが、その結果まだデータが到来していないのでサブシェル自身がブロック状態になってしまっているのです。

その様子を観察してみましょう。冒頭の「問題」のコマンドを打ち込んだ後に、さらに次のコマンドを打ち込んでみてください。今、この議論に関係するプロセスのみが表示されます。

関係するプロセスを列挙
$ ps -Ao pid,ppid,command | egrep $$'|'cat | egrep -v grep'|'ps
27488 27487 -bash()今コマンド打ち込んでいるシェルのプロセス
27673 27488 -bash()catを呼びだすサブシェルのプロセス

このように、コマンドを打ちこんでいるシェルのプロセスと、{ cat < "HOGEPIPE" >/dev/null; }のサブシェルの2つしか居ません。

では、パイプにデータを流し始めてみたらどうなるか見てみましょう。まずは次のコマンドを打ちこみ、データを流し始めてみてください。

名前付きパイプにデータを流し始める
$ yes > "HOGEPIPE" &

そして、もう一度関係するプロセスを列挙してみましょう。

改めて関係するプロセスを列挙
$ ps -Ao pid,ppid,command | egrep $$'|'cat | egrep -v grep'|'ps
27488 27487 -bash()今コマンド打ち込んでいるシェルのプロセス
27673 27488 -bash()catを呼びだすサブシェルのプロセス
27674 27673 cat()上記のサブシェルから呼びだされたcat
27686 27488 yes()名前付きパイプ経由でcatにデータを送っているyes
$ killall yes # 余計な負荷を掛けぬよう、確認後、yesはすぐに止めましょう

というわけでようやくcatコマンドが起動しましたね。

起動しないのはリダイレクションで受け取る場合だけ

ただし、次のようにして入力リダイレクション表記を使わない場合はちゃんとkillできます。

冒頭の「問題」を入力リダイレクション無しでやり直し
$ mkfifo "HOGEPIPE"
$ { cat "HOGEPIPE" >/dev/null; } &
$ killall cat

理由は、最初に名前付きパイプ"HOGEPIPE"を開くのがサブシェルでななく、catコマンドに任せられるからです。

14
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?