Verifique o processo se o mesmo estiver em execução

4

Existe um script ou uma forma no linux em que, quando tento executar um script / processo de shell, se o mesmo estiver em execução, ele avisa que o mesmo está sendo executado e sairá do contrário, continuará.

    
por user60216 01.03.2014 / 13:28

6 respostas

6

Você pode usar este forro para fazer o que quiser:

$ pgrep script.bash && echo "already running" || ( ./script.bash & )

Exemplo

Digamos que eu tenha este script:

$ cat script.bash 
#!/bin/bash

echo "Hello World"
sleep 10

Se usarmos nosso liner único:

$ pgrep script.bash && echo "already running" || ( ./script.bash & )
Hello World
$

Nós o rodamos novamente:

$ pgrep script.bash && echo "already running" || ( ./script.bash & )
10197
already running
$

Esperando 10 segundos e rodando novamente, funciona novamente:

$ pgrep script.bash && echo "already running" || ( ./script.bash & )
Hello World
$
    
por 01.03.2014 / 14:10
5

Observe que essa resposta é orientada para um script de autoverificação, para verificar manualmente se um processo está em execução antes de tentar executá-lo a partir da linha de comando, consulte resposta do slm .

A maneira mais fácil é usar pgrep , se estiver disponível:

if pgrep "$0" >/dev/null
then
  echo "$0 is already running" 2>&1
  exit 1
fi

Se não, você pode usar uma combinação de ps e grep :

if ps -Ao comm | grep -q "^$0\$"
then
  echo "$0 is already running" 2>&1
  exit 1
fi

É mais robusto usar um arquivo de bloqueio, já que é sempre possível que o processo esteja sendo executado com um nome diferente. Aqui está um exemplo usando flock :

lockfile=/var/lock/mprog
{
  if ! flock -n 9
  then
    echo "Unable to lock $lockfile, exiting" 2>&1
    exit 1
  fi

  # do stuff here

} 9>"$lockfile"
    
por 01.03.2014 / 14:00
1

Existem muitas maneiras de fazer isso. Eu prefiro que o script impeça de rodar as mesmas cópias armazenando seu pid.

Um método conveniente é pidof

$ pidof -x /bin/yourscript || /bin/yourscript  

com ps

$ ps aux|grep -q /bin/yourscript || /bin/yourscript

auto-verificação

#!/bin/sh

NAME=$(basename $0)

if ps -p 'cat /var/run/$NAME".pid' >/dev/null 2>&1; then
   echo "script already running"
   exit 1
fi

echo $$ > /var/run/$NAME".pid"

...
rm /var/run/$NAME".pid"

existem muitos outros scripts. Por exemplo, solo

    
por 01.03.2014 / 14:06
0

O fato de que fazer algo parecido com isso de forma confiável no Unix em geral é impossível foi uma das coisas que desencadeou o desenvolvimento de ferramentas como systemd (ele usa o recurso cgroups específico do Linux para bloquear processos e, assim, mantê-los sob rígido controle, incluindo a reinicialização conforme necessário). Você pode juntar algo usando ps (1) ou pgrep (1), guardando um PID em um arquivo e verificando, e assim por diante. Mas todos esses estão sujeitos a corridas, fraudes ou erros simples.

Você deve repassar suas necessidades e ver como isso é crítico se der errado, como isso é repetitivo (vale a pena automatizar, ou é algo feito de vez em quando?), o quão interessante é um alvo para invasores em potencial e assim por diante.

    
por 02.03.2014 / 03:17
0

Eu tive um problema parecido com isso. A solução mais fácil que encontrei foi verificar um arquivo check_running.txt no diretório. se o arquivo existir; então o script já está rodando, então inicialize o arquivo, e no final do seu script rm o arquivo do diretório. Dessa forma, contanto que o arquivo esteja no diretório, o script está sendo executado.

if [[ -f check_running.txt ]]; then 
  echo "already running"
  exit 
fi

touch check_running.txt 
...
...
...
rm check_running.txt 

Acredito que isso também pode ser implementado apenas com uma variável de sinalizador.

    
por 09.05.2018 / 09:12
0

Usando um diretório de bloqueio:

#!/bin/sh

lockdir=${TMPDIR:-/tmp}/mylock

if ! mkdir "$lockdir" 2>/dev/null; then
    exit 1
fi

trap 'rmdir "$lockdir" 2>/dev/null' EXIT HUP INT TERM

# The rest of code goes here.

Usar um diretório de bloqueio é mais seguro do que usar um arquivo de bloqueio. Se estiver usando um arquivo, você teria que fazer um teste separado para a existência do arquivo antes de criá-lo. No intervalo entre essas duas operações, outra instância do script pode tentar fazer o mesmo. O utilitário mkdir fornece uma operação atômica "create-if-not-exist".

Ressalva: O código acima não detecta se o script já está em execução, mas se o diretório de bloqueio existe. Se o script terminar de forma anormal, por ex. por ser morto por SIGKILL , o diretório de bloqueio será deixado para trás e nenhuma nova instância do script poderá ser iniciada.

A seguinte variação tenta detectar um diretório de bloqueio que foi deixado para trás por um script finalizado anormalmente. Apenas detecta o bloqueio que sobrou, mas não tenta fazer qualquer limpeza (isto introduziria novas condições de corrida).

#!/bin/sh

lockdir=${TMPDIR:-/tmp}/mylock

if { read pid <"$lockdir/pid" && ! kill -0 "$pid"; } 2>/dev/null then
    printf 'Detected left-over lock "%s"\n' "$lockdir" >&2
    exit 1
fi

if ! mkdir "$lockdir" 2>/dev/null; then
    echo 'Could not get lock' >&2
    exit 1
fi

printf '%d\n' "$$" >"$lockdir/pid"

trap '{ rm "$lockdir/pid" && rmdir "$lockdir"; } 2>/dev/null' EXIT HUP INT TERM

# The rest of code goes here.

O comando ! kill -0 "$pid" será verdadeiro se $pid não referir-se a um ID de processo alocado atualmente para um processo em execução.

    
por 09.05.2018 / 09:36