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?
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:
Enquanto pidof
e pgrep
sã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 ax
que 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 which
para verificar um caminho completo sempre que possível.
Referências:
grep
também vai encontrar-se em execução (por exemplo, ps cax | grep randomname
sempre retornará 0 porque grep
achados 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
.
ps cax | rev | cut -f1 -d' ' | rev
irá mostrar apenas a coluna de nome, para facilitar a análise.
ps cax
não pode exibir o nome do comando totalmente. Por exemplo, ele imprime "chromium-browse" em vez de "chromium-browser".
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.
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 ps
comando 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 ps
deve 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.
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.
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 bash
e uma instância de remmina
execução):
$ pidof bash remmina
6148 6147 6144 5603 21598
Em outros Unices, pgrep
ou uma combinação de ps
e grep
alcançará a mesma coisa, como outros corretamente apontaram.
pidof httpd
funciona bem no Red Hat 5. Mas no meu Red Hat 4, pidof
não está presente :-(
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:
PATH=...
]ps
. Para evitar o segundo grep
, sugiro:ps aux | grep [h]ttpd
grep
.
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
ps cax
elimina a necessidade de uso grep -v
. Assim, por exemplo, você pode usar: ps cax | grep java > /dev/null || echo "Java not running"
.
Apenas uma pequena adição: se você adicionar o -c
sinalizador ao ps, não precisará remover a linha que contém o processo grep grep -v
posteriormente. 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 -u
se precisar de menos informações.
Em um sistema onde a genética do ps
comando 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.
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"
Eu uso pgrep -l httpd
mas não tenho certeza se está presente em alguma plataforma ...
Quem pode confirmar no OSX?
pidof
por favor? OK, você fez. Obrigado. Portanto, devemos encontrar algo mais funcionando no OSX ... Seu básico ps|grep
pode ser a única solução ;-)
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 $PID
instrução.
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:
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 gwak
como awk
alternativa 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"
Aqui está minha versão. Recursos:
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
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.
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 ps
opçõ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.