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 pgrep
assim:
if ! pgrep -u $USER top >/dev/null 2>&1; then
exec top
fi
Explicação:
- O
pgrep
utilitá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, exec
substitua o shell, conforme a pergunta do OP.
Isso deve funcionar em todos sh
os shells compatíveis.
EDIT: A pgrep
implementação em sistemas BSD (OS X, OpenBSD, ...) possui uma -q
opção que faz descartar qualquer saída, mas no pgrep
Linux 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 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 executará o top
comando (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 mytop
quando quiser.
Responder3
Concordar que esse pgrep
é o caminho a seguir, existem algumas armadilhas. Você não precisa usar a -q
opção, pois pode redirecionar a saída de pgrep
para 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 USER
variá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 top
comovocê mesmo, claro. Se você escolheu fazê-lo funcionar comoraiz, então você pode alterar $USER
para root
e executar top
usando 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 sudo
geralmente é preferido. Então você teria
pgrep -U root top >/dev/null || exec sudo top
A menos que você tenha configurado sudo
para 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.