2

名前付きパイプを介して通信するシェルプログラムのペアがあります。リーダーは、開始時にパイプを作成し、終了時にパイプを削除します。

場合によっては、ライターは、リーダーが読み取りを停止してからパイプを削除するまでの間にパイプに書き込もうとします。

reader: while condition; do read data <$PIPE; do_stuff; done
writer: echo $data >>$PIPE
reader: rm $PIPE

これが発生すると、ライターは書き込み用のパイプを開こうとして永遠にハングします。

手動で強制終了するまでハングしたままにならないように、タイムアウトを設定するクリーンな方法はありますか?私は私ができることを知っています

#!/bin/sh
# timed_write <timeout> <file> <args>
# like "echo <args> >> <file>" with a timeout

TIMEOUT=$1
shift;
FILENAME=$1
shift;
PID=$$

(X=0; # don't do "sleep $TIMEOUT", the "kill %1" doesn't kill the sleep
 while [ "$X" -lt "$TIMEOUT" ];
 do sleep 1; X=$(expr $X + 1);
 done; kill $PID) &

echo "$@" >>$FILENAME
kill %1

しかし、これはちょっと厄介です。これをよりクリーンに(Cコンパイラを壊さずに)行うためのシェルビルトインまたはコマンドはありますか?

4

4 に答える 4

1

これに対処するUNIXの「標準」の方法は、Expectを使用することです。これには、時間指定実行の例が付属しています。プログラムを指定された時間だけ実行します。

期待することで、スクリプトを作成することができます。学ぶ価値は十分にあります。Tclが気に入らない場合は、PythonExpectモジュールもあります。

于 2009-01-08T04:42:21.663 に答える
1

この質問は定期的に出てきます(検索しても見つかりませんでしたが)。タイムアウト コマンドとして使用する 2 つのシェル スクリプトを作成しました。1 つは標準入力を読み取るもの用、もう 1 つは標準入力を読み取らないもの用です。これは悪臭を放ち、私は C プログラムを書くつもりでしたが、まだそれに慣れていません。Cでコマンドを書くことを絶対にお勧めtimeoutします。ただし、コマンドが標準入力を読み取るとハングする 2 つのシェル スクリプトのうち、単純なものを次に示します。

#!/bin/ksh

# our watchdog timeout in seconds
maxseconds="$1"
shift

case $# in
  0) echo "Usage: `basename $0` <seconds> <command> [arg ...]" 1>&2 ;;
esac

"$@" &
waitforpid=$!

{
    sleep $maxseconds
    echo "TIMED OUT: $@" 1>&2 
    2>/dev/null kill -0 $waitforpid && kill -15 $waitforpid
} &
killerpid=$!

>>/dev/null 2>&1 wait $waitforpid
# this is the exit value we care about, so save it and use it when we
rc=$?

# zap our watchdog if it's still there, since we no longer need it
2>>/dev/null kill -0 $killerpid && kill -15 $killerpid

exit $rc

もう 1 つのスクリプトは、http://www.cs.tufts.edu/~nr/drop/timeoutでオンラインになっています。

于 2009-01-08T00:39:28.877 に答える
0
trap 'kill $(ps -L $! -o pid=); exit 30' 30
echo kill -30 $$ 2\>/dev/null | at $1 2>/dev/null
shift; eval $@ &
wait
于 2016-12-09T18:58:13.930 に答える
0

このプログラムのペアは、名前付きパイプの代わりに Unix ドメイン ソケットを使用して Perl で書き直された後、はるかにうまく機能します。この質問の特定の問題は完全に解消されました。一方の端が停止した場合、ハングする代わりに接続が消えるためです。

于 2009-02-02T16:21:38.757 に答える