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

Foi útil?

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top