説明のために、次のスクリプトwrapcat.sh
(猫のラッパー)について考えてみます。組み込みLinux2.6ボックス内のbusybox(ash)で実行されます。
#!/bin/sh
cat $1
特定の状況下では、このスクリプトは常に正常に終了するとは限りません。例えば、私が走るとき
$./wrapcat.sh /proc/pid/cmdline
一部のpid
については、コマンドを待っているシェルにドロップされることがあります。リターン等を押すと終了します。
私の診断では、cat
が何らかのシグナルによって中断されているため、スクリプトが正常に終了しません(-eオプションを設定していないため)。だから私はcat
コマンドのリターンステータスに興味があります。スクリプトを次のように変更します。
#!/bin/sh
cat $1
echo $? # echo the exit status
ただし、スクリプトが正常に終了しない場合、終了ステータスはエコーされません。 $?
の終了ステータスがエコーされない理由(より具体的には、特に/proc/pid/cmdline
をキャッチするときにクリーンな終了が常に発生しない理由)を知りたいのですが。 /proc/pid/auxv
と/proc/pid/environ
をキャットするときにも同じことが時々発生します。ソース内の関連関数: http://lxr.linux.no/#linux+v2.6.31/fs/proc/base.c#L25
これを「修正」する方法を必ずしも知りたくはありません。おそらく、前述の-eオプションを設定することで修正できます。
注:UbuntuやDebianのようなものではおそらくこれを再現できないでしょう-この現象はbusybox ash、cat、または組み込みLinuxに固有である可能性があります。ただし、スクリプト内で実行される子プロセスsleep
を中断することで、シミュレートできます。
例えば。スクリプトを実行するs.sh
:
#!/bin/sh
sleep 1000
echo $?
次に、$./s.sh
、ctrl-z、bg
、disown %1
を実行して、独自のプロセスでスクリプトを実行します。 ps
には、次のようなものが表示されます。
15610 pts/35 00:00:00 s.sh
15611 pts/35 00:00:00 sleep
先に進んでkill -2 15611
を実行すると(childプロセスで)、次のようになります。
$ 130 # the exit status, which does get printed
command line waits for next command without clean exit
出力を誤って解釈しています。
これらのファイル(cmdline、environ ...)が改行文字で終了していないだけです。
したがって、たとえば、/proc/pid/cmdline
にxxx
が含まれている場合、cat /proc/pid/cmdline
はxxx
を出力しますが、改行文字(端末の分野が出力時にCRLFに変換する)がないため、カーソルは行頭(CR)に戻ることも、1つ下がること(LF)もありません。
次に、終了すると、シェルは次のコマンドを待つためのプロンプトを出力するため、次のように表示されます。
xxx$
echo $?
がある場合、次のようになります。
xxx0
$
ファイルにxxx
を超えるファイルが含まれていると、混乱が生じる可能性があります。
改行文字が欠落しているときに改行文字を追加する場合は、cut
の代わりにcat
を使用できます。
#! /bin/sh -
cut -b1- < "$1"
$ 1が空の文字列と評価された場合、cat
がstdinからの読み取りを待機していることがわかります。次に、Ctrl-DまたはCtrl-Cを押して猫を閉じ、スクリプトを続行できるようにする必要があります。特にこの問題については、私は試してみます
cat "${1:-/dev/null}"
そのため、$ 1が空または設定されていない場合、少なくともcatは、処理する内容が有限である有効なファイル名を取得します。