Comando Linux / Unix para determinar se o processo está em execução?


97

Preciso de um comando shell / bash independente de plataforma (Linux / Unix | OSX) que determine se um processo específico está em execução. por exemplo mysqld, httpd... Qual é a maneira / comando mais simples de fazer isso?

Respostas:


168

Enquanto pidofe pgrepsão ótimas ferramentas para determinar o que está funcionando, ambos são, infelizmente, não disponível em alguns sistemas operacionais. Um fail safe definitivo seria usar o seguinte:ps cax | grep command

A saída no Gentoo Linux:

14484? S 0:00 apache2
14667? S 0:00 apache2
19620? Sl 0:00 apache2
21132? Ss 0:04 apache2

A saída no OS X:

42582 ?? Z 0: 00,00 (smbclient)
46529 ?? Z 0: 00,00 (smbclient)
46539 ?? Z 0: 00,00 (smbclient)
46547 ?? Z 0: 00,00 (smbclient)
46586 ?? Z 0: 00,00 (smbclient)
46594 ?? Z 0: 00,00 (smbclient)

No Linux e no OS X, grep retorna um código de saída para que seja fácil verificar se o processo foi encontrado ou não:

#!/bin/bash
ps cax | grep httpd > /dev/null
if [ $? -eq 0 ]; then
  echo "Process is running."
else
  echo "Process is not running."
fi

Além disso, se você quiser a lista de PIDs, pode facilmente fazer um grep por eles também:

ps cax | grep httpd | grep -o '^ [] * [0-9] *'

Cuja saída é a mesma no Linux e OS X:

3519 3521 3523 3524

A saída do seguinte é uma string vazia, tornando essa abordagem segura para processos que não estão em execução:

eco ps cax | grep aasdfasdf | grep -o '^[ ]*[0-9]*'

Essa abordagem é adequada para escrever um teste de string vazia simples e, em seguida, iterar através dos PIDs descobertos.

#!/bin/bash
PROCESS=$1
PIDS=`ps cax | grep $PROCESS | grep -o '^[ ]*[0-9]*'`
if [ -z "$PIDS" ]; then
  echo "Process not running." 1>&2
  exit 1
else
  for PID in $PIDS; do
    echo $PID
  done
fi

Você pode testá-lo salvando-o em um arquivo (denominado "running") com permissões de execução (chmod + x running) e executando-o com um parâmetro: ./running "httpd"

#!/bin/bash
ps cax | grep httpd
if [ $? -eq 0 ]; then
  echo "Process is running."
else
  echo "Process is not running."
fi

AVISO!!!

Lembre-se de que você está simplesmente analisando a saída, o ps axque significa que, conforme visto na saída do Linux, não é apenas correspondência nos processos, mas também nos argumentos passados ​​para aquele programa. Eu recomendo fortemente ser o mais específico possível ao usar este método (por exemplo ./running "mysql", também corresponderá a processos 'mysqld'). É altamente recomendável usar whichpara verificar um caminho completo sempre que possível.


Referências:

http://linux.about.com/od/commands/l/blcmdl1_ps.htm

http://linux.about.com/od/commands/l/blcmdl1_grep.htm


O processo pode estar em execução, mas interrompido. Portanto, se o objetivo é testar se mysqld ou httpd estão "funcionando" (respondendo), você também deve verificar se ele está parado ou não.
oluc

2
Desculpe, mas embora a resposta esteja certa do ponto de vista semântico, sou totalmente contra tentar encontrar um processo por correspondência de padrões no vetor de arg do processo. Qualquer abordagem desse tipo está fadada ao fracasso mais cedo ou mais tarde (você na verdade admite isso, dizendo que mais verificações são necessárias). Eu adicionei minha própria recomendação em uma resposta separada.
Peter,

