Sous Linux, comment démarrer un processus dans son propre groupe de processus? et plus

Je voudrais lancer un processus dans son propre groupe de processus (ou, alternativement, changer son groupe une fois commencé) et:

  • faire en sorte que les processus du groupe répondent à Ctrl + C depuis le terminal
  • récupère l’id du groupe de processus pour que je puisse terminer tous les processus du groupe via la commande kill .

Note: J’ai essayé setsid prog [args] mais les processus ne répondent pas à Ctrl + C depuis le terminal et je ne pourrais pas obtenir le nouvel identifiant de groupe de processus.

J’ai également essayé de changer le groupe de processus via setpgrp($pid, $pid) et POSIX::setpgid($pid, $pid) Perl, sans succès.

Edit: Le plus gros problème:

J’ai un processus (single-threaded; appelons-le le processus P “prolifique”) qui lance de nombreux processus fils de manière synchrone (l’un après l’autre; il en démarre un nouveau lorsque le processus fils précédent se termine). Depuis le terminal, je veux pouvoir tuer P et l’arborescence des processus en dessous. Pour ce faire, je pourrais simplement arranger pour tuer les processus dans le groupe de P Cependant, le comportement par défaut est que P est dans le groupe de son processus parent. Cela signifie que le parent de P sera tué si je tue tous les processus dans le groupe de P , sauf si P et son arbre sont dans leur propre groupe.

Mon intention est de tuer P et l’arbre en dessous, mais pas le parent de P De plus, je ne peux pas modifier le code de P lui-même.

Que voulez-vous dire par “démarrer un processus dans son propre groupe de processus”? Le shell lance des processus dans leurs propres groupes de processus, ce qui explique comment il contrôle les travaux (en ayant un groupe de processus pour les processus au premier plan et plusieurs groupes de processus pour chaque pipeline lancé en arrière-plan).

Pour voir que le shell lance un nouveau groupe de processus pour chaque pipeline, vous pouvez le faire:

 ps fax -o pid,pgid,cmd | less 

qui montrera quelque chose comme:

 11816 11816 | \_ /bin/bash 4759 4759 | \_ ps fax -o pid,pgid,cmd 4760 4759 | \_ less 

Notez que le shell a créé un nouveau groupe de processus pour le pipeline et que chaque processus du pipeline partage le groupe de processus.

Modifier:

Je pense que je sais ce que tu veux dire. Vous appelez le system de Perl. Apparemment, sh -c ne crée pas de nouveaux groupes de processus, car il s’agit d’un shell sans contrôle du travail.

Ce que je ferais serait de fork , puis de l’enfant:

 setpgrp; system("ps fax -o pid,pgid,cmd"); 

et wait sur le parent.

EDIT: Si vous vouliez faire, utilisez setsid mais trouvez l’identifiant de session et / ou le pid du processus résultant:

Si vous lancez un processus via la commande setsid, il ne sera pas attaché à votre terminal, donc il ne répondra évidemment pas à ctrl-c.

Vous pouvez le trouver en passant à travers la sortie de

 ps x -O sid 

ou quelque chose de plus limité comme

 ps x -o %c,%p,sid 

Ou simplement naviguer dans proc / [pid] / stat pour toutes les entrées et regarder l’ID de session et tout ce qui peut vous intéresser (voir man proc pour plus de détails)

La page de manuel de setsid ne donne aucun indicateur pour générer directement une sortie, mais vous pouvez créer votre propre version qui imprime les informations souhaitées en modifiant la norme.

Par exemple, prenez une copie de setsid.c à partir d’un des résultats pour

http://www.google.com/codesearch?as_q=setsid&as_package=util-linux

Commentez les nls include, les parameters régionaux et la macro d’erreur _ (“”) qui causera des problèmes, puis ajoutez ceci juste avant la ligne execvp:

  printf("process will be pid %d sid %d\n", getpid(), getsid(0)); 

Voici la réponse dans le code Perl suivant les suggestions de ninjalj ci-dessus:

prolific_wrapper.pl

 my $pid = fork(); if (not defined $pid) { die 'resources not available'; } elsif ($pid == 0) { # CHILD setpgrp; exit system(prolific => @ARGV); } else { # PARENT my $was_killed = 0; local $SIG{INT} = sub { say 'kill prolific and its tree ...'; kill KILL => -$pid; $was_killed = 1; }; wait; my $child_status = $?; $SIG{INT} = 'DEFAULT'; if ($was_killed) {kill INT => $$} else {exit $child_status} } 

Merci encore beaucoup!