Como evitar matar o processo errado em um script bash?

3

Estou escrevendo um script básico que gera dois processos filhos e será executado por um trabalho cron a cada hora. Na verdade, ele está executando um comando rsync para um servidor remoto e a associada ssh connection.

Se o comando rsync ou script demorar muito, eu gostaria de matá-lo e seus processos filhos, mas dar a ele um período de tolerância primeiro. O script é executado a cada hora, mas as próximas duas tentativas verão que uma instância anterior do script está sendo executada e sairá antes de tentar iniciar uma transferência. A terceira tentativa subseqüente matará a instância original, ainda em execução, antes de iniciar uma nova transferência.

Eu decidi controlar isso escrevendo em um arquivo PID, a primeira instância grava seu PID no arquivo, as próximas duas tentativas gravam seu PID no arquivo antes de sair. A terceira tentativa mata a primeira e, em seguida, substitui o arquivo PID pelo novo PID. Qualquer conclusão bem-sucedida limpa o arquivo PID. Para matar todas as crianças, decidi usar o PGID da instância de script original com a qual obtenho:

previous_pid=$(head -n1 "$pid_file")
previous_groupid=$(ps -hp "$previous_pid" -o pgid:1)

Em seguida, mate-o com:

kill -- -"$previous_pid"

Minha preocupação é que possa haver uma condição em que o script original tenha de alguma forma morrido sem limpar o arquivo PID, e que o PID esteja sendo reutilizado também reutilizando o PGID, então acabarei matando um processo completamente não relacionado. Como posso evitar isso?

    
por Arronical 31.03.2016 / 10:55

1 resposta

3

Obtenha o script para se matar. Por exemplo, tenha algo parecido com isso no início do seu script:

kill_myself () {
    while sleep 1
    do
        if [[ -f /tmp/kill-myself ]]
        then
            rm /tmp/kill-myself
            kill -- -
        fi
    done
}

kill_myself $$ &

Agora, quando chegar a hora:

touch /tmp/kill-myself

Você pode personalizar isso, para que cada instância do script tenha seu próprio arquivo de eliminação, que você registraria em algum lugar. Então você usará esse arquivo para matar aquela instância específica do script.

Outra maneira: você provavelmente poderia usar pgrep / pkill para correspondência mais precisa. Eles podem ler de um arquivo pid, combinar com o nome do comando e argumentos, etc.

Algo parecido com o seguinte apenas matará processos que tenham o mesmo nome do seu script (supondo que você o tenha chamado como script-name ou /path/to/script-name ):

pkill -g "$previous_groupid" script-name

Isso não funcionará se você usar bash script-name . Ou apenas para matar o comando rsync , que provavelmente deve fazer com que seu script saia depois disso:

pkill -g "$previous_groupid" rsync
    
por muru 31.03.2016 / 11:32