Come fermare un bash mentre il loop è in esecuzione in background?


23

Ho iniziato un ciclo while come segue:

while true; do {command}; sleep 180; done &

Notare il &.

Pensavo che quando avessi ucciso il terminale, questo ciclo si sarebbe fermato. Ma sta ancora andando. Sono passate ore da quando ho ucciso la sessione terminale.

Come posso interrompere questo ciclo continuo?

Risposte:


38

Ho iniziato

while true; do yad; sleep 60; done &

e chiuso il terminale per testarlo, ora ho avuto lo stesso problema.

Se hai già chiuso il terminale hai iniziato il loop in

Diamo una panoramica dei processi in esecuzione con ps fjx, le ultime righe sulla mia macchina leggere

 2226 11606 11606 19337 ?           -1 S     1000   0:00  \_ /bin/bash
11606 22485 11606 19337 ?           -1 S     1000   0:00  |   \_ sleep 10
 2226  9411  9411  8383 ?           -1 S     1000   0:00  \_ /bin/bash
 9411 17674  9411  8383 ?           -1 Sl    1000   0:00      \_ yad
    1  2215  2215  2215 ?           -1 Ss    1000   0:00 /lib/systemd/systemd --user
 2215  2216  2215  2215 ?           -1 S     1000   0:00  \_ (sd-pam)

Puoi vedere yadcome un sottoprocesso di /bin/bash, se lo chiudo yadcambia sleep 60in nell'output di ps. Se la visualizzazione ad albero è troppo confusa, puoi anche cercare l'output come segue 1 :

ps fjx | grep "[y]ad"  # or respectively
ps fjx | grep "[s]leep 60"

Le righe di output iniziano con due numeri, il primo è il PPID, l'ID processo del processo padre e il secondo è il PID, l'ID del processo stesso. È per questo che 9411appare in entrambe le righe qui:

2226  9411  9411  8383 ?           -1 S     1000   0:00  \_ /bin/bash
9411 17674  9411  8383 ?           -1 Sl    1000   0:00      \_ yad

Questa è la bashsubshell che vogliamo uccidere e abbiamo appena scoperto il suo PID, quindi ora tutto ciò che rimane è semplice

kill 9411  # replace 9411 with the PID you found out!

e la fastidiosa subshell è andata per sempre.

1 : la notazione in quanto grep "[y]ad"invece semplicemente grep yadimpedisce al grepprocesso stesso di comparire nell'elenco dei risultati.


Se il terminale è ancora aperto

bashfornisce la variabile $!, che "si espande nell'ID del processo del lavoro più recentemente inserito in background", quindi ciò che segue uccide solo l'ultimo processo in background:

kill $!

Se non è il processo più recente, è possibile ottenere un elenco di processi in esecuzione con l' jobsintegrato, ad esempio output:

[1]-  Running                 while true; do
    yad; sleep 60;
done &
[2]+  Stopped                 sleep 10

Ci sono due lavori nella lista dei lavori, per uccidere uno di essi è possibile accedervi con il numero del lavoro o le scorciatoie %, %+("lavoro corrente") e %-("lavoro precedente"), ad esempio per terminare il ciclo in esecuzione in background potrebbe fare

kill %1  # or
kill %-

e per terminare il sleep 10lavoro sospeso :

kill %2  # or
kill %+  # or
kill %

5

Devo notare che quando si chiude il terminale in cui è stato immesso quel comando, il sottocomando dovrebbe essere morto con esso. Cercare di riprodurre questo ha mostrato questo comportamento.

Ora, supponendo che tu sia effettivamente in una situazione in cui ciò non è accaduto, un modo per uccidere il programma che hai lasciato in esecuzione in background, causato dalla &fine del comando, è il seguente:

  1. Apri una nuova shell ed esegui echo $$per annotare il tuo PID (ID processo) corrente, in modo da non uccidere la tua sessione.
  2. Identifica il PID del programma che ritieni sia ancora in esecuzione; puoi farlo usando il ps -ef | grep $SHELLcomando per trovare quali programmi eseguono una shell.
  3. Nota la seconda colonna da sinistra e nota il valore numerico che differisce dal echo $$risultato sopra; questo è il PID che vuoi uccidere.
  4. Esegui il kill -SIGTERM <pid>comando, dove si <pid>trova il valore numerico identificato nel passaggio 3
  5. Verificare che il programma non sia più in esecuzione ripetendo il passaggio 2

Puoi anche riavviare la sessione o il computer, ma quanto sopra ti permetterà di evitarlo.


2
È inoltre possibile utilizzare topper terminare il processo premendo k, quindi immettendo il PID, quindi premendo due volte Invio.
luk3yx,

-1

La &farà il terminale crea un nuovo processo e ottenere il codice per eseguire al suo interno. Quindi il tuo codice diventa indipendente dal processo terminale. Anche se chiudi il terminale il nuovo processo in cui il tuo codice è in esecuzione non si fermerà. Quindi rimuovere &o fare ps -aux, individuare il processo e ucciderlo kill (process id).


-3

Di solito bg per lo sfondo fg per il primo piano. Se usi & symbol usa fg mostrerà il programma corrente in esecuzione. Premi Ctrl + C per uccidere.


3
L'uso bg/ fgnon funzionerà una volta che il terminale è stato rimosso bash. Non sarebbe in grado di ricollegarlo utilizzando reptyrperché bashha processi figlio ( sleep).
Xiota,

Ha chiuso il terminale perché ucciderà quel processo. Quindi la prossima volta userà fg per chiudere il programma. Semplice
Curioso

@Curious che è la prossima volta. Ma OP sta chiedendo riguardo a questa volta.
RonJohn,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.