commande linux setsid
Je suis en train d'écrire un wrapper qui va exécuter un script en tant qu'animateur de la séance.
Je suis déconcerté par le comportement de la commande linux setsid
. Considérer ce script, appelé test.sh
:
#!/bin/bash
SID=$(ps -p $$ --no-headers -o sid)
if [ $# -ge 1 -a $$ -ne $SID ] ; then
setsid bash test.sh
echo pid=$$ ppid=$PPID sid=$SID parent
else
sleep 2
echo pid=$$ ppid=$PPID sid=$SID child
sleep 2
fi
La sortie diffère selon qu'il soit exécuté ou de source:
$ bash
$ SID=$(ps -p $$ --no-headers -o sid)
$ echo pid=$$ ppid=$PPID sid=$SID
pid=9213 ppid=9104 sid= 9104
$ ./test.sh 1 ; sleep 5
pid=9326 ppid=9324 sid= 9326 child
pid=9324 ppid=9213 sid= 9104 parent
$ . ./test.sh 1 ; sleep 5
pid=9213 ppid=9104 sid= 9104 parent
pid=9336 ppid=1 sid= 9336 child
$ echo $BASH_VERSION
4.2.8(1)-release
$ exit
exit
Donc, il me semble que setsid
retourne immédiatement lorsque le script est d'origine, mais il attend son enfant lorsque le script est exécuté.
Pourquoi la présence d'un contrôle des ats ont rien à voir avec setsid
? Merci!
Edit: Pour clarifier, j'ai ajouté pid/ppid/sid de déclaration pour toutes les commandes.
OriginalL'auteur Matei David | 2012-03-13
Vous devez vous connecter pour publier un commentaire.
Le code source de la
setsid
utilitaire est en fait très simple. Vous remarquerez qu'il nefork()
s si elle voit que son IDENTIFIANT de processus du processus et de l'ID de groupe sont égaux (c'est à dire, si il voit que c'est un processus de chef de groupe) — et qu'il n'a jamaiswait()
s pour son processus enfant: s'ilfork()
s, alors le processus parent retourne immédiatement. Si il n'est pasfork()
, puis il donne l'apparence dewait()
ing pour un enfant, mais vraiment ce qui se passe c'est juste que c' est l'enfant, et c'est Bash quiwait()
ing (tout comme il le fait toujours). (Bien sûr, quand il n'a vraimentfork()
, Bash peut paswait()
pour l'enfant qu'elle crée, car les processuswait()
pour leurs enfants, non pas de leurs petits-enfants.)De sorte que le comportement que vous voyez est une conséquence directe d'un comportement différent:
. ./test.sh
ousource ./test.sh
ou que sais-je encore — ou, d'ailleurs, quand vous venez d'exécutersetsid
directement à partir de l'invite Bash — Bash va lancersetsid
avec un nouveau processus-group-ID pour le contrôle du travail, afin desetsid
ont le même ID du processus que ses processus-group-ID (qui est, c'est un processus de chef de groupe), de sorte qu'il serafork()
et newait()
../test.sh
oubash test.sh
ou que sais-je encore et il se lancesetsid
,setsid
feront partie du même groupe de processus que le script qui est de la course, de sorte que son ID du processus et processus-group-ID sera différent, et il n'est donc pasfork()
, donc ça va donner l'apparence d'attente (sanswait()
ing).setsid
prendre sur un indicateur supplémentaire, dire-w
, dont la présence, il doit attendre que son enfant s'il en est. Comme il est, je sens que son comportement est incohérent: il revient tout de suite si et seulement si il est dirigé par un chef de groupe (et de la fourche). De Plus, comme vous le dites, seulementsetsid
pouvait attendre de son enfant, l'invocation debash
ne peuvent pas attendre pour un petit-enfant.Oui; et en général, c'est un peu étrange à
fork
sanswait
ing. Je ne pense pas que mon collège Systèmes d'Exploitation professeur aurait approuvé. 😛OriginalL'auteur ruakh
Le comportement que j'observe, c'est ce que j'attends, bien que différente de la vôtre. Pouvez-vous utiliser
set -x
à assurez-vous que vous voyez les choses?Lors de l'exécution de
./test.sh 1
, le script parent — le shell interactif — est le leader de la session, de sorte$$ != $SID
et la condition est vraie.Lors de l'exécution de
. test.sh 1
, le shell interactif est l'exécution du script en cours de processus, et est son propre chef de session, donc$$ == $SID
et la condition est fausse, donc jamais de l'exécution de l'enfant intérieur script.bash
comme je l'ai fait dans mon premier exemple. (Ce que je suis en train de réaliser est de lancer le script en tant que garantie animateur de la séance. Si je suppose que c'est le cas, il n'y a aucun point en ayant le script en premier lieu.)OriginalL'auteur ephemient
Je ne vois pas de problème avec votre script. J'ai ajouté supplémentaires énoncés dans le code pour voir ce qui se passe:
Le cas qui vous préoccupe est:
Et de confiance en moi, d'exécuter ce script modifié et vous verrez exactement ce qui se passe. Si la coque qui n'est pas un leader de session s'exécute le script puis il va tout simplement à
else
bloc. Ai-je raté quelque chose?Je vois maintenant ce que tu veux dire: Quand vous faites
./test.sh 1
avec votre script est ensuite parent attend l'enfant à effectuer. enfant blocs de la mère. Mais si vous commencez à l'enfant en arrière-plan, alors vous remarquerez que le parent se termine avant d'enfant. Pour faire ce changement dans votre script:setsid
est nécessaire (c'est à dire, je ne suis pas déjà leader de session) j'aimerais que le parent d'attendre pour l'enfant. Le si partie est vraie dans les deux scénarios, dans mon exemple: parentPID
!= parentSID
. Ce qui me dérange, c'est que le n'est pas prise quand le script est source: parent quitte avant d'enfant.OriginalL'auteur abc