Erro ao manipular no shell script

3

Eu escrevi um script de shell run_script.sh , que inclui uma etapa que cria um arquivo vazio run_script.lck . Toda vez que o script de shell foi chamado pelo cronjob, ele verificará a existência de run_script.lck . Se o bloqueio for presença, isso indica que run_script.sh já está em execução e ainda não foi concluído. O arquivo run_script.lck será excluído no final do programa.

O problema é remover o arquivo de bloqueio quando o script da shell falhou e antes de sair.

Eu escrevi uma linha como esta:

trap "rm -f run_script.lck" EXIT

Mas isso removerá o arquivo de bloqueio em uma condição indesejada como esta:

Eu executo run_script.sh no shell A e ele está em execução, o arquivo de bloqueio foi criado. Então eu o executo novamente no shell B, e ele disse que o script já está rodando e o script será abortado. No entanto, como a armadilha recebeu um sinal EXIT incluindo o sinal do shell B, que está saindo de um script abortado, ele remove o arquivo de bloqueio. E o script no shell A ainda está em execução, mas o bloqueio foi excluído e qualquer um pode chamar outro run_script.sh novamente enquanto já houver um script em execução.

Alguma ideia de como resolver isso?

    
por lamwaiman1988 21.09.2011 / 03:48

3 respostas

4

Para ilustrar a resposta de Ignacio (use o seguinte protocolo: primeiro verifique se existe lockfile e depois instale o trap), você pode resolver o problema assim:

$ cat test2.sh
if [ -f run_script.lck ]; then
  echo Script $0 already running
  exit 1
fi
trap "rm -f run_script.lck" EXIT
# rest of the script ...
    
por 21.09.2011 / 10:14
5

Verifique a presença do bloqueio antes definir o trapping.

    
por 21.09.2011 / 03:49
4

No caminho é definido o trap em erros e deixe sh abortar o script em caso de erros ( set -e ). Por exemplo

$ cat test.sh
set -e
trap "echo foo" ERR
if [ $# == 1 ]; then
  exit 0
fi
false
$ bash test.sh
foo
$ bash test.sh 1
$

(onde $# é o número de argumentos)

No seu script, você só precisa certificar-se de que executa o comando trap quando o script é executado com êxito (ou seja, nenhum travamento acontece, por exemplo, no final do fluxo de programa normal).

set -e significa que cada status de saída desigual 0 encerra a execução do script. Semelhante a isso, com set -u cada uso (provavelmente acidental) de uma variável indefinida termina a execução.

Assim, transferindo essa ideia para o caso de uso original, uma solução poderia ser assim:

$ cat test.sh
set -e
trap "rm -f run_script.lck" ERR
if [ -f run_script.lck ]; then
  echo Script $0 is already running
  exit 1
fi
#
# do all the work ...
#
# no error until now
rm -f run_script.lck
    
por 21.09.2011 / 10:06