Eu escrevi um script de shell para monitorar um diretório usando o utilitário inotifywait do inotifyt-tools. Quero que esse script seja executado continuamente em segundo plano, mas também quero poder interrompê-lo quando desejado.
Para fazê-lo funcionar continuamente, eu usei while true
; como isso:
while true;
do #a set of commands that use the inotifywait utility
end
Salvei-o em um arquivo /bin
e o tornei executável. Para executá-lo em segundo plano, usei nohup <script-name> &
e fechei o terminal.
Não sei como paro esse script. Eu olhei para as respostas aqui e uma pergunta muito relacionada aqui .
ATUALIZAÇÃO 1: Com base na resposta de @InfectedRoot abaixo, consegui resolver meu problema usando a seguinte estratégia. Primeiro uso
ps -aux | grep script_name
e use sudo kill -9 <pid>
para matar os processos. Eu tive que pgrep inotifywait
usar sudo kill -9 <pid>
novamente para o ID retornado.
Isso funciona, mas acho que é uma abordagem confusa, estou procurando uma resposta melhor.
ATUALIZAÇÃO 2: A resposta consiste em matar 2 processos . Isso é importante porque a execução do script na linha de comando inicia 2 processos, 1 o próprio script e 2, o processo de inotificação .
-9
opçãokill
e usá-la apenaskill
eliminará a bagunça.-9
opção seria totalkill
aqui. : Pkill
ele você prefixar o PGID com um sinal de menos:kill -- -<pgid>
,kill -9 -<pgid>
, etc.Respostas:
Para melhorar, usar
killall
e também combinar os comandos:Ou faça tudo em uma linha:
fonte
Error: no process
deve significar que você já o matou. Você pode testá-lo abrindo outros dois programas, como o VLC & Geany , e testando com eles.grep -v grep
transformargrep script_name
emgrep -e "[s]cript_name"
.Listar os trabalhos em segundo plano usando
# jobs
Em seguida, escolha o número anterior de trabalho e execute
exemplo
trará para o primeiro plano.
Em seguida, mate-o usando CTRL + C ou a maneira mais fácil de encontrar o PID do script usando
Então mate usando pid
fonte
jobs
comando realmente exibia apenas os trabalhos em execução enquanto estava no shell. Depois que fechei uma determinada janela do terminal, a única maneira de acessá-los era viaps
(veja acima para isso). Portanto, é certo que você não está inventando isso.Você pode usar
ps
+grep
oupgrep
para obter o nome do processo / pid ; depois usekillall
/pkill
para matar o nome do processo ou usekill
para matar o pid. Todos os seguintes devem funcionar.O mais importante é garantir que você mate apenas o (s) processo (s) exato (s) que deseja matar.
pkill
/pgrep
corresponde a um padrão e não ao nome exato ; portanto, é mais perigoso; aqui-x
é adicionado para corresponder ao nome exato.Além disso, ao usar
pgrep
/pkill
você pode precisar-f
para coincidir com a linha de comando completa (comops aux
faz)-a
para imprimir também o nome do processo.fonte
pgrep
/pkill
. Se isso ainda der errado, você pode tentarpgrep
sem -x. Basicamente, não acho que seja bom interromper o processo em um comando de linha sem verificar se outros processos são compatíveis.Como você provavelmente pode dizer, existem várias maneiras de fazer isso.
Em relação à sua "ATUALIZAÇÃO # 2" - em geral, encerrar qualquer processo em uma hierarquia pai-filho geralmente encerrará todos os processos associados. Mas há muitas exceções a isso. Idealmente, você deseja encerrar o 'filho' final em uma árvore de processos; os pais desse filho devem sair se não tiverem outras tarefas para executar. Mas se você matar um pai, o sinal deve ser retransmitido para os filhos quando o pai morrer e os filhos também devem sair - mas há casos em que os processos filhos podem ignorar o sinal (por meio de armadilhas ou mecanismos semelhantes) e podem continuar executar um será herdado pelo processo 'init' (ou similar). Mas esse assunto de comportamento do processo pode se tornar complexo e eu vou deixá-lo lá ...
Um método que eu gosto se não quiser usar um script de controle (descrito a seguir) é usar o utilitário 'screen' para iniciar e gerenciar o processo. O comando 'screen' está cheio de recursos e pode levar algum tempo para dominar. Recomendamos que você leia a página do manual 'screen' para obter uma explicação completa. Um exemplo rápido para iniciar um processo em segundo plano seria o comando:
tela -d -m / caminho / para / programa
Isso iniciará "/ path / to / program" dentro de uma sessão de 'tela'.
Você pode ver sua sessão em execução com o comando:
tela -ls
E a qualquer momento, você pode reconectar-se ao seu programa em execução com o comando:
tela -r
E então apenas termine com um ^ C ou o que seja.
Além da beleza de poder reconectar e desconectar do seu processo à vontade, essa 'tela' capturará qualquer stdout () que seu programa possa produzir.
Mas minha preferência pessoal nessas questões é ter um programa de controle que gerencia o início e a parada de um processo. Isso pode se tornar um pouco complicado e requer alguns scripts discutivelmente complicados. E, como qualquer script, existem dezenas de boas maneiras de fazê-lo. Incluí um exemplo básico de um método usado rotineiramente para iniciar e parar aplicativos. Se sua tarefa é simples, você pode inseri-la diretamente no script de controle - ou pode fazer com que esse script de controle chame outro programa externo. Observe que este exemplo não é de forma alguma abrangente em termos de gerenciamento do processo. Eu deixei de fora a possibilidade de cenários como: Garantir que o script ainda não esteja em execução quando você usar a opção "start", validando que o PID em execução é realmente o processo que você iniciou (por exemplo, seu script não ' morreu e outro processo foi iniciado usando o mesmo PID) e validando que o script realmente respondeu (saiu) na primeira solicitação de "interrupção". Fazer todas essas verificações pode ficar complicado e eu não queria tornar o exemplo muito longo e complexo. Você pode modificar o exemplo para praticar seu script de shell.
Salve o seguinte código em um arquivo chamado "programctl", torne-o executável com o comando:
chmod 755 programctl
Em seguida, edite o arquivo e adicione seu código / script na seção do caso que começa com "myscript".
Depois que tudo estiver no lugar, assumindo que "programctl" esteja no diretório atual, você poderá iniciar seu programa com:
./programctl start
E pare com:
./programctl stop
Felicidades.
fonte