Sinal não recebido pelo script executado usando sh -c

4

Eu tenho um script que dorme por 3 minutos antes de executar um comando demorado. Eu quero que o script saia se ele receber SIGINT somente enquanto estiver dormindo, e não quando estiver executando o comando de longa execução. Isso é para garantir que apenas uma instância do comando demorado esteja em execução em um determinado instante de tempo.

Aqui está o myscript.sh :

#!/bin/bash

trap 'exit' INT
sleep 180 &
wait
trap '' INT

# Long running command
/etc/init.d/myd sync 

Veja como eu executo:

kill -INT 'pgrep myscript.sh' 2>/dev/null; ! pgrep -x "myscript.sh" > /dev/null && /opt/my/scripts/myscript.sh &

Agora isso funciona como esperado, mesmo em execuções subsequentes. ou seja,

  1. Ele executa o script, se não estiver em execução.

  2. Pára o script (envia SIGINT ) e o reinicia, se o script estiver em execução, mas ainda não tiver executado o comando de longa execução.

  3. Não faz nada se o script estiver sendo executado e executando o comando de longa execução.

No entanto, quando executo o mesmo liner usando sh -c :

sh -c 'kill -INT 'pgrep myscript.sh' 2>/dev/null; ! pgrep -x "myscript.sh" > /dev/null && /opt/my/scripts/myscript.sh &'

Ele inicia o script se ele não estava sendo executado anteriormente, mas parece que não consegue parar o script.

Eu não entendo porque isso não está funcionando.

    
por user3490458 17.05.2017 / 09:38

1 resposta

0

Então tive que modificar um pouco seus caminhos de comando, mas acredito que isso seja o que você quer. Mas primeiro, as modificações que eu precisava fazer no seu script:

#!/bin/bash
# Make sure we know when the trap fires. 
trap 'printf "quiting with return code %d\n" "$?"; exit' INT
sleep 180 &
wait
trap '' INT

# Long running command
/usr/bin/sleep 86400

Depois, consegui fazer o que você queria, alterando seu segundo comando assim:

sh -c 'set -x; (exec kill --verbose -INT $(pgrep myscript.sh) 2>/dev/null); ! pgrep -x "myscript.sh" > /dev/null && /tmp/myscript.sh &'

E uma vez que você tenha verificado a execução dessa maneira funciona como esperado, você pode remover a instrução printf da primeira armadilha no script e executar o comando da seguinte forma:

 sh -c '(exec kill -INT $(pgrep myscript.sh) 2>/dev/null); ! pgrep -x "myscript.sh" > /dev/null && /tmp/myscript.sh &'

Sem os parens na primeira instrução no comando acima, o que faz com que seja executado em um subshell, o processo sh será substituído pelo processo kill e a segunda instrução não será executada.

    
por 24.02.2018 / 01:39