A maneira "adequada" de testar se um serviço está sendo executado em um script

96

Meu problema:

Estou escrevendo um script bash e nele gostaria de verificar se um determinado serviço está sendo executado.

Eu sei como fazer isso manualmente, com $ service [service_name] status.

Mas (especialmente desde a mudança para o systemd), que imprime um monte de texto que é um pouco complicado de analisar. Eu assumi que há um comando feito para scripts com saída simples ou um valor de retorno que posso verificar.

Mas pesquisar no Google produz apenas uma tonelada de resultados "Ah, apenas ps aux | grep -v grep | grep [service_name]". Essa não pode ser a melhor prática, é? E se outra instância desse comando estiver em execução, mas não uma iniciada pelo script init do SysV?

Ou devo calar a boca e sujar as mãos com um pouco de pgrep?

Nick S
fonte

Respostas:

140

systemctlpossui um is-activesubcomando para isso:

systemctl is-active --quiet service

sairá com status zero se serviceestiver ativo, diferente de zero, caso contrário, tornando-o ideal para scripts:

systemctl is-active --quiet service && echo Service is running

Se você omitir --quiet, também emitirá o status atual para sua saída padrão.

Conforme apontado por don_crissti , algumas unidades podem estar ativas mesmo que nada esteja em execução para fornecer o serviço: as unidades marcadas como "RemainAfterExit" são consideradas ativas se elas saírem com êxito, com a idéia de que elas forneçam um serviço que não precise de um daemon ( por exemplo, eles configuram algum aspecto do sistema). As unidades que envolvem daemons, no entanto, só estarão ativas se o daemon ainda estiver em execução.

Stephen Kitt
fonte
Cuidado com os serviços oneshot. Eles são apenas inactiveou activatinge ambos systemctl statuse systemctl is-activesaem com 3. (a partir de systemd-241 ) Solução alternativa:systemctl show service | grep -qx ActiveStatus=activating
Alois Mahdal
@Alois: Gostaria de saber que tipo de cenário você encontrou em que você gostaria de considerar um serviço oneshot ativo; Você tem um exemplo?
Stephen Kitt
Claro, @StephenKitt. O Tool foofaz algo no sistema que envolve a reinicialização e usa um serviço único, por exemplo, foo_cleanupna próxima inicialização para limpar as coisas. Estou testando isso (meu script também está agendado como um serviço) e quero coletar erros depois, mas quando será depois (música vsauce)? Bem, um dos critérios é que foo_cleanupterminou ("deixou de ser ativo").
Alois Mahdal
Vale a pena ressaltar que 'está com falha' também é uma opção e é útil se você precisar executar uma ação com base em um serviço não iniciado.
Phill Healey
33

systemctlpossui um modo adequado para scripts; use em showvez de statuse adicione as opções -p/ --propertiese --valuepara obter apenas a saída desejada.

Aqui está um exemplo (de um sistema Ubuntu 17.04):

$ systemctl show -p SubState --value NetworkManager
running

Correr (ou não) é um SubState. Se você deseja saber se um serviço está ativo, use a propriedadeActiveState

$ systemctl show -p ActiveState --value x11-common
inactive
$ systemctl show -p SubState --value x11-common
dead

Notas do man:

show [PATTERN...|JOB...]
           Show properties of one or more units, jobs, or the manager
           itself. If no argument is specified, properties of the
           manager will be shown. If a unit name is specified, properties
           of the unit are shown, and if a job ID is specified,
           properties of the job are shown. By default, empty properties
           are suppressed. Use --all to show those too. To select specific
           properties to show, use --property=. This command is intended
           to be used whenever computer-parsable output is required. Use
           status if you are looking for formatted human-readable output.

-p, --property=
           When showing unit/job/manager properties with the show command,
           limit display to properties specified in the argument. The
           argument should be a comma-separated list of property names,
           such as "MainPID". Unless specified, all known properties are
           shown. If specified more than once, all properties with the
           specified names are shown. Shell completion is implemented for
           property names.

