Comment get l'ID du travail?

Comme nous le soaps, le shell permet à l'user d'exécuter des process d'arrière-plan en utilisant & à la fin de la command line. Chaque process d'arrière-plan est identifié par un ID de travail et, bien sûr, par son PID.

Lorsque j'exécute un nouveau travail, la sortie est quelque chose comme [1] 1234 (le deuxième numéro est l'ID du process). Essayer d'appeler des commands comme l' stop 1 et l' stop %1 provoque un message d'erreur: stop: Unknown job: 1

Comprenant que la command stop provoque la suspension d'un travail, je me demandais comment get l'ID du travail et le faire correctement. Si le seul moyen de tuer un travail est son ID de process, quel est le but de l'ID du travail ?

Après qu'un process est envoyé en arrière-plan avec & , son PID peut être récupéré à partir de la variable $! . Les ID de travail peuvent être affichés à l'aide de la command jobs , le commutateur -l affiche également le PID.

  $ sleep 42 & [1] 5260 $ echo $! 5260 $ jobs -l [1] - 5260 running sleep 42 

Certaines implémentations de kill permettent de tuer par ID de travail au lieu de PID. Mais une utilisation plus judicieuse de l'ID du travail consiste à mettre en avant sélectivement un process particulier. Si vous démarrez cinq process en arrière-plan et que vous souhaitez mettre en avant le troisième, vous pouvez exécuter la command jobs pour voir les process que vous avez lancés, puis fg %3 pour mettre en avant celui avec l'ID de travail trois.

Le contrôle des travaux est une fonctionnalité qui a été ajoutée aux systèmes BSD au début des années 80. csh étant le shell BSD, il n'est pas surprenant que la fonctionnalité ait été introduite dans cette shell en premier. Il a fallu attendre plusieurs années avant que le contrôle du travail soit ajouté aux Unices non-BSD et aux autres shells (à commencer par le shell Korn).

Il est à noter que le contrôle de travail n'est pas la capacité de démarrer un process de façon asynchronous (c'est-à-dire que le shell n'attend pas sa terminaison avant d'émettre l'invite suivante; 10 ans plus tard), mais sur la capacité d'interagir avec plusieurs tâches du même terminal.

Nous parlons d' emplois , pas de process . Pour mettre en œuvre le contrôle des tâches, des groupes de process ont été introduits. Un travail est un groupe de process ( travail du sharepoint vue de l'user, groupe de process du sharepoint vue de la mise en œuvre du operating system).

Il s'agit généralement de coquilles interactives qui créent et gèrent des groupes de process, et encore une fois, il s'agit d'interaction avec le terminal.

Lorsque vous exécutez une command, tous les process et leurs descendants sont placés dans un nouveau groupe de process.

Dans une session sur un terminal donné, un groupe de process bénéficie d'un access privilégié au terminal. C'est le groupe de process de premier plan du terminal. Ce groupe de process est celui dont les membres reçoivent un SIGINT / SIGTSTP / SIGQUIT lorsque vous appuyez sur CTRL- {C, Z, \} . Les process des autres groupes de process sont suspendus lorsqu'ils essaient de lire (et parfois d'écrire) sur le terminal. etc.

Lorsque vous démarrez un travail en avant-plan, le shell interactif fait en sorte que son groupe de process soit le groupe de process de premier plan du terminal et non ceux qui sont démarrés en arrière-plan.

De cette façon, un user peut faire plusieurs choses à la fois dans un terminal, il peut avoir une list de tâches, qui sont des groupes de process qui peuvent être au premier plan (avec un access privilégié au terminal), en arrière-plan, en cours d'exécution ou suspendus. Et le travail peut être déplacé de / vers l'arrière-plan / premier plan et suspendu / en cours d'exécution.

De nos jours, tous les systèmes et tous les shells prennent en charge le contrôle des tâches (bien que dans le shell Bourne, vous devez explicitement le requestr avec set -m IIRC).

Toutes les commands démarrées à l'invite reçoivent un numéro de travail. Du sharepoint vue du système, ceux-ci sont mappés pour traiter les identifiants de groupe.

  $ ps -fj | cat UID PID PPID PGID SID C STIME TTY TIME CMD chazelas 8237 7315 8237 8237 0 15:54 pts/7 00:00:00 /bin/zsh chazelas 10720 8237 10720 8237 0 21:25 pts/7 00:00:00 ps -fj chazelas 10721 8237 10720 8237 0 21:25 pts/7 00:00:00 cat 

