Bash maneira de verificar se um processo já está sendo executado em segundo plano (e pular a re-execução com base nisso)?

11

Posso criar uma linha de comando bash que execute apenas um determinado comando se o processo ainda não estiver em execução (em segundo plano)?

Como verifico * se um comando já está sendo executado?

(para que eu possa adicionar o próximo comando &&entre eles, o próximo só será executado se o primeiro for verdadeiro).

*: teste, determine, descubra, descubra

n611x007
fonte
3
ps -ef | grep -v grep | grep "process_name" || run_command_here
Rahul Patil
1
@RahulPatil você pode usar apenas em pgrep "process_name"vez deps | grep | grep
rush
hmm, eu esqueço que ..: D
Rahul Patil
1
Por que você não usa um arquivo de "bloqueio" e, quando você inicia pela segunda vez, ele será iniciado somente quando o arquivo de bloqueio desaparecer.
BitsOfNix
melhor maneira de verificar se existe um processo: stackoverflow.com/questions/3043978/...
Trevor Boyd Smith

Respostas:

3

Eu usei essa técnica de tempos em tempos:

$ pgrep <process name> || <process name>

Antes pgrep, costumava ser feito desta maneira:

$ ps -eaf | grep -q <[p]rocess name> || <process name>

exemplo

A parte com o [p]faz para que o resultado grepnão se encontre.

$ ps -eaf | grep -q [s]leep || sleep 10
slm
fonte
2

Isso pode ser complicado, porque você pode ter instâncias separadas do mesmo processo que vivem independentemente. Por exemplo, servidores atendendo em portas diferentes ou serviços executando como usuários diferentes. Para distinguir entre essas instâncias, você precisa atribuir a cada uma delas uma tag exclusiva. A tag geralmente é um arquivo, mas pode ser um soquete local no espaço para nome abstrato, uma porta TCP etc. - qualquer identificador exclusivo serve. Quando a tag é um arquivo, pode ser um arquivo comum que contém um ID do processo (um arquivo de pid) ou um pipe ou soquete nomeado no qual o arquivo está ouvindo etc. Idealmente, a tag é um terminal de comunicação que permite que os clientes se conectem para esse processo.

Cada um desses tipos diferentes de tags resulta em uma maneira diferente de verificar se a instância que você está procurando está em funcionamento. Por exemplo, com um soquete de arquivo local, tente conectar-se a ele e inicie o processo se não houver nenhum processo atendendo nesse soquete. Se a tag for um pidfile, verifique se há um processo com esse ID de processo, mas tenha cuidado, pois é frágil, pois, se o processo morreu, pode haver um processo não relacionado que reutilizou seu ID. Lembre-se de que, se dois clientes tentarem acessar o processo em um curto espaço de tempo, eles poderão achar que o processo não existe e tentarem iniciá-lo; proteger adequadamente dessa condição de corrida pode ser complicado.

É mais fácil gerenciar instâncias quando todas elas são iniciadas pelo mesmo processo do supervisor, e esse processo do supervisor detecta quando as instâncias morrem e reagem de acordo. Muitos programas de monitoramento de serviço que podem fazer isso.

Se o programa não responder a um ponto de extremidade de comunicação conhecido e não for gerenciado por um programa supervisor, a tag do pobre homem é um pidfile: um arquivo contendo o ID do processo. Ao iniciar o processo, escreva o pid em um arquivo com um nome previamente combinado. Quando você precisar que o processo exista, leia o pidfile e veja se existe um processo com esse pid. Quando você finalizar o processo, apague o arquivo pid. O problema mais saliente de um arquivo de pid não supervisionado é que, se o processo morrer, seu pid poderá ser reutilizado por algum processo não relacionado. Você deve pelo menos verificar o nome do processo ou o executável do processo para garantir que esteja falando com o processo correto. Muitas variantes do unix possuem um comando pgrep :pgrep SOMENAME lista os processos cujo nome contém SOMENAME como uma substring, com opções adicionais para limitar a um usuário específico, exigir uma correspondência exata, alterar qual das várias noções possíveis de "nome do processo" é usada etc.

Gilles 'SO- parar de ser mau'
fonte
1

Você pode usar esta abordagem:

if [[ -z $(ps -C appname -opid=) ]]; then
    appname && secondapp
fi
jasonwryan
fonte
1

