Domanda

Ho uno script bash che fa un po 'di elaborazione in parallelo in un ciclo. Non voglio che il processo parallelo a picco la CPU, in modo da utilizzare un comando di sonno. Ecco una versione semplificata.

(while true;do sleep 99999;done)&

Così ho eseguire la linea di cui sopra da una festa pronta e ottenere qualcosa di simile: [1] 12345

Dove [1] è il numero di posti di lavoro e 12345 è l'ID di processo (PID) del ciclo while. Faccio un kill 12345 e ottengo:

[1]+  Terminated              ( while true; do
    sleep 99999;
done )

Sembra che l'intero script è stato terminato. Tuttavia, faccio un ps aux|grep sleep e trovare il comando del sonno è ancora forte, ma con il proprio pid! Posso uccidere il sleep e tutto sembra bene. Tuttavia, se dovessi uccidere il sonno prima, il ciclo while inizia una nuova pid sleep. Questa è una sorpresa per me dal momento che il sonno non è parallelo al ciclo while. Dello stesso ciclo, è un singolo percorso di esecuzione.

Così ho due domande:

  1. Perché il comando di sonno ottenere il proprio ID di processo?
  2. Come faccio facilmente uccidere il ciclo while e il sonno?
È stato utile?

Soluzione

  1. Il sonno prende il proprio PID perché è un processo in esecuzione e solo in attesa. Prova which sleep per vedere dove si trova.
  2. È possibile utilizzare ps -uf per vedere l'albero processo sul vostro sistema. Da lì si può determinare ciò che il PPID (genitore PID) del guscio (quello che esegue il loop) del sonno è.

Altri suggerimenti

Hai provato a fare kill %1, dove 1 è il numero che si ottiene dopo aver lanciato il comando in background?

L'ho fatto proprio ora dopo il lancio (while true;do sleep 99999;done)& e conclusa correttamente esso.

"ps --ppid" seleziona tutti i processi con il PID genitore specificato, ad esempio:

$ (while true;do sleep 99999;done)&
[1] 12345

$ ppid=12345 ; kill -9 $ppid $(ps --ppid $ppid -o pid --no-heading)

Si può uccidere il gruppo di processi.

Per trovare il gruppo di processo del vostro processo di esecuzione:

ps --no-headers -o "%r" -p 15864

Poi uccidere il gruppo di processi utilizzando:

kill -- -[PGID]

Si può fare tutto in un unico comando. Proviamo out:

$ (while true;do sleep 99999;done)&
[1] 16151

$ kill -- -$(ps --no-headers -o "%r" -p 16151)
[1]+  Terminated              ( while true; do
    sleep 99999;
done )
  1. A causa "sonno" è un processo, non una funzione o simili

  2. build-in
  3. Si potrebbe procedere come segue:

    (while true;do sleep 99999;done)&
    whilepid=$!
    kill -- -$whilepid
    

Il codice sopra uccide il gruppo di processo, poiché il PID è specificato come un numero negativo (ad esempio -123 invece di 123). Inoltre, esso utilizza il $! variabile, che memorizza il PID del processo eseguito più recentemente.

Nota: Quando si esegue qualsiasi processo in background in modalità interattiva (vale a dire utilizzando la riga di comando prompt dei) si crea un nuovo gruppo di processi, che è ciò che sta accadendo a voi. In questo modo, è relativamente facile "Kill 'em all", in quanto è sufficiente per uccidere l'intero gruppo di processi. Tuttavia, quando lo stesso viene fatto all'interno di uno script, non crea alcun nuovo gruppo, perché tutti i nuovi processi appartengono allo script PID, anche se sono eseguiti in background (controllo di posti di lavoro è disabilitato per impostazione predefinita). Per attivare il controllo di posti di lavoro in uno script, basta inserire il seguente all'inizio dello script:

#!/bin/bash

set -m

Per uccidere il ciclo while e la sleep utilizzando $! è anche possibile utilizzare un gestore di segnale trap all'interno della subshell.

(trap 'kill ${!}; exit' TERM; while true; do sleep 99999 & wait ${!}; done)&
kill -TERM ${!}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top