Para melhorar, use killall
e combine os comandos:
ps -aux | grep script_name
killall script_name inotifywait
Ou faça tudo em uma linha:
killall 'ps -aux | grep script_name | grep -v grep | awk '{ print $1 }'' && killall inotifywait
Eu escrevi um script de shell para monitorar um diretório usando o utilitário inotifywait de inotifyt-tools. Eu quero que esse script seja executado continuamente em segundo plano, mas também quero ser capaz de pará-lo quando desejar.
Para fazê-lo funcionar continuamente, usei while true
; assim:
while true;
do #a set of commands that use the inotifywait utility
end
Eu salvei-o em um arquivo em /bin
e o tornei executável. Para executá-lo em segundo plano, usei nohup <script-name> &
e fechei o terminal.
Eu não sei como faço para parar este script. Eu olhei para as respostas aqui e uma questão muito relacionada < href="https://unix.stackexchange.com/questions/79441/terminating-a-bash-shell-script-running-in-the-background"> aqui . Mas eu não consigo resolver o problema.
P.S: Me desculpe se isso soa trivial, eu sou um iniciante em scripts de shell.
UPDATE 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 eliminar os processos.
Eu tive que pgrep inotifywait
e use sudo kill -9 <pid>
novamente para o id retornado.
Isso funciona, mas acho que essa é uma abordagem confusa, estou procurando uma resposta melhor.
UPDATE 2: A resposta consiste em matar 2 processos . Isso é importante porque executar o script na linha de comando inicia 2 processos, 1 o próprio script e 2, o processo inotify . Por favor, sugira se o meu entendimento está correto. Obrigado !!
Relacione os trabalhos em segundo plano usando
# jobs
Em seguida, escolha o número anterior de trabalho e execute
exemplo
# fg 1
traráparaoprimeiroplano.
Emseguida,mate-ousandoCTRL+CouumamaneiramaisfácildeencontraroPIDdoscriptusando
ps-aux|grepscript_name
Em seguida, mate usando pid
sudo kill -9 pid_number_here
Você pode usar ps
+ grep
ou pgrep
para obter o processo nome / pid ; depois use killall
/ pkill
para matar o nome do processo ou use kill
para matar o pid. Todos os seguidores devem funcionar.
killall $(ps aux | grep script_name | grep -v grep | awk '{ print $1 }') && killall inotifywait
(ps -ef | grep script_name | grep -v grep | awk '{ print $1 }' | xargs killall) && killall inotifywait
(ps -ef | grep script_name | grep -v grep | awk '{ print $2 }' | xargs kill) && killall inotifywait
(pgrep -x script_name | xargs kill) && pkill -x inotifywait
pkill -x script_name && pkill -x inotifywait
O mais importante é que você tenha certeza de matar apenas o (s) processo (s) exato (s) que você espera matar.
pkill
/ pgrep
corresponde a um padrão em vez do nome exato , por isso é mais perigoso; aqui -x
é adicionado para corresponder ao nome exato.
Além disso, ao usar pgrep
/ pkill
, você pode precisar
-f
para corresponder à linha de comando completa (como ps aux
) -a
para também imprimir o nome do processo. Como você provavelmente sabe, há muitas maneiras de fazer isso.
Em relação ao seu "UPDATE # 2" - em geral, encerrar qualquer processo em uma hierarquia pai-filho geralmente terminará todos os processos associados. Mas há muitas exceções para isso. O ideal é que você termine o 'filho' final em uma árvore de processos, então o (s) pai (s) desta criança deve sair se não tiver outras tarefas para executar. Mas se você mata um dos pais, o sinal deve ser transmitido para as crianças quando o pai morre e os filhos devem sair também - mas há casos em que os processos filhos podem ignorar o sinal (via armadilhas ou mecanismos similares) e continuar para executar um será herdado pelo processo 'init' (ou similar). Mas esse assunto de comportamento de processo pode se tornar complexo e eu vou deixar isso lá ...
Um método que eu gosto, se eu 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. Eu o encorajaria a ler a página de manual 'screen' para uma explicação completa. Um exemplo rápido para iniciar um processo em segundo plano seria o comando:
tela -d -m / caminho / para / programa
Isto irá iniciar "/ path / to / program" dentro de uma sessão de 'screen'.
Você pode ver sua sessão em execução com o comando:
tela -ls
E a qualquer momento você pode se reconectar ao seu programa em execução com o comando:
tela -r
E depois terminá-lo com um ^ C ou o que for.
Além da beleza de ser capaz de se reconectar e desconectar do seu processo à vontade, o 'screen' irá capturar qualquer stdout () que o seu programa possa produzir.
Mas minha preferência pessoal nessas questões é ter um programa de controle que administre o início e a interrupção de um processo. Isso pode ficar um pouco complicado e requer alguns scripts complicados. E como qualquer script, existem dezenas de boas maneiras de fazer isso. Eu incluí um exemplo básico de um método que uso rotineiramente para iniciar e parar aplicativos. Se sua tarefa é simples, você pode inseri-la diretamente no script de controle - ou você pode fazer com que este script de controle chame outro programa externo. Observe que este exemplo não é abrangente em termos de gerenciamento do processo. Deixei de fora a possibilidade de cenários como: Certificar-se de que o script ainda não esteja em execução quando você usa a opção "start", validando que o PID em execução é realmente o processo iniciado (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 "kill". Fazer todas essas verificações pode ficar complicado e eu não queria tornar o exemplo muito longo e complexo. Você pode querer 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 de casos que começa com "myscript".
Quando tudo estiver pronto, supondo que o "programctl" esteja no diretório atual, você pode iniciar seu programa com:
./ programctl start
E pare com:
./ programctl stop
Felicidades.
#!/bin/bash
# Description: A wrapper script used to stop/start another script.
#--------------------------------------
# Define Global Environment Settings:
#--------------------------------------
# Name and location of a persistent PID file
PIDFILE="/tmp/tmpfile-$LOGNAME.txt"
#--------------------------------------
# Check command line option and run...
# Note that "myscript" should not
# provided by the user.
#--------------------------------------
case $1
in
myscript)
# This is where your script would go.
# If this is a routine 'bash' shell script, you can enter
# the script below as illustrated in the example.
# Or you could simply provide the path and parameters
# to another script such as /dir/name/command -options
# Example of an embedded script:
while true
do
# do something over and over...
sleep 1
done
# Example of an external script:
/usr/local/bin/longrun -x
;;
start)
# Start your script in the background.
# (Note that this is a recursive call to the wrapper
# itself that effectively runs your script located above.)
$0 myscript &
# Save the backgound job process number into a file.
jobs -p > $PIDFILE
# Disconnect the job from this shell.
# (Note that 'disown' command is only in the 'bash' shell.)
disown %1
# Print a message indicating the script has been started
echo "Script has been started..."
;;
stop)
# Read the process number into the variable called PID
read PID < $PIDFILE
# Remove the PIDFILE
rm -f $PIDFILE
# Send a 'terminate' signal to process
kill $PID
# Print a message indicating the script has been stopped
echo "Script has been stopped..."
;;
*)
# Print a "usage" message in case no arguments are supplied
echo "Usage: $0 start | stop"
;;
esac