Outras opções:

  • pgrep -xq processname
    • Corresponde apenas aos 15 primeiros caracteres no GNU / Linux
    • Não inclui ancestrais no OS X
  • ps -eo comm= | sed 's|.*/||' | grep -xq processname
    • Corresponde apenas aos 15 primeiros caracteres no GNU / Linux
    • sed 's|.*/||' remove partes do nome do diretório no OS X

Em GNU / Linux ps -o commtrunca os nomes de comandos para 15 caracteres e pgrepe ps -Ccorresponder apenas os primeiros 15 caracteres.

ps -C (match command names) não é suportado no OS X.

No OS X ps -o commimprime os caminhos absolutos dos comandos e ps -co commapenas imprime os nomes dos comandos. No GNU, ps -o commapenas imprime nomes de comandos e -ctem um significado diferente.

O pgrep do OS X não inclui processos ancestrais (como bash, Terminal ou launchd) sem -a. O pgrep do GNU os inclui por padrão e não suporta -a.

grep -xe pgrep -xnão implica -F, portanto, use -Fxse o nome do processo puder conter caracteres regex.

Lri
fonte
-C não está disponível no meu cygwin quer :)
n611x007
1

Sinto muito, mas todas essas soluções não oferecem suporte ao contab, pois a mesma linha de comando aparecerá duas vezes no resultado 'ps'.

Então aqui está o meu:

## Test pour voir si le même script tourne déjà
## Un fichier .pid est utilisé pour stocké le numéro de process
## Si le pid est en train de tourner alors on sort.
lock_file=$0".pid"
[ -r $lock_file ] && read pid <$lock_file
if [ "$pid" -gt 1 ] && [ `ps --no-headers -p "$pid" | wc -l` -gt 0 ] ; then
    echo "WARNING : le process $pid tourne deja : $0"
    ps -edf | grep `basename $0` | grep -v grep
    echo "WARNING : Arrêt de cette instance ($$)."
    exit 7
fi
echo $$ >$lock_file
Francis
fonte
O que você sente muito? O que é contab? Você quer dizer verificar dentro de um cronemprego?
Anthon
0

With Bash

#!/usr/bin/env bash

[[ $# -eq 0 ]] && { echo -e "Usage:\t\t $0 <Process_name>  <Command here>"; exit 1;  }

ifnotrun(){
        local p=$1
        if ! ps -C "$1" -opid=
        then
                cmd=($@)
                echo ${cmd[@]:1}
        else
                echo "Process \"$p\" Already Running.."
                exit 1
        fi

}

ifnotrun $*

Nota: - remova echose a saída estiver ok.

Rahul Patil
fonte
0

Vou explicar o caso em que você executa o comando no beckgreoud. O "$!" salve o PID do último processo em segundo plano. Portanto, você pode usá-lo para encontrá-lo nas tabelas de processos, seguindo as respostas acima:

sleep 4 &
ps -ef | grep -w  $!  ...

O comando interno "jobs" - tente o seguinte:

sleep 4&
J=`jobs`
while [ "$J" ]; do
        sleep 1
        jobs # This line flush the jobs' bufer.
        J=`jobs`
done

Em relação à opção "&&"

Em vez de &&, use o comando wait. No exemplo a seguir, myproc2 não será executado até que myproc1 termine:

myproc1 &
wait
myproc2
Udi
fonte
0

Obtenha o estado do seu processo:

ps -lp $(pgrep <YOUR_PROCESS_NAME>) | tail -1 | awk '{print $11}'

Referência:

D    uninterruptible sleep (usually IO)
R    running or runnable (on run queue)
S    interruptible sleep (waiting for an event to complete)
T    stopped, either by a job control signal or because it is being traced
W    paging (not valid since the 2.6.xx kernel)
X    dead (should never be seen)
Z    defunct ("zombie") process, terminated but not reaped by its parent

Por exemplo, usei-o para reproduzir ou pausar condicionalmente meu processo sox em uma sessão tmux:

/usr/local/bin/tmux if-shell -t sox "[ $(ps -lp $(pgrep sox) | tail -1 | awk '{print $11}') == 'T' ]" \
  'send -t sox "fg" Enter' \
  'send -t sox C-z'
Jose Alban
fonte
-1

Você pode usá-lo dentro de um script:

if [ `ps -ef | grep "script.sh" | grep -v grep | wc -l` -gt 1 ] ; then
echo "RUNNING...."
else
echo "NOT RUNNING..."
fi
Pravs
fonte