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

7

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

Exemplo: Estou iniciando um novo shell zsh. Se top ainda não estiver em execução, gostaria de começar do início e fazer com que ele domine o shell. Se top estiver rodando em outra janela, eu 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 satisfaz 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.

Eu 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 inserir uma senha. Como eu autorun topo como root se eu precisasse?

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

Obrigado por todas as respostas atenciosas.

    
por J363 01.06.2016 / 14:29

4 respostas

3

Use pgrep da seguinte forma:

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

Explicação:

  • O utilitário pgrep sai 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 atenda aos processos de outra pessoa. $USER é uma variável de shell padrão. Se por algum motivo isso não estiver definido, tente usar $LOGNAME , e se isso falhar, use $( id -n -u ) (mas, nesse ponto, você deve se perguntar o que está acontecendo, porque $LOGNAME é também uma variável de shell padrão).
  • Não precisamos da saída de pgrep , portanto, redirecione a saída padrão e os fluxos de erro para /dev/null .

Se top (ou qualquer outro) não estiver em execução, exec para substituir o shell, de acordo com a pergunta do OP.

Isso deve estar funcionando em todos os shells compatíveis com sh .

EDIT: A implementação de pgrep em sistemas BSD (OS X, OpenBSD, ...) possui uma opção -q que faz com que seja descartada qualquer saída, mas o pgrep no Linux aparentemente não possui este sinalizador . Em sistemas BSD, use este e não o redirecionamento levemente feio para /dev/null .

    
por 16.06.2016 / 22:35
2

Se o programa é sempre iniciado a partir do shell e você tem controle total sobre ele (ou seja, não é codificado dentro do programa de terceiros), então você pode usar algum mecanismo de bloqueio como lockfile ou flock . Por exemplo, adicionando

flock -n /tmp/top -c top

para o .bashrc / .zshrc você garantirá que apenas a primeira instância do shell execute o comando top (a menos que você o mate, depois outro que será iniciado).

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

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

E apenas execute mytop quando quiser.

    
por 17.06.2016 / 01:25
1

Concordando que pgrep é o caminho a percorrer, existem algumas armadilhas. Você não precisa usar a opção -q , pois você pode redirecionar a saída de pgrep para eliminar isso:

pgrep -U $USER top >/dev/null || exec top
As armadilhas estão no fato de que não é um utilitário padrão, então você deve ter em mente que ele pode não ser portátil. Aqui estão alguns links de manual, para ajudar:

A variável de ambiente USER é mais bem estabelecida, mas não parece estar na lista do POSIX para o shell (veja 2.5.3 Variáveis da Shell ). Em vez disso, ele observa que USER é uma das muitas variáveis conhecidas por estar em uso (veja nota em 8.1 Definição da Variável de Ambiente ).

Isso executa top como você mesmo , é claro. Se você optar por executá-lo como root , poderá alterar o $USER para root e, em seguida, executar top usando sudo (preferencial) ou su . Também não está em POSIX ( ver lista ). O último ( su ) está disponível em todos os lugares em sistemas semelhantes ao Unix, mas sudo é geralmente preferido. Então você teria

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

A menos que você tenha configurado o sudo para não exigir uma senha, será solicitada uma senha quando o seu shell iniciar top .

    
por 17.06.2016 / 01:47
0

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

if pgrep -u $USER program_name
then
    exec program_name
fi

Ressalva: eu não testei este código. Por favor, não use na raiz ou no único usuário que você tem em um servidor. Certifique-se de recuperar se falhar.

    
por 01.06.2016 / 14:34