Как получить идентификатор задания?

Как известно, оболочка позволяет пользователю запускать фоновые процессы, используя & в конце командной строки. Каждый фоновый процесс идентифицируется идентификатором задания и, конечно же, его PID.

Когда я выполняю новое задание, результат выглядит как [1] 1234 (второе число – идентификатор процесса). При попытке вызвать команды, такие как stop 1 и stop %1 появляется сообщение об ошибке: stop: Unknown job: 1

Понимая, что команда stop приводит к приостановке задания, мне было интересно, как получить идентификатор задания и сделать это правильно. Если единственный способ убить работу – это идентификатор процесса, какова цель идентификатора задания ?

3 Solutions collect form web for “Как получить идентификатор задания?”

После того, как процесс отправлен на задний план с помощью & , его ПИД можно получить из переменной $! , Идентификаторы заданий могут отображаться с помощью команды jobs , в -l переключателе также отображается PID.

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

Некоторые kill позволяют убивать по идентификатору задания вместо PID. Но более разумным использованием идентификатора задания является выборочный подход к конкретному процессу. Если вы запустили пять процессов в фоновом режиме и хотите перенести третий, вы можете запустить команду jobs чтобы посмотреть, какие процессы вы запускали, а затем fg %3 чтобы задать приоритет с идентификатором задания три.

Управление заданиями – это функция, которая была добавлена ​​в BSD-системы в начале 80-х годов. csh является оболочкой BSD, неудивительно, что функция была впервые введена в этой оболочке. Вы должны были ждать несколько лет, прежде чем управление заданиями было добавлено в UnBD Unices и в другие оболочки (начиная с оболочки Korn).

Следует отметить, что управление заданиями – это не возможность запуска процесса асинхронно (то есть с оболочкой, не ожидающей ее завершения до выдачи следующего приглашения, оболочка Bourne имела & с самого начала, но не поддерживала контроль работы до тех пор, пока 10 лет спустя), но и о способности взаимодействовать с несколькими задачами из одного терминала.

Мы говорим о работе , а не о процессах . Для реализации контроля за работой были представлены группы процессов . Задание – это группа процессов ( задание с точки зрения пользователя, группа процессов с точки зрения реализации ОС).

Обычно это интерактивные оболочки, которые создают и управляют группами процессов, и снова это все о взаимодействии с терминалом.

Когда вы запускаете команду, все процессы и их потомки помещаются в новую группу процессов.

В сеансе на данном терминале одной группе процессов предоставляется привилегированный доступ к терминалу. Это основная группа процессов терминала. Эта группа процессов является той, чьи члены получают SIGINT / SIGTSTP / SIGQUIT, когда вы нажимаете CTRL- {C, Z, \} . Процессы в других группах процессов приостанавливаются, когда они пытаются читать терминал (и когда-то писать). и т.п.

Когда вы начинаете работу на переднем плане, интерактивная оболочка делает свою группу процессов группой процессов переднего плана терминала, а не для тех, которые начинаются в фоновом режиме.

Таким образом, пользователь может выполнять несколько операций за раз в терминале, он может иметь список заданий, которые представляют собой группы процессов, которые могут находиться на переднем плане (с привилегированным доступом к терминалу), фон, запуск или приостановление. И работа может быть перемещена с / на фон / переднем плане и приостановлена ​​/ запущена.

В настоящее время все системы и все оболочки поддерживают управление заданиями (хотя в оболочке Bourne вы должны явно запрашивать ее с помощью set -m IIRC).

Все команды, запущенные в строке, получают номер задания. С системной точки зрения они отображаются на идентификаторы групп процессов.

  $ 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 

Выше я начал, что ps -j | cat работа ps -j | cat на переднем плане. Ему была назначена группа процессов 10720 (которая также является идентификатором процесса ps ). Если бы вы запросили идентификатор группы процессов переднего плана терминала в тот момент, когда они запущены (с помощью tcgetpgrp() ), вы получили бы 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 

В то время я начал конвейер в фоновом режиме. Оболочка дала мне номер задания (1) и 2 идентификатора процесса ( (t)csh , pdksh и zsh дает все идентификаторы процесса, поведение меняется в других оболочках), одно для подоболочки, одно для sleep 101 . Кстати, эта подоболочка породила третий процесс ( sleep 100 ). Оболочка не сообщила pid этого, потому что она ничего не знает об этом, но она по-прежнему является частью одной и той же работы (группа процессов 10787 выше).

Теперь у вас есть несколько команд для управления этими заданиями: fg , bg , kill , wait и jobs (в некоторых оболочках также отключены и псевдонимы, чтобы kill чтобы отправить другой сигнал по умолчанию).

Те принимают идентификаторы работы в формате %n где n – номер задания. Существует %foo для ссылки на задание, чья команда начинается с foo и т. Д. (См. Руководство вашей оболочки).

 kill %1 

посылает сигнал SIGTERM ко всем процессам задания 1. kill -s STOP %1 когда-то сглаживается, чтобы stop отправку сигнала SIGSTOP .

 fg %1 

ставит его на передний план (делает его группой процесса переднего плана терминала, отправляет сигнал SIGCONT и сообщает оболочке ждать ее завершения).

 bg %1 

возобновляет (отправляет SIGCONT) прекращенное фоновое задание.

 wait %1 

не ставит задачу на передний план, но ждет ее завершения (или до ее приостановки).

 jobs 

перечисляет текущие задания ( jobs -l с pgids и / или pids).

%% и %+ относятся к текущему заданию. Следует отметить, что текущая работа не обязательно является самой последней запущенной работой. Это задание, помеченное знаком « + в jobs . Это также работа, с которой fg или bg без аргумента. Это самая недавняя приостановленная работа, если есть приостановленные или недавно запущенные, если они все запущены.

Итак, будьте осторожны, kill %% не собирается убивать задание, которое вы только что начали в фоновом режиме, если есть приостановленные задания. Всегда полезно запускать jobs чтобы увидеть, какие рабочие задания в настоящее время запущены до их убийства.

Следует отметить, что вы не должны использовать идентификаторы процессов при работе с заданиями.

$! возвращает идентификатор процесса последней команды, выполняемой в фоновом режиме. В случае с конвейером это pid самой правой команды.

 $ 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 

Выше $! это 11045, но группа процессов 1 – это 11044. Если я kill "$1" , я собираюсь убить только sleep 101 , а не sleep 100 . Если я kill -- "-$!" (то есть уничтожить все процессы в группе процессов 11045), это не сработает, потому что нет такой группы процессов.

Там вы хотите использовать kill %1 (или kill %sleep или, возможно, kill %% ), чтобы убить это задание (которое сделает kill -- -11044 ).

Похоже, когда вы набрали stop , вы на самом деле выполняли команду, которая поставляется с upstart , которая не связана с командами stop csh или ksh , с которыми вы знакомы. Поэтому сообщение об ошибке «Неизвестная работа» не относится к тому, что вы пытались сделать.

ksh реализует stop как псевдоним для kill -s STOP , который понимает нотацию %n для заданий или идентификаторов групп процессов. Этот псевдоним будет работать и в других оболочках, например, если ваша оболочка bash :

 $ alias stop='kill -s STOP' $ sleep 30& [3] 9820 $ stop %3 [3]+ Stopped sleep 30 
Linux и Unix - лучшая ОС в мире.