6
greptambém vai encontrar-se em execução (por exemplo, ps cax | grep randomnamesempre retornará 0 porque grepachados grep randomname(espero que isso é claro ...) Uma correção é adicionar colchetes ao redor da primeira letra do nome do processo, por exemplo. ps cax | grep [r]andomname.
Kyle G.

ps cax | rev | cut -f1 -d' ' | revirá mostrar apenas a coluna de nome, para facilitar a análise.
Tyzoid

1
ps caxnão pode exibir o nome do comando totalmente. Por exemplo, ele imprime "chromium-browse" em vez de "chromium-browser".
jarno

24

Você DEVE saber o PID!

Encontrar um processo tentando fazer algum tipo de reconhecimento de padrão nos argumentos do processo (como pgrep "mysqld") é uma estratégia que está fadada ao fracasso mais cedo ou mais tarde. E se você tiver dois mysqld em execução? Esqueça essa abordagem. Você PODE acertar temporariamente e PODE funcionar por um ou dois anos, mas então algo acontece que você não tinha pensado.

Apenas o id do processo (pid) é verdadeiramente único.

Sempre armazene o pid ao lançar algo em segundo plano. No Bash, isso pode ser feito com a $!variável Bash. Você vai economizar MUITOS problemas ao fazer isso.

Como determinar se o processo está em execução (por pid)

Portanto, agora a questão é como saber se um pid está sendo executado.

Basta fazer:

ps -o pid = -p <pid>

Este é POSIX e, portanto, portátil. Ele retornará o próprio pid se o processo estiver em execução ou não retornará nada se o processo não estiver em execução. Estritamente falando, o comando retornará uma única coluna, o pid, mas como fornecemos um cabeçalho de título vazio (o que imediatamente precede o sinal de igual) e esta é a única coluna solicitada, o comando ps não usará nenhum cabeçalho. Que é o que queremos porque torna a análise mais fácil.

Isso funcionará em Linux, BSD, Solaris, etc.

Outra estratégia seria testar o valor de saída do pscomando acima . Deve ser zero se o processo estiver em execução e diferente de zero se não estiver. A especificação POSIX diz que psdeve sair> 0 se ocorreu um erro, mas não está claro para mim o que constitui 'um erro'. Portanto, não estou usando essa estratégia pessoalmente, embora tenha quase certeza de que funcionará bem em todas as plataformas Unix / Linux.


1
Exceto que isso não responde à pergunta, que é determinar se um serviço está sendo executado. O PID não será conhecido em tais casos, portanto, essa resposta só é válida se fazer conhecer a PID.
Highway of Life

2
Errado. Todo o meu objetivo com o comentário é dar um passo para trás e dizer que se você primeiro se encontrar na situação em que tem que fazer alguma forma de grep <sometext>encontrar um determinado processo, então você fez algo errado quando iniciou o processo, IMHO. Eu deduzo da pergunta do OP que de fato ele tem controle sobre como o processo é iniciado.
Peterh

2
O "termo" mais correto para a pergunta do OP deveria ser "comando de plataforma cruzada para determinar se um serviço está sendo executado", não é o mesmo sistema executando a verificação, mas um sistema externo, então o PID simplesmente não será conhecido em tudo.
Highway of Life

2
Isso não é infalível. O processo no qual você está interessado pode ter morrido depois que o sistema ficou ativo por tempo suficiente para os PIDs serem encerrados, e outro processo pode ter sido alocado para o mesmo PID que você está verificando. stackoverflow.com/questions/11323410/linux-pid-recycling
claymation

1
@claymation. Ponto justo. No entanto, o método PID ainda é melhor do que a correspondência de padrões em argumentos de processo, pois o conflito de PID é muito mais improvável do que, digamos, iniciar acidentalmente duas instâncias do mesmo serviço. Apenas meus dois centavos. :-)
peterh

15

Na maioria das distribuições Linux, você pode usar pidof(8).

Ele imprimirá os ids de processo de todas as instâncias em execução de processos especificados, ou nada se não houver instâncias em execução.

Por exemplo, no meu sistema (tenho quatro instâncias de bashe uma instância de remminaexecução):

$ pidof bash remmina
6148 6147 6144 5603 21598

Em outros Unices, pgrepou uma combinação de pse grepalcançará a mesma coisa, como outros corretamente apontaram.


+1 pidof httpdfunciona bem no Red Hat 5. Mas no meu Red Hat 4, pidofnão está presente :-(
olibre

Na verdade, esse comando é menos difundido do que eu pensava, editei minha resposta para deixar isso mais claro.
Frédéric Hamidi

Boa resposta limpa, de fato. (em sistemas suportados). Obrigado.
Mtl Dev

7

Isso deve funcionar na maioria dos sabores de Unix, BSD e Linux:

PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep

Testado em:

  • SunOS 5.10 [Daí o PATH=...]
  • Linux 2.6.32 (CentOS)
  • Linux 3.0.0 (Ubuntu)
  • Darwin 11.2.0
  • FreeBSD 9.0-STABLE
  • Red Hat Enterprise Linux ES versão 4
  • Servidor Red Hat Enterprise Linux versão 5

2
+1 Sim, simplesmente ps. Para evitar o segundo grep, sugiro:ps aux | grep [h]ttpd
olibre 02/02/12

Eu não usei o truque dos colchetes aqui para tornar mais fácil colocar uma variável no principal grep.
Johnsyweb

1
Tudo bem;) Acabei de testar no Red Hat AS 4 e Red Hat AP 5. Claro que funciona! Portanto, você pode adicionar à sua lista: Red Hat Enterprise Linux ES versão 4 e Red Hat Enterprise Linux Server versão 5 . Saúde
olibre