Au-dessus, j'ai commencé ce ps -j | cat travail de ps -j | cat au premier plan. Il a été affecté au groupe de process 10720 (qui se trouve être l'identifiant de process de ps ). Si vous aviez interrogé l'identifiant de groupe de process au premier plan du terminal au moment où ceux-ci étaient exécutés (avec tcgetpgrp() ), vous auriez obtenu 10720.

 $ (sleep 100;:) | sleep 101 & [1] 10787 10789 $ ps -fj UID PID PPID PGID SID C STIME TTY TIME CMD chazelas 8237 7315 8237 8237 0 15:54 pts/7 00:00:00 /bin/zsh chazelas 10787 8237 10787 8237 0 21:33 pts/7 00:00:00 /bin/zsh chazelas 10788 10787 10787 8237 0 21:33 pts/7 00:00:00 sleep 100 chazelas 10789 8237 10787 8237 0 21:33 pts/7 00:00:00 sleep 101 chazelas 10790 8237 10790 8237 0 21:33 pts/7 00:00:00 ps -fj 

Cette fois, j'ai commencé un pipeline en arrière-plan. Le shell m'a donné un numéro de tâche (1) et 2 identifiants de process (t)csh , pdksh et zsh donnent tous les identifiants de process, le comportement varie dans d'autres shells), un pour un sous-shell, un pour le sleep 101 . Par ailleurs, ce sous-marin a engendré un troisième process ( sleep 100 ). Le shell n'a pas signalé le pid de celui-ci parce qu'il n'en sait rien, mais il fait toujours partie du même travail (groupe de process 10787 ci-dessus).

Maintenant, vous avez quelques commands pour manipuler ces tâches: fg , bg , kill , wait et jobs (certaines coquilles ont aussi un disown et des alias à kill pour envoyer un signal par défaut différent).

Ceux-ci prennent les identifiants de travail dans le format de %nn est le numéro de travail. Il y a %foo pour faire reference au travail dont la command commence par foo , et plus encore (voir le manuel de votre shell).

 kill %1 

envoie le signal SIGTERM à tous les process du travail 1. kill -s STOP %1 parfois aliasé pour stop envoie le signal SIGSTOP la place.

 fg %1 

le met au premier plan (il en fait le groupe de traitement au premier plan du terminal, envoie le signal SIGCONT et dit au shell d'attendre son achèvement).

 bg %1 

reprend (envoie un SIGCONT) un travail d'arrière-plan arrêté.

 wait %1 

ne met pas le travail au premier plan, mais attend son achèvement (ou jusqu'à ce qu'il soit suspendu).

 jobs 

répertorie les travaux en cours ( jobs -l avec pgids et / ou pids).

%% et %+ rapportent au travail en cours. Il convient de noter que le travail actuel n'est pas nécessairement le travail le plus récemment commencé. C'est le travail marqué par un + dans la production des jobs . C'est aussi le travail que fg ou bg sans argument traiter. Il s'agit du travail suspendu le plus récemment s'il y en a un suspendu, ou le plus récemment lancé s'il est en cours d'exécution.

Alors, attention kill %% ne va pas tuer le travail que vous venez de lancer en arrière-plan s'il y a des tâches suspendues. C'est toujours une bonne idée d'exécuter des jobs pour voir quels travaux sont en cours d'exécution avant d'en tuer.

Il convient de noter que vous ne devez pas utiliser les ID de process lorsque vous traitez avec des tâches.

$! renvoie l'identifiant de process de cette dernière command exécutée en arrière-plan. Dans le cas d'un pipeline, c'est le pid de la command la plus à droite.

 $ sleep 100 | sleep 101 & ps -fj; echo "$!" [1] 11044 11045 UID PID PPID PGID SID C STIME TTY TIME CMD chazelas 8237 7315 8237 8237 0 15:54 pts/7 00:00:00 /bin/zsh chazelas 11044 8237 11044 8237 0 22:08 pts/7 00:00:00 sleep 100 chazelas 11045 8237 11044 8237 0 22:08 pts/7 00:00:00 sleep 101 chazelas 11046 8237 11046 8237 0 22:08 pts/7 00:00:00 ps -fj 11045 

Au-dessus de $! est 11045, mais le groupe de process du travail 1 est 11044. Si je kill "$1" , je vais tuer seulement sleep 101 , pas sleep 100 . Si je kill -- "-$!" (c'est-à-dire tuer tous les process du groupe de process 11045), cela échouera car il n'y a pas de groupe de process.

Là, vous voulez utiliser kill %1 (ou kill %sleep ou éventuellement kill %% ) pour tuer ce job (qui fera un kill -- -11044 ).

Il semble que lorsque vous avez tapé stop , vous étiez en train d'exécuter la command fournie avec upstart , qui n'est pas liée aux commands d' stop inhérentes csh ou ksh que vous connaissez. Donc, son message d'erreur concernant un "travail inconnu" ne s'applique pas à ce que vous essayiez de faire.

ksh implémente l' stop en tant qu'alias pour kill -s STOP , qui comprend la notation %n pour les jobs ou les ID de groupe de process. Cet alias fonctionnera également dans d'autres shells, par exemple si votre shell est bash :

 $ alias stop='kill -s STOP' $ sleep 30& [3] 9820 $ stop %3 [3]+ Stopped sleep 30