--value
           When printing properties with show, only print the value, and
           skip the property name and "=".
Zanna
fonte
2
+1 para uma resposta sofisticada. Por favor, especifique as distribuições que aceitarão a --versionopção com systemctl.
SK Venkat
11

Como complemento à resposta de Zanna, a --valueopção for systemctl showfoi introduzida na versão 230 do systemd . Portanto, pode não estar disponível em certas distros como o debian jessie.

Nesse caso, pode-se emular a opção usando sed:

$ systemctl show -p ActiveState sshd | sed 's/ActiveState=//g'
active
$ systemctl show -p SubState sshd | sed 's/SubState=//g'  
running
Oxmel
fonte
1
+1 para apontar a versão de introdução e distribuição --value, que não funcionará.
SK Venkat
3

Acho isso útil para execução de linha de comando ou se você estiver criando scripts.

Copiado de @StephenKitt

Isso verificará se o serviço está inoperante e executará a reinicialização do serviço

systemctl is-active --quiet <service name> || <service name> restart

a ||não verifica se o valor de retorno de systemctl é diferente de zero significado se não é ativo como explica o autor.

asterisco
fonte
Você também pode usar `is-failed 'para testar se é necessário reiniciar. Parece um pouco mais intuitivo para reiniciar um serviço com falha.
Phill Healey
sim, mas para mim .. eu queria me praticar e assumir que tudo está funcionando quando não está. para que eu possa fazer as coisas verificarem outras coisas com ele. simplesmente se você quiser apenas verificar se não está em execução, a opção 'está com falha' é uma boa escolha. :)
asterisk
3


Estou muito atrasado para a festa, no entanto, usar systemctl is-active junto com &&e ||para isso no script não será o caso o tempo todo. A seguir, usei o tomcat, mas posso usá-lo no método usando argumentos e passando o nome do serviço como argumentos se você precisar verificar vários serviços, mas está fora do escopo aqui.

STATUS=`systemctl is-active tomcat.service`
  if [[ ${STATUS} == 'active' ]]; then
    echo "Execute your tasks ....."
  else 
    echo " Service not running.... so exiting "  
    exit 1  
  fi

Foi assim que fiz uso ... Apenas compartilhando o meu.

e pela simplicidade e facilidade dos itens, siga os outros explicados aqui:

systemctl -q is-active tomcat.service  && echo "Tomcat Runnung" || echo "Service is not running at all "
SAGAR Nair
fonte
Como isso é melhor do que simplesmente if systemctl is-active --quiet tomcat.service? Além disso, [[não é um shell padrão.
Toby Speight
@TobySpeight Você precisa ler meu post um pouco mais, como mencionei no post "É assim que eu usei .... Apenas compartilhando o meu." Eu nunca disse, é um uso de shell padrão, se você o fizer com suporte único, ele se tornará então, mas está fora de escopo aqui. Além disso, abaixo menciono o uso fácil de linha única para fazê-lo usando &&e ||.
SAGAR Nair 19/06
2

Em vez de usar o comando sed como na resposta do Oxmel, basta usar cut -d'=' -f 2para todos os tipos de propriedades consultadas:

por exemplo:

$ systemctl show -p ActiveState sshd | cut -d'=' -f2
active
$ systemctl show -p SubState sshd | cut -d'=' -f2
running
Mohamed El
fonte
Isso é ótimo, mas você realmente precisa dar uma explicação sobre o que esses comandos fazem.
Phill Healey
-1

Acabei de encontrar este ótimo pequeno script:

#!/bin/bash
service=replace_me_with_a_valid_service

if (( $(ps -ef | grep -v grep | grep $service | wc -l) > 0 ))
then
  echo "$service is running!!!"
else
  /etc/init.d/$service start
fi

Fonte

Terry
fonte
Nem todos os serviços têm um executável com o mesmo nome e qualquer usuário pode estar executando um comando que coincide acidentalmente - esta é uma receita para o desastre.
Toby Speight