@Downvoter: Por quê? O que eu perdi? Pelo que eu posso dizer, a resposta aceita é fazer a mesma pesquisa!
Johnsyweb

6

A maneira mais simples é usar ps e grep:

command="httpd"
running=`ps ax | grep -v grep | grep $command | wc -l`
if [ running -gt 0 ]; then
    echo "Command is running"
else
    echo "Command is not running"
fi

Se o seu comando tem alguns argumentos de comando, então você também pode colocar mais 'grep cmd_arg1' depois de 'grep $ command' para filtrar outros processos possíveis nos quais você não está interessado.

Exemplo: mostre-me se algum processo java com o argumento fornecido:

-Djava.util.logging.config.file = logging.properties

está correndo

ps ax | grep -v grep | grep java | grep java.util.logging.config.file=logging.properties | wc -l

2
Na verdade, o uso ps caxelimina a necessidade de uso grep -v. Assim, por exemplo, você pode usar: ps cax | grep java > /dev/null || echo "Java not running".
Highway of Life

1
Há um erro na 3ª linha. altere "running" para "$ running".
Programador

5

Apenas uma pequena adição: se você adicionar o -csinalizador ao ps, não precisará remover a linha que contém o processo grep grep -vposteriormente. Ie

ps acux | grep cron

é toda a digitação que você precisa em um sistema bsd-ish (isso inclui MacOSX). Você pode deixar de usar o -use precisar de menos informações.

Em um sistema onde a genética do pscomando nativo aponta de volta para SysV, você usaria

ps -e |grep cron

ou

ps -el |grep cron 

para uma lista contendo mais do que apenas pid e nome do processo. Claro, você pode selecionar os campos específicos para imprimir usando a -o <field,field,...>opção.


Como essa resposta é portátil? (Você diz que diferentes formas do comando ps devem ser usadas em diferentes plataformas)
peterh

O ps infelizmente é uma daquelas ferramentas com um conjunto diferente de opções para o mesmo resultado, dependendo de sua ancestralidade. Portanto, a menos que você escreva seu próprio (novamente incompatível com qualquer outra coisa) em torno disso, o caminho a seguir seria conhecer as principais linhas do patrimônio e se adaptar de acordo. É diferente quando você está escrevendo um script - aí você usaria essas diferenças para determinar em qual branch você está e adaptar o comportamento do seu script. Resumindo: você precisa conhecer os dois. Exemplo famoso: o script "configure" de Larry Wall. Citação famosa: Parabéns, você não está comandando a Eunice.
Tatjana Heuser

5

Juntando as várias sugestões, a versão mais limpa que consegui criar (sem o grep não confiável que aciona partes das palavras) é:

kill -0 $(pidof mysql) 2> /dev/null || echo "Mysql ain't runnin' message/actions"

kill -0 não elimina o processo, mas verifica se ele existe e retorna verdadeiro, se você não tiver pidof em seu sistema, armazene o pid ao iniciar o processo:

$ mysql &
$ echo $! > pid_stored

então no script:

kill -0 $(cat pid_stored) 2> /dev/null || echo "Mysql ain't runnin' message/actions"

3

Eu uso pgrep -l httpdmas não tenho certeza se está presente em alguma plataforma ...
Quem pode confirmar no OSX?


Obrigado @Johnsyweb. Você também pode verificar, pidofpor favor? OK, você fez. Obrigado. Portanto, devemos encontrar algo mais funcionando no OSX ... Seu básico ps|greppode ser a única solução ;-)
olibre

1

Você deve saber o PID do seu processo.

Ao iniciá-lo, seu PID ficará gravado na $!variável. Salve este PID em um arquivo.

Em seguida, você precisará verificar se este PID corresponde a um processo em execução. Aqui está um esqueleto de script completo:

FILE="/tmp/myapp.pid"

if [ -f $FILE ];
then
   PID=$(cat $FILE)
else
   PID=1
fi

ps -o pid= -p $PID
if [ $? -eq 0 ]; then
  echo "Process already running."  
else
  echo "Starting process."
  run_my_app &
  echo $! > $FILE
fi

Com base na resposta de peterh. O truque para saber se um determinado PID está em execução está na ps -o pid= -p $PIDinstrução.


0

Esta abordagem pode ser usada caso os comandos 'ps', 'pidof' e rest não estejam disponíveis. Eu pessoalmente uso procfs com muita freqüência em minhas ferramentas / scripts / programas.

   egrep -m1  "mysqld$|httpd$" /proc/[0-9]*/status | cut -d'/' -f3

Uma pequena explicação do que está acontecendo:

  1. -m1 - interrompe o processo na primeira partida
  2. "mysqld $ | httpd $" - grep corresponderá às linhas que terminaram em mysqld OU httpd
  3. / proc / [0-9] * - bash corresponderá à linha que começou com qualquer número
  4. cut - basta dividir a saída por delimitador '/' e extrair o campo 3

