2010-11-23 7 views
12

Estoy envolver una aplicación fastcgi en una escritura del golpe como éste:Kill escritura del golpe foreground niños cuando llegue una señal

#!/bin/bash 
# stuff 
./fastcgi_bin 
# stuff 

Como fiesta sólo se ejecuta trampas para señales cuando termina la secuencia de comandos de primer plano que no puedo acaba kill -TERM scriptpid porque la aplicación fastcgi se mantendrá viva.
He intentado enviar el binario para el fondo:

#!/bin/bash 
# stuff 
./fastcgi_bin & 
PID=$! 
trap "kill $PID" TERM 
# stuff 

Pero si lo hago de esta manera, al parecer, la entrada y salida estándar no se redirigen adecuadamente porque no se conecta con lighttpds mod_fastgi, la versión en primer plano funciona.

EDIT: He estado buscando en el problema y esto se debe a que redirige fiesta/dev/null a la entrada estándar cuando un programa se puso en marcha en el fondo, por lo que cualquier forma de evitar esto debería resolver mi problema también.

¿Alguna pista sobre cómo solucionar esto?

Respuesta

15

Hay algunas opciones que vienen a la mente:

  • Cuando un proceso se inicia desde un script de shell, ambos pertenecen al mismo grupo de procesos. Matar al proceso principal deja vivos a los niños, por lo que se debe matar a todo el grupo de procesos. Esto puede lograrse pasando el PGID negado (ID del grupo de procesos) para matar, que es el mismo que el PID del padre. EJ: kill -TERM -$PARENT_PID

  • No ejecutar el binario como un niño, pero reemplazando el proceso de escritura de con exec. Sin embargo, pierde la capacidad de ejecutar cosas , ya que exec reemplaza por completo el proceso principal por .

  • No mate el proceso de script de shell, pero el binario de FastCGI. Luego, en el script, examine el código de retorno y actúe en consecuencia. por ejemplo: ./fastcgi_bin || exit -1

Dependiendo de cómo mod_fastcgi maneja los procesos de trabajo, sólo la segunda opción podría ser viable.

+0

que fue mi primer pensamiento también: 'killpg'. – tchrist

+2

'exec' era exactamente lo que necesitaba! Gracias –

+0

También podría considerar buscar el otro script. Esto le permite ejecutarse en el mismo proceso sin eliminar el resto del script actual. (por ejemplo, ./fastcgi.bin) (es decir, ) – GinoA

-1

Puedes hacerlo con un coprocess.

Edit: bueno, los coprocesos son procesos en segundo plano que pueden tener stdin y stdout open (porque bash prepara fifos para ellos). Pero aún necesita leer/escribir en esos fifos, y la única primitiva útil para eso es bash's read (posiblemente con un tiempo de espera o un descriptor de archivo); nada lo suficientemente robusto para un cgi. Pensándolo bien, mi consejo sería no hacer esto en bash. Hacer el trabajo extra en el fastcgi, o en un envoltorio http como WSGI, sería más conveniente.

+0

¿Podría profundizar en esto? –

1

No tengo idea si esta es una opción para ti o no, pero como tienes una recompensa, estoy asumiendo que puedes buscar ideas que están fuera de la caja.

¿Podría volver a escribir el script bash en Perl? Perl tiene varios métodos para administrar procesos secundarios. Puede leer perldoc perlipc y más detalles en los módulos centrales IPC::Open2 y IPC::Open3.

No sé cómo esto se relacionará con lighttpd, etc. o si hay más funcionalidad en este enfoque, pero al menos le da más flexibilidad y algo más para leer en su búsqueda.

0

no estoy seguro consigo totalmente su punto, pero aquí es lo que traté y el proceso parece ser capaz de gestionar la trampa (llámese trap.sh):

#!/bin/bash 

trap "echo trap activated" TERM INT 
echo begin 
time sleep 60 
echo end 

iniciarlo:

./trap.sh & 

y jugar con él (sólo uno de esos comandos a la vez):

kill -9 %1 
kill -15 %1 

O empezar en primer plano:

./trap.sh 

Y se interrumpe con control-C.

Parece que funciona para mí. ¿Qué exactamente no funciona para usted?

+0

Ambos 'kill' con un especificador de trabajo y señales de terminal se envían a todo el grupo de procesos, por lo que tanto el shell como' sleep'. Por cierto, ¿por qué intentas atrapar 'SIGKILL'? – jilles

+0

@jilles: es suficiente, he editado la publicación para que coincida con su comentario. – asoundmove

0

Puede anular la </dev/null implícito para un proceso de fondo mediante la reorientación de la entrada estándar a sí mismo, por ejemplo:

sh -c 'exec 3<&0; { read x; echo "[$x]"; } <&3 3<&- & exec 3<&-; wait' 
1

de escribir este guión hace sólo unos minutos para matar a una escritura del golpe y todos sus hijos ...

#!/bin/bash 
# This script will kill all the child process id for a given pid 
# based on http://www.unix.com/unix-dummies-questions-answers/5245-script-kill-all-child-process-given-pid.html 

ppid=$1 

if [ -z $ppid ] ; then 
    echo "This script kills the process identified by pid, and all of its kids"; 
    echo "Usage: $0 pid"; 
    exit; 
fi 

for i in `ps j | awk '$3 == '$ppid' { print $2 }'` 
do 
    $0 $i 
    kill -9 $i 
done 

Asegúrese de que el guión es ejecutable, o se obtendrá un error en el $ 0 $ i

0

trate de mantener el original stdin usin g ./fastcgi_bin 0<&0 &:

#!/bin/bash 
# stuff 
./fastcgi_bin 0<&0 & 
PID=$!./fastcgi_bin 0<&0 & 
trap "kill $PID" TERM 
# stuff 


# test 
#sh -c 'sleep 10 & lsof -p ${!}' 
#sh -c 'sleep 10 0<&0 & lsof -p ${!}' 
Cuestiones relacionadas