Pregunta

Tengo un par de programas shell que hablan sobre una canalización con nombre. El lector crea el canal cuando se inicia y lo elimina cuando sale.

A veces, el escritor intentará escribir en la tubería entre el momento en que el lector deja de leer y la hora en que se quita la tubería.

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

cuando esto suceda, el escritor se colgará para siempre intentando abrir el conducto para escribir.

¿Hay una forma limpia de darle un tiempo de espera, para que no se cuelgue hasta que se elimine manualmente? Sé que puedo hacer

#!/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

pero esto es un poco desagradable. ¿Hay un shell incorporado o un comando para hacerlo de forma más limpia (sin romper el compilador de C)?

¿Fue útil?

Solución 3

Este par de programas funciona mucho mejor después de ser reescrito en Perl usando sockets de dominio Unix en lugar de canales con nombre. El problema particular en esta pregunta desapareció por completo, ya que si / cuando un extremo muere, la conexión desaparece en lugar de colgarse.

Otros consejos

El UNIX " estándar " La forma de lidiar con esto es usar Expect , que viene con un ejemplo de ejecución cronometrada: ejecute un programa por solo una cantidad de tiempo dada.

Esperar puede hacer maravillas para los scripts, vale la pena aprenderlo. Si no te gusta Tcl, también hay un módulo Python Expect .

Esta pregunta surge periódicamente (aunque no pude encontrarla con una búsqueda). He escrito dos scripts de shell para usar como comandos de tiempo de espera: uno para cosas que leen entrada estándar y otro para cosas que no leen entrada estándar. Esto apesta, y he tenido la intención de escribir un programa en C, pero todavía no he llegado a eso. Definitivamente recomiendo escribir un comando de timeout en C de una vez por todas. Pero mientras tanto, aquí está el más simple de los dos scripts de shell, que se cuelga si el comando lee la entrada estándar:

#!/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

El otro script está en línea en 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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top