Я использую Ubuntu 14.04 и у меня такое поведение, которое я не могу понять:
- Запустите
yes
команду (в оболочке по умолчанию: Bash ) - Тип, CtrlZчтобы остановить
yes
- Беги
jobs
. Вывод:
[1]+ Stopped yes
- Беги,
kill -9 %1
чтобы остановитьсяyes
. Вывод:
[1]+ Stopped yes
- Беги
jobs
. Вывод:
[1]+ Stopped yes
Это на Ubuntu, 3.16.0-30-generic
работающем в виртуальной машине Parallels.
Почему моя kill -9
команда не завершила команду yes ? Я думал, что SIGKILL не может быть пойман или проигнорирован? И как я могу прекратить команду да ?
shell
job-control
s1m0n
источник
источник
uname -a
) пожалуйстаLinux ubuntu 3.16.0-30-generic #40~14.04.1-Ubuntu SMP Thu Jan 15 17:43:14 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
, Я использую Ubuntu в Parallels Desktop.(signal)
чтобы вы могли заметить разницу.Ответы:
Сигналы заблокированы для приостановленных процессов. В терминале:
Во втором терминале:
В первом терминале:
Однако
SIGKILL
не может быть заблокирован. Выполнение того же действия соkillall -9 yes
вторым терминалом немедленно дает это вyes
терминале:Следовательно, если
kill -9 %1
процесс не завершается сразу же, либоbash
вы фактически не отправляете сигнал, пока не завершитеfg
процесс, либо вы обнаружили ошибку в ядре.источник
SIGTSTP
(который является блокируемой версиейSIGSTOP
) активному процессу. Это переводит процесс в замороженное состояние, когда ядро не будет его планировать. Это также препятствует обработке сигнала (за исключениемSIGCONT
сигнала, который размораживает процесс) и, следовательно, предотвращает немедленное завершение процесса.SIGTERM
заблокировано, ноSIGKILL
нет. В любом случае, согласно комментарию от OP, проблема, похоже, заключается в том,jobs
что не обнаруживается, что процесс умер, а не процесс не был убитkill -9 %1
.SIGKILL
не может быть заблокировано, нет никакой гарантии, что оно будет доставлено в любое значимое время. Например, если процесс приостановлен в ожидании блокирующего ввода-вывода,SIGKILL
он не поступит, пока процесс не проснется. Это потенциально может быть никогда, если не происходит ввода-вывода.Не паникуйте.
В этом нет ничего прикольного. Здесь нет ошибки ядра. Это совершенно нормальное поведение оболочки Bourne Again и многозадачной операционной системы.
Следует помнить, что процесс убивает себя , даже в ответ
SIGKILL
. Здесь происходит то, что оболочка Bourne Again перебирает вещи до того, как процесс, который он только что велел убить сам, доходит до самоубийства.Подумайте, что происходит с точки, где
yes
вы остановились,SIGTSTP
и вы только что выполнилиkill
команду с оболочкой Bourne Again:SIGKILL
вyes
процесс.yes
Процесс планируется запустить и сразу же убивает себя.Причина, по которой вы видите одно, а другие видят другое, заключается в простой гонке между двумя готовыми к запуску процессами, победителем которой являются исключительно вещи, которые варьируются как от машины к машине, так и со временем. Загрузка системы имеет значение, как и факт, что ваш процессор является виртуальным.
В интересном случае деталь шага # 2 такова:
kill
команды, она помечает запись в своей таблице заданий как нуждающуюся в уведомлении, напечатанном в следующей доступной точке.kill
команду и непосредственно перед печатью снова проверяет, следует ли печатать уведомления о каких-либо заданиях.yes
процесса еще не было возможности покончить с собой, поэтому, что касается оболочки, задание все еще находится в остановленном состоянии. Таким образом, оболочка печатает строку состояния задания «Остановлено» для этого задания и сбрасывает флаг ожидания уведомления.yes
Процесс получает регулярные и убивает себя.Важными моментами являются:
SIGKILL
не волшебно Процессы проверяют наличие ожидающих сигналов при возврате в режим приложения из режима ядра, что происходит в конце ошибок страниц, (не вложенных) прерываний и системных вызовов. Единственная особенность заключается в том, что ядро не позволяет действию в ответSIGKILL
на что-либо, кроме немедленного и безусловного самоубийства, без возврата в режим приложения. Важно отметить, что процессы должны как переходить из режима ядра в режим приложения, так и быть запланированы для запуска, чтобы реагировать на сигналы.set -o notify
). Они печатаются, когда следующая оболочка достигает точки в своем цикле выполнения, которая проверяет, ожидают ли какие-либо уведомления.kill
и один разSIGCHLD
обработчиком сигнала. Это означает, что можно увидеть два сообщения, если оболочка запущена раньшеyes
запланированного процесса, чтобы убить себя; одно сообщение «Остановлено» и одно сообщение «Убито»./bin/kill
программа не имеет доступа к внутренней таблице заданий оболочки; так что вы не увидите такого поведения с/bin/kill
. Флаг ожидания уведомления устанавливаетсяSIGCHLD
обработчиком только один раз .kill
выполняетеyes
процесс из другой оболочки.источник
jobs
и оболочка все еще видит процесс как живой. Это было бы одно необычно длинное расписание гонки. :)jobs
команды умножения, послеkill
которых все еще указывают, что процесс просто остановлен. Однако вы вдохновили меня на продолжение экспериментов, и я обнаружил следующее: сообщение[1]+ Terminated yes
печатается, как только я запускаю другую внешнюю команду (а не встроенную оболочку, подобнуюecho
илиjobs
). Так что я могу бегатьjobs
столько, сколько мне нравится, и он продолжает печатать[1]+ Stopped yes
. Но как только я бегу,ls
например, Bash печатает[1]+ Terminated yes
jobs
что не замечает, что процесс на самом деле умер ... Не уверен, что делать с обновлением статуса, выполнив другую команду.Что-то странное может происходить в вашей системе, по моему ваш рецепт работает хорошо как с, так и без
-9
:Получить Пид с
jobs -p
и попытаться убить его какroot
.источник
kill
команда вашего bash делает лишнюю милю и проверяет, заморожено ли задание (вы можете попытаться узнать PID задания и уничтожить его, используяenv kill <pid>
. Таким образом, вы будете использовать реальнуюkill
команду, а не встроенную в bash.which kill /usr/bin/kill
which
не является встроенным в bash, поэтомуwhich <anything>
всегда будет указывать путь к фактической команде. Но попробуйте сравнитьkill --help
с/usr/bin/kill --help
.kill
.То, что вы наблюдаете, является ошибкой в этой версии bash.
kill -9 %1
убивает работу немедленно. Вы можете наблюдать это сps
. Вы можете отслеживать процесс bash, чтобы видеть, когдаkill
вызывается системный вызов, и отслеживать подпроцесс, чтобы видеть, когда он получает и обрабатывает сигналы. Более того, вы можете пойти и посмотреть, что происходит с процессом.В другом терминале:
Подпроцесс - это зомби . Он мертв: от него остается только запись в таблице процессов (но без памяти, кода, открытых файлов и т. Д.). Запись остается до тех пор, пока ее родитель не заметит и не получит статус выхода, вызвав
wait
системный вызов или одного из своих братьев и сестер .Предполагается, что интерактивная оболочка проверяет наличие мертвых детей и собирает их перед печатью приглашения (если не указано иное). Эта версия bash не может сделать это при некоторых обстоятельствах:
Вы можете ожидать, что bash сообщит «Killed», как только напечатает приглашение после
kill
команды, но это не гарантировано, потому что есть условие гонки. Сигналы доставляются асинхронно:kill
системный вызов возвращается, как только ядро выяснило, в какой процесс (ы) доставить сигнал, не дожидаясь его фактической доставки. Возможно, и на практике это происходит, когда bash успевает проверить состояние своего подпроцесса, обнаружить, что он все еще не мертв (wait4
не сообщает о смерти ребенка), и напечатать, что процесс все еще остановлен. Что неправильно, так это то, что перед следующим приглашением сигнал был доставлен (ps
сообщает, что процесс мертв), но bash все еще не вызвалwait4
(мы видим это не только потому, что он по-прежнему сообщает о задании как «Остановлено», но и потому, что зомби все еще присутствует в таблице процессов). На самом деле, bash получает зомби только в следующий разwait4
, когда ему нужно позвонить , когда он запускает какую-то другую внешнюю команду.Ошибка периодически, и я не мог воспроизвести ее, пока отслеживается bash (возможно, потому что это состояние гонки, где bash должен реагировать быстро). Если сигнал доставляется до bash-проверок, все происходит как положено.
источник