タイムアウト付きでシェルからfifo / pipeに書き込みます
-
05-07-2019 - |
質問
名前付きパイプを介して通信するシェルプログラムのペアがあります。リーダーは開始時にパイプを作成し、終了時に削除します。
ライターは、リーダーが読み取りを停止してからパイプを削除するまでの間にパイプへの書き込みを試みることがあります。
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
しかし、これはちょっと厄介です。これをよりきれいに行うためのシェル組み込みコマンドまたはコマンドがありますか?
解決 3
このペアのプログラムは、名前付きパイプの代わりにUnixドメインソケットを使用してPerlで書き直された後、はるかにうまく機能します。この質問の特定の問題は、一方の端が死ぬと接続がハングする代わりに消えるため、完全になくなりました。
他のヒント
UNIXの「標準」これに対処する方法は、 Expect を使用することです。これには、timed-runの例が付属しています。一定の時間。
Expectはスクリプティングに対して驚くべきことを学ぶことができます。 Tclが気に入らない場合は、 Python Expect モジュールもあります。
この質問は定期的に発生します(検索で見つけることができませんでしたが)。タイムアウトコマンドとして使用する2つのシェルスクリプトを作成しました。1つは標準入力を読み取るもの用、もう1つは標準入力を読み取らないもの用です。これは悪臭を放ち、私はCプログラムを書くつもりでしたが、私はまだそれに気づいていません。 Cで timeout
コマンドを書くことを絶対にお勧めします。しかし、一方、コマンドが標準入力を読み取るとハングする2つのシェルスクリプトのうち、より単純なものを次に示します。
#!/bin/ksh
# our watchdog timeout in seconds
maxseconds="$1"
shift
case $# in
0) echo "Usage: `basename <*>` <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
他のスクリプトは、 http://www.cs.tuftsでオンラインになっています。 edu /〜nr / drop / timeout 。
trap 'kill $(ps -L $! -o pid=); exit 30' 30
echo kill -30 $ 2\>/dev/null | at $1 2>/dev/null
shift; eval $@ &
wait