0

Isso imprime o número de processos cujo nome de base é "chromium-browser":

ps -e -o args= | awk 'BEGIN{c=0}{
 if(!match($1,/^\[.*\]$/)){sub(".*/","",$1)} # Do not strip process names enclosed by square brackets.
 if($1==cmd){c++}
}END{print c}' cmd="chromium-browser"

Se imprimir "0", o processo não está em execução. O comando assume que o caminho do processo não contém espaço de quebra. Eu não testei isso com processos suspensos ou processos zumbis.

Testado usando gwakcomo awkalternativa em Linux.

Aqui está uma solução mais versátil com alguns exemplos de uso:

#!/bin/sh
isProcessRunning() {
if [ "${1-}" = "-q" ]; then
 local quiet=1;
 shift
else
 local quiet=0;
fi
ps -e -o pid,args= | awk 'BEGIN{status=1}{
 name=$2
 if(name !~ /^\[.*\]$/){sub(".*/","",name)} # strip dirname, if process name is not enclosed by square brackets.
 if(name==cmd){status=0; if(q){exit}else{print $0}}
}END{exit status}' cmd="$1" q=$quiet
}

process='chromium-browser'

printf "Process \"${process}\" is "
if isProcessRunning -q "$process" 
 then printf "running.\n"
 else printf "not running.\n"; fi

printf "Listing of matching processes (PID and process name with command line arguments):\n"
isProcessRunning "$process"

0

Aqui está minha versão. Recursos:

  • verifica o nome exato do programa (primeiro argumento da função). a pesquisa por "mysql" não corresponderá ao executar "mysqld"
  • procura argumentos do programa (segundo argumento da função)

roteiro:

#!/bin/bash

# $1 - cmd
# $2 - args
# return: 0 - no error, running; 1 - error, not running
function isRunning() {
    for i in $(pidof $1); do
        cat /proc/$i/cmdline | tr '\000' ' ' | grep -F -e "$2" 1>&2> /dev/null
        if [ $? -eq 0 ]; then
            return 0
        fi
    done
    return 1
}

isRunning java "-Djava.util.logging.config.file=logging.properties"
if [ $? -ne 0 ]; then
    echo "not running, starting..."
fi

0

Nenhuma das respostas funcionou para mim, então aqui está a minha:

process="$(pidof YOURPROCESSHERE|tr -d '\n')"
if [[ -z "${process// }" ]]; then
  echo "Process is not running."
else
  echo "Process is running."
fi

Explicação:

|tr -d '\n'

Isso remove o retorno de carro criado pelo terminal. O resto pode ser explicado neste post.


-1

A seguinte função de shell, sendo baseada apenas em comandos e opções padrão POSIX, deve funcionar na maioria (se não em qualquer) sistema Unix e Linux. :

isPidRunning() {
  cmd=`
    PATH=\`getconf PATH\` export PATH
    ps -e -o pid= -o comm= |
      awk '$2 ~ "^.*/'"$1"'$" || $2 ~ "^'"$1"'$" {print $1,$2}'
  `
  [ -n "$cmd" ] &&
    printf "%s is running\n%s\n\n" "$1" "$cmd" ||
    printf "%s is not running\n\n" $1
  [ -n "$cmd" ]
}

$ isPidRunning httpd
httpd is running
586 /usr/apache/bin/httpd
588 /usr/apache/bin/httpd

$ isPidRunning ksh
ksh is running
5230 ksh

$ isPidRunning bash
bash is not running

Observe que ele irá engasgar quando passar o duvidoso nome de comando "0]" e também falhará em identificar processos que tenham um espaço embutido em seus nomes.

Observe também que a solução mais votada e aceita exige psopções não portáteis e usa gratuitamente um shell que, apesar de sua popularidade, não tem garantia de estar presente em todas as máquinas Unix / Linux ( bash)


$ isPidRunning 0]imprime, por exemplo, "0] está executando 3 [ksoftirqd / 0] 8 [rcuop / 0] 17 [rcuos / 0] 26 [rcuob / 0] 34 [migration / 0] 35 [watchdog / 0]" aqui.
jarno

Para que você precisa dessa coisa PATH?
jarno de

Eu desenvolvi a solução ainda mais aqui .
jarno de

@jarno A configuração PATH é um requisito para que o script seja portátil. Caso contrário, ele falhará pelo menos no Solaris 10 e mais antigo e possivelmente em outras implementações Unix.
jlliagre

1
@jarno: Posso fazer isso, mas também preciso repetir essa configuração de PATH para o awk. Observe que eu reverti para a velha sintaxe de crase para ser portátil com shells bourne de sintaxe pré-POSIX.
jlliagre
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.