¿Por qué SIGSTOP no funciona dentro de la session de la pantalla?

Considere la siguiente secuencia de commands:

#!/bin/bash OFILE='log' echo 'ok' > ${OFILE} kill -SIGSTOP $$ echo 'after stop' > ${OFILE} 

En un shell interactivo, el script se detiene y el resultado es ok . Sin embargo, si se inicia como

 screen -d -m ./test.sh 

la salida es after stop . ¿La pantalla maneja la señal? ¿Cómo suspender un process en una session de pantalla?

Probablemente el process de pantalla está reiniciando el process detenido bash. Intenté seguir (enviando la señal SIGSTOP a ambos processs):

test.sh

 #!/bin/bash OFILE='log' echo 'ok' > ${OFILE} echo 'screen pid ' $(screen -list | grep sc_test | cut -f1 -d'.' | sed 's/\W//g') >> ${OFILE} echo 'test.sh pid ' $$ >> ${OFILE} kill -SIGSTOP $(screen -list | grep sc_test | cut -f1 -d'.' | sed 's/\W//g') kill -SIGSTOP $$ echo 'after stop' >> ${OFILE} 

command de pantalla

 screen -dmS sc_test ./test.sh 

file de logging

 ok screen pid 4453 test.sh pid 4454 

pantallas de listdo

 screen -list There is a screen on: 4453.sc_test (11/05/2015 10:45:20 AM) (Detached) 1 Socket in /var/run/screen/S-root. 

El examen del código fuente de GNU screen-4.0.2 mostró que la pantalla verifica si sus processs secundarios están detenidos y luego intenta reanudarlos con SIGCONT. Aquí hay una parte relevante de la screen.c :

 1561 if (WIFSTOPPED(wstat)) 1562 { 1563 debug3("Window %d pid %d: WIFSTOPPED (sig %d)\n", p->w_number, p->w_pid, WSTOPSIG(wstat)); .... 1578 /* Try to restart process */ 1579 Msg(0, "Child has been stopped, restarting."); 1580 if (killpg(p->w_pid, SIGCONT)) 1581 kill(p->w_pid, SIGCONT); 1582 } 

Parece que este comportamiento no se puede cambiar con una opción o mediante un file de configuration. La solución sugerida para detener el process de pantalla podría tener efectos secundarios indeseables. Un mejor enfoque es ocultar el process detenido de la pantalla. Para un script bash esto se puede hacer con una subshell:

 #!/bin/bash ( OFILE='log' echo 'ok' > ${OFILE} kill -SIGSTOP ${BASHPID} echo 'after stop' > ${OFILE} ) 

Para otros shells, podría no ser tan sencillo, por ejemplo, para tcsh:

 #!/bin/tcsh (\ set OFILE='log' ;\ echo 'ok' > ${OFILE} ;\ kill -STOP `exec sh -c 'echo ${PPID}'` ;\ echo 'after stop' > ${OFILE} \ ) 

La diferencia key es el método para get PID de la subshell, más información aquí .

Alternativamente, la secuencia de commands se puede iniciar sin modificación con un script de envoltura :

 #!/bin/bash SCRIPTDIR="$(dirname "$(readlink -f -n "$0")")" ${SCRIPTDIR}/test.sh 

Correr:

 screen -d -m ./wrapper.sh