web-dev-qa-db-ja.com

catを実行した後、Busyboxashスクリプトが正常に終了しません。終了コードを取得できません

説明のために、次のスクリプト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、bgdisown %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
2
user54945

出力を誤って解釈しています。

これらのファイル(cmdline、environ ...)が改行文字で終了していないだけです。

したがって、たとえば、/proc/pid/cmdlinexxxが含まれている場合、cat /proc/pid/cmdlinexxxを出力しますが、改行文字(端末の分野が出力時にCRLFに変換する)がないため、カーソルは行頭(CR)に戻ることも、1つ下がること(LF)もありません。

次に、終了すると、シェルは次のコマンドを待つためのプロンプトを出力するため、次のように表示されます。

xxx$ 

echo $?がある場合、次のようになります。

xxx0
$ 

ファイルにxxxを超えるファイルが含まれていると、混乱が生じる可能性があります。

改行文字が欠落しているときに改行文字を追加する場合は、cutの代わりにcatを使用できます。

#! /bin/sh -
cut -b1- < "$1"
1

$ 1が空の文字列と評価された場合、catがstdinからの読み取りを待機していることがわかります。次に、Ctrl-DまたはCtrl-Cを押して猫を閉じ、スクリプトを続行できるようにする必要があります。特にこの問題については、私は試してみます

cat "${1:-/dev/null}"

そのため、$ 1が空または設定されていない場合、少なくともcatは、処理する内容が有限である有効なファイル名を取得します。

0
glenn jackman