Obtenir la liste des processus qui ont été ajoutés à mon processus en cours d'exécution?

3

Je suis en train d'écrire une application wrapper dans des scripts bash et je veux que l'application garde une trace des outils / processus qui ont été lancés à partir de scripts utilisateur. J'aimerais savoir quel est le meilleur moyen de déterminer la liste des processus enfants générés par ce processus parent.

j'ai essayé

  1. Invoquez périodiquement la commande ps et construisez un arbre de processus (comme ps -ejH), mais cela omet les processus qui se terminent très rapidement.
  2. Utiliser un outil tel que forkstat qui utilise l'interface du connecteur proc, mais qui ne peut s'exécuter qu'avec des privilèges élevés. Bien que cela donne les données correctes, une exécution en tant que sudo ne fonctionnerait pas dans mon cas?

Des suggestions sur la façon dont cela peut être réalisé?

divyanshm
la source
Dans quelle langue écrivez-vous?
ctrl-alt-delor
Voulez-vous également inclure les "petits-enfants, etc.", c'est-à-dire que si votre script génère le processus A, les enfants du processus A seront-ils inclus dans votre suivi?
humanite et
Oui, j'aurais aussi besoin des petits-enfants. Fondamentalement, la sous-arborescence enracinée dans mon processus d'application wrapper.
divyanshm
1
J'espère que vous savez qu'un processus peut se débarrasser de son parent (échappe à l'arborescence des processus) par fork + exit b) vous pouvez démarrer un processus dans un autre processus non lié du même utilisateur avec ptrace, par exemple. gdb -p PID -batch -ex 'p system("command")'.
Mosvy
Oui, et c’est la raison pour laquelle j’explorais # 2 -> la capacité d’écouter immédiatement un processus.
Divyanshm

Réponses:

4

Si vous utilisez Linux, vous pouvez utiliser stracepour tracer les appels système utilisés par un processus. Par exemple:

~ strace -e fork,vfork,clone,execve -fb execve -o log ./foo.sh
foo bar
~ cat log
4817  execve("./foo.sh", ["./foo.sh"], [/* 42 vars */]) = 0
4817  clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f1bb563b9d0) = 4818
4818  execve("/bin/true", ["/bin/true"], [/* 42 vars */] <detached ...>
4817  --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=4818, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
4817  clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f1bb563b9d0) = 4819
4817  clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f1bb563b9d0) = 4820
4820  execve("/bin/echo", ["/bin/echo", "foo", "bar"], [/* 42 vars */] <detached ...>
4817  --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=4820, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
4817  +++ exited with 0 +++
4819  execve("/bin/sleep", ["sleep", "1"], [/* 42 vars */] <detached ...>

Vous pouvez voir que le script a déclenché trois processus (PID 4818, 4819, 4820) à l'aide de l' clone(2)appel système et que les execve(2)appels système de ces processus ont montré les commandes exécutées.

  • -e fork,vfork,clone,execve limite la sortie strace à ces appels système
  • -f suit les processus enfants
  • -b execvese détache d'un processus lorsque execveest atteint, nous ne voyons donc pas de traçage supplémentaire des processus enfants.
muru
la source
Est-il conseillé de s'appuyer sur strace? D'après ce que je sais, cela prend pas mal de ressources.
Divyanshm
1
@divyanshm, cela ne prend que beaucoup de ressources si vous ne limitez pas l'ensemble des appels système à tracer. Lorsque vous utilisez plutôt -eune poignée d'appels système, cela ne fait que ralentir les choses pour les processus qui utilisent ces appels très fortement.
Ruslan
Le traçage d’un processus et de ses enfants (ce que fait strace (1)) les ralentira considérablement - un ralentissement d’au moins 1,8 fois pour un simple strace -qfe trace=execve -o /dev/null -p PIDsur un shell exécuté /.configure && makedans le répertoire source bash. Ensuite, il y a toujours le problème de l'analyse de la sortie de strace dans un arbre - cela ne sonne pas comme un morceau de gâteau ;-)
mosvy
@mosvy, la plupart des scripts de configuration et des makefiles sont très chargés en exec, bien sûr, ils auront un ralentissement comme le dit Ruslan.
Muru
1
Ce n'est pas que strace (1) soit un gros problème de ressources (ce n'est en aucun cas une mesure), mais il doit fonctionner en parallèle avec les processus qu'il trace - il ne fait pas sa trace de manière asynchrone. Le processus tracé s'arrête pendant que strace fait son travail (en jetant un œil aux arguments, etc.).
Mosvy
3
pstree -p `pgrep NetworkManager`
NetworkManager(1638)─┬─dhclient(3594)
                     ├─{NetworkManager}(1645)
                     ├─{NetworkManager}(1647)
                     └─{NetworkManager}(7363)

Je pense que c'est ce que vous cherchiez.

utilisez direct pid ou pgrep avec le nom du processus.

-p utilisé pour imprimer des pids d'enfants.

Devidas
la source
Cela me laisse avec le besoin d'invoquer cette méthode périodiquement, ce qui me permet de rater des processus qui s'achèvent très rapidement.
Divyanshm
Bonne réponse cependant, mieux que mon n ° 1 :) Mais il y avait une raison pour laquelle je suis passé au n ° 2 - cela aurait le même problème
divyanshm
3

La commande pgrep sera utile. Utilisez ces commandes:

Imprimer les PID de chaque processus créé à partir de process ( $pid):

pgrep -P $pid

Pour des informations plus détaillées sur chaque processus forké, utilisez cette commande:

ps -fp `pgrep -P $pid`

$pidest votre identifiant de processus.

Finlandais
la source
-1

J'aimerais savoir quel est le meilleur moyen de déterminer la liste des processus enfants générés par ce processus parent.

En supposant que vous écrivez en bash (vous ne dites pas). Ensuite, vous pouvez utiliser le contrôle des travaux. Ceci est désactivé par défaut, lors de l'exécution de scripts.

Le manuel de bash dit:

set [--abefhkmnptuvxBCHP] [option -o] [arg ...]
...
-m Mode surveillance.
Le contrôle des tâches est activé. Cette option est activée par défaut pour les shells interactifs sur les systèmes qui le prennent en charge (voir ci-dessus CONTRÔLE DES TRAVAUX). Les processus en arrière-plan s'exécutent dans un groupe de processus séparé et une ligne contenant leur statut de sortie est imprimée à la fin.

Donc, ajoutez à votre script set -m, les commandes que vous pouvez démarrer, avec command &, puis faites-le jobspour lister les tâches.

ctrl-alt-delor
la source