質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

Q&A

解決済

1回答

3754閲覧

yes | rm * の動作の仕方が謎です

motisen

総合スコア92

bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

0グッド

0クリップ

投稿2017/06/05 14:51

yes | rm * の謎。

yes | rm * でファイルを一気に消したりするのですが、終了時の動きが気になっています。
なぜrmが終わったタイミングでyesもおわるのでしょうか。

パイプでつなぐ場合、プロセスは一気に立ち上げられ、左側のプロセスが終われば、右側のプロセスが終わるという認識です。
しかし、 yes | rm * は逆になります。右側(rm)が終われば、 左側(yes) が終わります。

###試したこと
パイプの右側が終わっても、左側が終わらないことを、試してみました。

↓作成したシェルスクリプトです。

[piyo@hoge tmp]# tail test* ==> test1.sh <== sleep 1 echo "exit test1" >&2 ==> test2.sh <== sleep 10 echo "exit test2" >&2

※パイプに渡さないように標準エラー出力に出しています。

↓試行結果です。

[piyo@hoge tmp]# ./test1.sh | ./test2.sh exit test1 exit test2 [piyo@hoge tmp]# ./test2.sh | ./test1.sh exit test1 exit test2

両方ともtest2.sh が終わったタイミングでシェル操作が可能になりました。
やはり、左が終わってから右が終わっているように思えます。

どなたか仕組みを教えていただけないでしょうか。よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

yesは、rm -iが終了したタイミングで終わるのでは無いです。
rm -iが終了すると、パイプを読み取るプロセスが無くなるので、書き込みプロセスがパイプに書こうとした段階で、そのプロセスにSIGPIPEというシグナルが送られます。特にこのシグナルに対してのの動作を変えていない場合、それでプロセスが終了します。パイプへの書き込みがあるまではそのまま実行が続きます。
プログラムによってはSIGPIPEを受け取ると、Broken Pipeというメッセージを出してから終了する物もあります。あるいは、シグナルを無視して続行する物もあるかも。

yes | rm -i *が終了した直後に、echo ${PIPESTATUS[*]}すると、141 0と表示されます。
141yesの終了コードです。141 - 128 = 13 で、シグナル13つまりSIGPIPEで終了したと言うことです。
(番号とシグナル名の対応はkill -lで表示できます)

そもそもでいうと、yes | rm -i *-iを付けなければ良いので、無駄なyesです。
aliasで、alias rm="rm -i"などしている場合は、\rm *とすればいいです。

Bash

1$ tail test?.sh 2==> test1.sh <== 3trap 'echo パイプがちぎれた1 >&2; exit' 13 4sleep 1 5echo 1 6echo "exit test1" >&2 7 8==> test2.sh <== 9trap 'echo パイプがちぎれた2 >&2; exit' 13 10sleep 10 11echo 2 12echo "exit test2" >&2 13$ ./test1.sh | ./test2.sh 14exit test1 152 16exit test2 17$ ./test2.sh | ./test1.sh 181 19exit test1 20パイプがちぎれた2

#追記

パイプでつなぐ場合、プロセスは一気に立ち上げられ、左側のプロセスが終われば、右側のプロセスが終わるという認識です。

これにコメントし忘れました。
左側のプロセスが終わった段階で、パイプの入り口がクローズされ、右側のプロセスでのパイプからの読みとりは、パイプに溜まっていた物を読み切った段階でEOFになります。標準入力がEOFになると終了するというプログラムであれば、終了します。標準入力がEOFになっても動き続けるように書かれていれば、動き続けます。

つまり、パイプを使ったプロセスの連携は、あくまでwrite/readに関してのみで、SIGPIPEEOFでプロセスが終わるかどうかはプログラム依存です。

投稿2017/06/05 15:35

編集2017/06/05 15:52
otn

総合スコア84505

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

motisen

2017/06/06 01:06

大変わかりやすい解説でした。 パイプ使用時の動作も理解できました。 ありがとうございます。 またrm にはrm -i とエイリアスが設定されてました。失礼しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問