Comment obtenir le pid d'un sous-shell?


13

Comment obtenir le pid d'un sous-shell?

Par exemple:

$ echo $$
16808

Cela ne fonctionne pas, car le shell d'origine se développe $$:

$ ( echo $$ )
16808

Pourquoi les guillemets simples ne fonctionnent-ils pas? Une fois que le shell d'origine a supprimé le guillemet simple, le sous-shell ne se développe $$-t -il pas en soi?

$ ( echo '$$' )
$$

Pourquoi ça evalne marche pas non plus? Est evalgéré par le sous-shell? Pourquoi me donne-t-il le PID de la coque d'origine?

$ ( eval echo '$$' )
16808

Merci.


Je suggère une réouverture, car les questions sont essentiellement différentes à mon avis ("comment éviter l' $$expansion" vs "pid différent en sous-shell").
peterh

Réponses:


12

En plus de bash's $BASHPID, vous pouvez le faire de manière portable avec:

pid=$(exec sh -c 'echo "$PPID"')

Exemple:

(pid=$(exec sh -c 'echo "$PPID"'); echo "$$ $pid")

Vous pouvez en faire une fonction:

# usage getpid [varname]
getpid(){
    pid=$(exec sh -c 'echo "$PPID"')
    test "$1" && eval "$1=\$pid"
}

Notez que certains shells (par exemple. zshOu ksh93) ne démarrent PAS un sous-processus pour chaque sous-shell créé avec (...); dans ce cas, $pidpeut finir par être le même que $$, ce qui est juste, car c'est le PID du processus qui a getpidété appelé.


1
Non. Mais ne présumez pas qu'un sous-shell est nécessairement exécuté dans un sous-processus - ce n'est pas le cas ksh93, par exemple.
mosvy

1
Cela fonctionnera bien dans ksh93 - il retournera toujours le pid du processus à partir duquel il a été appelé. C'est (...)l'exemple de l'exemple qui peut ne pas engendrer un processus séparé, comme il le fait dans bash.
mosvy

1
De plus, certains shells aiment zshou yashoptimisent un fork()pour la dernière commande d'un sous-shell. Ils peuvent même optimiser la fourchette du sous-shell s'il s'agit de la dernière commande d'un script afin que vous getpidpuissiez même signaler le parent de $$. Vous pouvez définir getpidcomme: getpid(){ sh -c 'echo "$PPID"'; return; }pour désactiver, éviter le problème.
Stéphane Chazelas

1
@HaroldFischer 1. sans execou sans cette optimisation, le sh -c ...processus sera un petit-enfant, au lieu d'un enfant du processus où une $(...)substitution de commande est utilisée, et $PPIDsera le pid du $(...)sous - shell. C'est exactement ce qui se passe dans l' exemple set -E+ trap ERRbash ci-dessus.
mosvy

1
@HaroldFischer 2. test "$1"teste s'il $1s'agit d'une chaîne vide ou non - un moyen rapide et sale de tester si cette fonction a reçu un varnameargument pour assigner ou non le pid; utiliser une fonction n'était pas l' idée la plus brillante en premier lieu.
mosvy

18
$ echo $BASHPID
37152
$ ( echo $BASHPID )
18633

Du manuel:

BASHPID

Développe l'ID de processus du processus bash en cours. Cela diffère de $$dans certaines circonstances, telles que les sous-coquilles qui ne nécessitent pas la réinitialisation de bash.

$

Développe l'ID de processus du shell. Dans un ()sous - shell, il se développe à l'ID de processus du shell actuel, pas le sous-shell.

En relation:


Merci. (1) Que signifie «réinitialisé»? (2) Pourriez-vous également vous demander pourquoi ces méthodes que j'ai essayées ne fonctionnent pas?
Tim

@Tim Je crois que Gilles a répondu ici . Bash ne se met simplement pas à jour $$dans les sous-coquilles.
Kusalananda

Voulez-vous dire que je devrais toujours utiliser $ BASHPID à la place de $$ dans tous les cas en bash? Quand dois-je utiliser lequel?
Tim

@Tim Cela dépend si vous, dans un sous-shell, souhaitez obtenir l'ID de processus du script ou du sous-shell. Les deux possibilités sont fournies et celle qui est correcte dépend de l'application. Aucune réponse plus précise ne peut être donnée à cela.
Kusalananda

1
@Tim Le PID d'un shell parent d'un sous-shell ne peut être trouvé de manière fiable que si vous vous arrêtez pour enregistrer $BASHPIDdans une variable et l'utiliser dans le sous-shell. Oui $PPID, mais c'est le PID parent du shell dans le même sens que $$le PID du shell (il n'est pas réinitialisé dans un sous-shell). Il n'y a pas de $BASHPPIDvariable.
Kusalananda
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.