Примечание Простой мысленный однострочный аппарат с kill 0, $pid
находится в конце, прокомментирован.
Нам необходимо обнаружить завершение внешней программы, которая не была запущена этим скриптом. Вопрос спрашивает об использовании waitpid
. Чтобы скопировать мой ранний комментарий:
Вы не можете. Вы можете ждать только дочернего процесса. См. perldoc wait
(или waitpid
, это то же самое), первое предложение.
wait
и waitpid
ждать сигналов, доставленных сценарий относительно судьбы своего ребенка (детей). Нет причин для сценария получать такие сигналы о процессах, которые он не запускал.
Мы знаем идентификатор процесса и его название.Его PID можно использовать для опроса для того, работает ли он. Использование pid
само по себе не является полностью надежным, так как между нашими проверками процесс может завершиться, а случайному новому присваивается то же самое pid
. Мы можем использовать название программы, чтобы укрепить это.
В системе Linux информация о процессе может быть получена путем использования (many) ps
вариантов. В любом из этих возвращений полного вызова в программах
ps --no-headers -o cmd PID
ps --no-headers -p PID -o cmd
Возвращается строка может начинаться с путем интерпретатора (для сценария Perl, например), а затем полным именем программы. Версия ps -p PID -o comm=
возвращает только имя программы, но я обнаружил, что она может сломать это слово на дефис (если есть), что приведет к неполному имени. Это может потребоваться настроить на некоторых системах, пожалуйста, проконсультируйтесь с вашим man ps
. Если нет процесса с данным PID, мы ничего не получаем.
Затем мы можем проверить PID, и если найдено, проверьте, соответствует ли имя для этого PID программе. Название программы известно, и мы можем просто сделать это жестко. Тем не менее, он по-прежнему получается скриптом по мере его запуска, используя команду ps
, чтобы избежать двусмысленностей. (Тогда это также в том же формате для последующего сравнения.) Это само проверяется на известное имя, так как нет гарантии, что PID во время выполнения скрипта действительно для ожидаемой программы.
use warnings;
use strict;
# For testing. Retrieve your PID as appropriate for real use
my $ext_pid = $ARGV[0] || $$;
my $cmd_get_name = "ps --no-headers -o cmd $ext_pid";
# For testing. Replace 'sleep' by your program name for real use
my $known_prog_name = 'sleep';
# Get the name of the program with PID
my $prog_name = qx($cmd_get_name);
# Test against the known name, exit if there is a mismatch
if ($prog_name !~ $known_prog_name) {
warn "Mismatch between:\n$prog_name\n$known_prog_name -- $!";
exit;
}
my $name;
while ($name = qx($cmd_get_name) and $name =~ /$prog_name/)
{
print "Sleeping 1 sec ... \n";
sleep 1;
}
# regex above may need slight adjustment, depending on format of ps return
Вывода команды, полученный через qx()
выше (оператор кавычки) содержит символ новой строки. Если это окажется проблемой в сценарии, это может быть chomp
-ed, что потребует небольшой корректировки. Оставшаяся лазейка заключается в том, что , что может быть закончена и перезагружена между проверками и с тем же PID.
Это будет испытана путем запуска в оболочке
sleep 30 &
script.pl `ps aux | egrep '[s]leep'`
egrep
является grep -E
. Выходной сигнал от `ps ...`
содержит несколько слов. Они передаются в качестве аргументов командной строки для нашего скрипта, который использует первый как PID. Если есть проблема с этим, сначала выполните фильтрацию ps
, а затем вручную введите PID в качестве входного аргумента скрипта. sleep
из 30 секунд выше, чтобы дать достаточно времени, чтобы сделать все это в командной строке.
Код может быть упрощен путем сопоставления $name
с жестким кодом $prog_name
, если имя программы достаточно уникально, и оно не изменится. Твердое имя - это, использованный выше, но для проверки и генерирует предупреждение, если оно несовместимо. (Если мы полагаться на него только HARDCODED мы не можем выдавать предупреждения, если он не соответствует, так как это то часть работы кода.)
Если процесс принадлежит тому же пользователю, что и сценарий можно использовать kill 0, $pid
как
while (kill 0, $ext_pid) { sleep 1 }
Тогда вы должны либо сделать еще один вызов, чтобы проверить имя или удовольствоваться (маленький) возможность ошибки в том, что сам процесс $pid
представляет.
Модуль Proc::ProcessTable
может использоваться для всего этого. В системе Windows это был бы путь.
Вы уверены, что '$ pid' - это то, что вы думаете? Что такое возвращаемое значение 'waitpid'? Он укажет, какой процесс завершен. – Schwern
@Schwern - возвращаемое значение waitpid равно -1. Это означает, что такого дочернего процесса я не думаю. И я добавил ниже строк, чтобы проверить, что $ pid запущен или нет. my $ exists = kill 0, $ pid; print «Процесс запущен \ n", если ($ существует); И он печатает заявление – user3395103
Вы не можете. Вы можете «подождать» только на дочернем процессе. См. 'Perldoc wait' (или' waitpid', это то же самое), первое предложение. Если вы хотите знать, когда завершается внешняя программа, вы должны делать совершенно разные вещи. – zdim