Discendenti del processo


20

Sto cercando di creare un contenitore di processi. Il contenitore attiverà altri programmi. Ad esempio: uno script bash che avvia l'esecuzione di attività in background con l'utilizzo di "&".

La caratteristica importante che sto cercando è questa: quando uccido il container, tutto ciò che è stato generato sotto di esso dovrebbe essere ucciso. Non solo i bambini diretti, ma anche i loro discendenti.

Quando ho iniziato questo progetto, ho erroneamente creduto che quando tu avessi ucciso un processo anche i suoi figli fossero automaticamente uccisi. Ho chiesto consiglio a persone che avevano la stessa idea sbagliata. Mentre è possibile catturare un segnale e passare l'uccisione ai bambini, non è quello che sto cercando qui.

Credo che ciò che voglio sia realizzabile, perché quando chiudi un xterm, tutto ciò che correva al suo interno viene ucciso a meno che non venga annullato. Ciò include i processi orfani. Questo è quello che sto cercando di ricreare.

Ho idea che ciò che sto cercando è quello di coinvolgere sessioni unix.

Se esistesse un modo affidabile per identificare tutti i discendenti di un processo, sarebbe utile poter inviare anche loro segnali arbitrari. ad es. SIGUSR1.


Bene, uccidere il processo genitore invia SIGHUPai suoi processi figli diretti. Il gestore predefinito del segnale di riaggancio interrompe l'esecuzione del processo, quindi la route predefinita è quella di uccidere tutti i discendenti. Ulteriori informazioni sui processi e sui gruppi di processi.
alex,

Chiudere lo xterm uccide tutto ciò che è generato nello xterm perché il TTY viene distrutto. Se riesci a trovare un modo per creare un tty che i processi figlio possono usare, puoi quindi distruggere il TTY e realizzare la stessa cosa. Qualsiasi processo che non ha chiuso quel TTY (nohup e amici) riceverà un SIGHUP.
Patrick,

Risposte:


23

Se si invia un segnale a un processo, tale processo viene ucciso. Mi chiedo come sia iniziata la voce che uccidere un processo uccida anche altri processi, sembra particolarmente controintuitiva.

Vi sono, tuttavia, modi per uccidere più di un processo. Ma non invierai un segnale a un processo. È possibile eliminare un intero gruppo di processi inviando un segnale a -1234 dove 1234 è il PGID (ID gruppo di processo), che è il PID del leader del gruppo di processi. Quando si esegue una pipeline , l'intera pipeline inizia come un gruppo di processi (le applicazioni possono modificarlo chiamando setpgido setpgrp).

Quando si avviano processi in background ( foo &), si trovano nel proprio gruppo di processi. I gruppi di processi vengono utilizzati per gestire l'accesso al terminale; normalmente solo il gruppo di processi in primo piano ha accesso al terminale. I processi in background rimangono nella stessa sessione , ma non esiste alcuna possibilità di terminare un'intera sessione o addirittura di enumerare i gruppi di processi o i processi in una sessione, quindi non è di grande aiuto.

Quando si chiude un terminale, il kernel invia il segnale SIGHUPa tutti i processi che lo hanno come terminale di controllo . Questi processi formano una sessione , ma non tutte le sessioni hanno un terminale di controllo. Per il tuo progetto, una possibilità è quindi quella di avviare tutti i processi nel proprio terminale, creati da script , schermo , ecc. Uccidere il processo di emulazione del terminale per uccidere i processi contenuti (supponendo che non siano stati risolti setsid).

È possibile fornire maggiore isolamento eseguendo i processi come proprio utente, che non fa nient'altro. Quindi è facile uccidere tutti i processi: esegui kill(la chiamata di sistema o l' utilità ) come quell'utente e usa -1 come argomento PID per uccidere, che significa "tutti i processi di quell'utente".

È possibile fornire un isolamento ancora maggiore, ma con una configurazione notevolmente maggiore eseguendo i processi contenuti in un contenitore reale .


Se programmi i tuoi processi, puoi usare qualcosa come :,prctl(PR_SET_PDEATHSIG, SIGHUP); maggiori informazioni: man7.org/linux/man-pages/man2/prctl.2.html
Alexis Wilke,

Gilles, dici questo: "Quando chiudi un terminale, il kernel invia il segnale SIGHUP a tutti i processi che lo hanno come terminale di controllo". Da questo sto supponendo che il terminale mandi SIGHUP al leader della sessione (shell) che lo inoltra a tutti i gruppi di processi all'interno della sessione. Quale dei due avrebbe ragione?
Iruvar,

4

All'interno dello script genitore intrappola il segnale di uccisione e fallo uccidere tutti i bambini. Per esempio,

#!/bin/bash
# kill the parent and children together
trap "kill 0" EXIT
# create all the children
for n in $(seq 1 100)
do
    ( echo "begin $n"; sleep 60; echo "end $n" ) &
done
# wait for the children to complete
wait

2

Un modo affidabile per identificare tutti i discendenti di un processo è utilizzare il comando pstree <pid>dove pid è l'ID del processo principale.

Leggi la pagina man pstree qui .

Per segnalare tutti i membri di un gruppo di processi: killpg(<pgrp>, <sig>);
dove pgrp è il numero del gruppo di processi e sig è il segnale.

Per attendere i bambini in un gruppo di processi specificato: waitpid(-<pgrp>, &status, ...);

Un'alternativa a ciò che stai facendo è eseguire il contenitore dei processi in una nuova shell bash. Crea la nuova shell bash con il comando bashed esegui i tuoi processi. Quando si desidera terminare tutti i processi, chiudere la shell con il comando exit.


Penso che killpg mi permetterà di fare quello che devo fare. Grazie.
Craig Turner,

1

Uso

unshare -fp --kill-child -- yourprogram

Se uccidi unshare, tutti i processi figlio (che yourprogrampossono essere stati generati) verranno uccisi.

Questo è ora possibile con util-linux 2.32 ; Ho implementato questo a monte . Richiede spazi dei nomi utente (opzione di configurazione del kernel CONFIG_USER_NS=y) o privilegi di root. Vedi anche qui .


0

Il comando rkill dal pacchetto pslist invia un determinato segnale (o SIGTERMdi default) al processo specificato e a tutti i suoi discendenti:

rkill [-SIG] pid/name...

0

Un'altra opzione per uccidere tutti i discendenti della shell: jobs -p | xargs -n 1 pkill -P

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.