Como determino se um programa está em execução quando inicio um shell e inicio esse programa se ele ainda não estiver em execução?

Como determino se um programa está em execução quando inicio um shell e inicio esse programa se ele ainda não estiver em execução?

Quando inicio um shell, no meu caso bash e/ou zsh, quais linhas preciso adicionar a .zshrc e/ou .bashrc para verificar se um programa já está em execução e se o programa ainda não está em execução, começar?

Exemplo: estou iniciando um novo shell zsh. Se o top ainda não estiver em execução, gostaria de iniciar o top e fazer com que ele assuma o controle do shell. Se top já estiver rodando em outra janela, gostaria que o .zshrc continuasse carregando e me desse um terminal aberto.

Atualização 6-16:

if ! pgrep -U $USER top >/dev/null; then
exec top
fi

O script acima atende ao meu pedido. O sinalizador -q não funcionaria para mim porque -q não é uma opção no meu sistema. Então eu tive que canalizar o PID para/dev/null. Obrigado mveroone, Kusalananda e Thomas Dickey.

Tenho alguns recursos que estão fora do escopo da pergunta original. Suponha que eu esteja em um sistema de usuário único onde posso me tornar root sem precisar digitar uma senha. Como eu executaria automaticamente o top como root se precisasse?

6-18 Ok, o problema de recurso de passar um comando como root foi resolvido. Estou usando isso para lançar vários

Obrigado por todas as respostas atenciosas.

Responder1

Use pgrepassim:

if ! pgrep -u $USER top >/dev/null 2>&1; then
    exec top
fi

Explicação:

  • O pgreputilitário é encerrado com um código de saída zero se o comando puder ser encontrado em execução. Portanto, negue o teste.
  • Também restrinja-o ao usuário atual com -u $USER, para que, por algum motivo, ele não capture os processos de outra pessoa. $USERé uma variável de shell padrão. Se isso por algum motivo não estiver definido, tente usar $LOGNAME, e se falhar, use $( id -n -u )(mas nesse ponto você deve se perguntar o que está acontecendo, porque $LOGNAMEétambémuma variável de shell padrão).
  • Não precisamos da saída de pgrep, então redirecione a saída padrão e os fluxos de erro para /dev/null.

Se top(ou qualquer outra coisa) não estiver em execução, execsubstitua o shell, conforme a pergunta do OP.

Isso deve funcionar em todos shos shells compatíveis.

EDIT: A pgrepimplementação em sistemas BSD (OS X, OpenBSD, ...) possui uma -qopção que faz descartar qualquer saída, mas no pgrepLinux aparentemente não possui esse flag. Em sistemas BSD, use isso em vez do redirecionamento um pouco feio para /dev/null.

Responder2

Se o programa for sempre iniciado a partir do shell e você tiver controle total sobre ele (ou seja, não estiver codificado dentro de um programa de terceiros), você poderá usar algum mecanismo de bloqueio como lockfileou flock. Por exemplo adicionando

flock -n /tmp/top -c top

para o .bashrc/ .zshrcvocê garantirá que apenas a primeira instância do shell executará o topcomando (a menos que você o mate, então outro será iniciado).

Você pode querer criar uma função para poder iniciar o comando também manualmente (não apenas quando o shell é inicializado):

mytop () { flock -n /tmp/$0 -c top; }

E apenas corra mytopquando quiser.

Responder3

Concordar que esse pgrepé o caminho a seguir, existem algumas armadilhas. Você não precisa usar a -qopção, pois pode redirecionar a saída de pgreppara eliminar isso:

pgrep -U $USER top >/dev/null || exec top

As armadilhas residem no fato de que não é um utilitário padrão, então você deve ter em mente que pode não ser portátil. Aqui estão alguns links de páginas de manual para ajudar:

A USERvariável de ambiente está mais bem estabelecida, mas não parece estar na lista POSIX para o shell (veja2.5.3 Variáveis ​​de shell). Em vez disso, observa que USERé uma das muitas variáveis ​​conhecidas por estar em uso (ver nota em8.1 Definição de Variável de Ambiente).

Isso funciona topcomovocê mesmo, claro. Se você escolheu fazê-lo funcionar comoraiz, então você pode alterar $USERpara roote executar topusando sudo(preferencial) ou su. Nem está em POSIX (ver lista). O último ( su) está disponível em qualquer lugar em sistemas do tipo Unix, mas sudogeralmente é preferido. Então você teria

pgrep -U root top >/dev/null || exec sudo top

A menos que você tenha configurado sudopara não exigir uma senha, você será solicitado a fornecer uma senha quando seu shell for iniciado top.

Responder4

Eu acrescentaria um trecho como este no meu .zshrc (ou outro):

if pgrep -u $USER nome_do_programa
então
    nome_do_programa executivo
fi

Embargo :Eu não testei esse código. Por favor, não use-o no root ou no único usuário que você possui em um servidor. Certifique-se de que você pode se recuperar se falhar.

informação relacionada