gravação para fifo / tubo de shell, com tempo limite
-
05-07-2019 - |
Pergunta
Eu tenho um par de programas shell que falar ao longo de um pipe nomeado. O leitor cria o pipe quando ele começa, e remove-lo quando ele sai.
Às vezes, o escritor vai tentar escrever para o tubo entre o momento em que o leitor pára a leitura eo tempo que ele remove o tubo.
reader: while condition; do read data <$PIPE; do_stuff; done
writer: echo $data >>$PIPE
reader: rm $PIPE
quando isso acontece, o escritor irá travar sempre tentando abrir o tubo para a escrita.
Existe um limpa maneira de dar-lhe um tempo limite, de modo que ele não vai ficar pendurado até matou manualmente? Eu sei que posso fazer
#!/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
mas este é o tipo de icky. Existe um builtin shell ou comando para fazer isso de forma mais limpa (sem quebrar o compilador C)?
Solução 3
Este par de programas funciona muito mais bem depois de estar em Perl utilizando soquetes de domínio Unix em vez de pipes nomeados re-escrita. O problema particular nesta questão foi embora completamente, já que, se / quando uma extremidade morre a conexão desaparece em vez de enforcamento.
Outras dicas
A maneira UNIX "padrão" de lidar com isso é usar Esperar , que vem com timed- executar exemplo:. executar um programa apenas por um determinado período de tempo
Esperar pode fazer maravilhas para scripting, vale a pena aprender. Se você não gosta Tcl, há um Python Esperar módulo também.
Esta questão surge periodicamente (embora eu não poderia encontrá-lo com uma pesquisa). Eu escrevi dois shell scripts para usar como comandos de tempo limite: um para as coisas que lê da entrada padrão e outro para as coisas que não lêem a entrada padrão. Isso fede, e eu tenho sentido de escrever um programa C, mas eu não ter chegado a cerca de ainda. Eu definitivamente recomendo escrever um comando timeout
em C uma vez por todas. Mas, enquanto isso, aqui está o mais simples dos dois scripts shell, que trava se o comando lê a entrada padrão:
#!/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
O outro roteiro está online em http: //www.cs.tufts. edu / ~ nr / gota / timeout .
trap 'kill $(ps -L $! -o pid=); exit 30' 30
echo kill -30 $$ 2\>/dev/null | at $1 2>/dev/null
shift; eval $@ &
wait