Вопрос

У меня есть пара программ оболочки, которые общаются по именованному каналу. Считыватель создает канал при запуске и удаляет его при выходе.

Иногда писатель пытается записать в канал между временем, когда читатель прекращает чтение, и временем, когда он удаляет канал.

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)?

Это было полезно?

Решение 3

Эта пара программ работает намного лучше после того, как она была переписана на Perl с использованием доменных сокетов Unix вместо именованных каналов. Конкретная проблема в этом вопросе полностью исчезла, поскольку, если / когда один конец умирает, соединение исчезает, а не зависает.

Другие советы

UNIX " стандарт " способ справиться с этим - использовать Expect , который поставляется с примером запуска по времени: запускать программу только для определенное количество времени.

Expect может творить чудеса со сценариями, которые стоит изучить. Если вам не нравится Tcl, есть также Python Expect .

Этот вопрос периодически возникает (хотя я не смог найти его с помощью поиска). Я написал два сценария оболочки для использования в качестве команд тайм-аута: один для вещей, которые читают стандартный ввод, и другой для вещей, которые не читают стандартный ввод. Это воняет, и я намеревался написать программу на C, но я еще не дошел до этого. Я определенно рекомендую написать команду timeout на C раз и навсегда. Но тем не менее, вот более простой из двух сценариев оболочки, который зависает, если команда читает стандартный ввод:

#!/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 / ~ Н.Р. / падение / тайм-аут .

trap 'kill $(ps -L $! -o pid=); exit 30' 30
echo kill -30 $ 2\>/dev/null | at $1 2>/dev/null
shift; eval $@ &
wait
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top