Як слід перевірити, чи працює даний PID?


16

Я пишу сценарій Perl, який аналізує логіни для збору PID, а потім перевіряє, чи працює цей PID. Я намагаюся придумати найкращий спосіб зробити цю перевірку. Очевидно, я міг би зробити щось на кшталт:

system("ps $pid > /dev/null") && print "Not running\n";

Однак я вважаю за краще уникати системного дзвінка, якщо це можливо. Тому я думав, що можу використовувати /procфайлову систему (портативність не викликає занепокоєнь, це завжди буде працювати в системі Linux). Наприклад:

if(! -d "/proc/$pid"){
    print "Not running\n";
}

Це безпечно? Чи можу я завжди вважати, що якщо немає /proc/$pid/каталогу, пов'язаний PID не працює? Я очікую цього, оскільки AFAIK psсам отримує свою інформацію з /procбудь-якого випадку, але оскільки це стосується виробничого коду, я хочу бути впевненим.

Отже, чи можуть бути випадки, коли запущений процес не має /proc/PIDкаталогу, або де /proc/PIDкаталог існує, а процес не працює? Чи є якась причина віддавати перевагу розбору psнад перевіркою на наявність каталогу?


2
є також killфункція perl, використовуючи сигнал 0, який не вбиває, але каже, якщо ви могли це зробити (тобто вам потрібен дозвіл, щоб подати сигнал про цей процес).
meuh

1
'/ proc / $ PID' має бути добре, якщо ви робите це в Linux.
likewhoa

7
@terdon Зауважте, що який би метод ви не використовували (і kill -0це найкращий), це говорить лише про те, чи є запущений процес із заданим PID . Це не говорить про те, чи буде процес все ще запускатися на одну мілісекунду пізніше, і не говорить вам, чи є процес, який вас цікавить, або незв'язаний процес, якому було призначено той самий PID після того, як цікавий процес загинув . Практично завжди є помилкою перевірити, чи працює даний ПІД : дуже мало обставин, коли це не схильне до перегонів.
Жил 'ТАК - перестань бути злим'

1
@Gilles дійсно, я також повинен перевірити назву процесу. Однак у цьому випадку мені байдуже, чи зміниться стан мілісекунди пізніше. У мене процеси, перелічені як активні в дБ, і відповідний файл з підами. Мені просто потрібно перевірити, чи щось, на думку БД, працює, насправді не працює і мати достатній контроль над налаштуванням, щоб знати, що він не може запуститися знову випадковим чином.
terdon

3
@MickLH вау, це мені сказали. Це насправді було б корисним коментарем замість святкування вашої власної блиску, якби ви намагалися пояснити, що так погано і небезпечно. Я не сумніваюся, що ти маєш рацію, я ніколи не претендував на те, що я програміст, саме тому я задав це питання, але ти зумів бути і образливим, і негідним.
terdon

Відповіді:


20

Функція perl kill(0,$pid)може бути використана.

Якщо код повернення дорівнює 1, то PID існує, і вам дозволяється надсилати сигнал на нього.

Якщо код повернення дорівнює 0, вам потрібно перевірити $ !. Це може бути EPERM (у дозволі відмовлено), що означає, що процес існує або ESRCH, у цьому випадку процес не існує.

Якщо ваш перевіряючий код працює так, rootви можете спростити це до просто перевірки повернення коду вбивства; 0 => помилка, 1 => ок

Наприклад:

% perl -d -e 0

Loading DB routines from perl5db.pl version 1.37
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::(-e:1):   0
  DB<1> print kill(0,500)
0
  DB<2> print $!
No such process
  DB<3> print kill(0,1)
0
  DB<4> print $!
Operation not permitted
  DB<5> print kill(0,$$)
1

Це можна перетворити на просту функцію

use Errno;

sub test_pid($)
{
  my ($pid)=@_;

  my $not_present=(!kill(0,$pid) && $! == Errno::ESRCH);

  return($not_present);
}

print "PID 500 not present\n" if test_pid(500);
print "PID 1 not present\n" if test_pid(1);
print "PID $$ not present\n" if test_pid($$);

FWIW, я додав просту функцію, яка показує, як ви можете це зробити.
Стівен Харріс

Так, я думаю, я піду з цим. Я видалив свій коментар, оскільки зрозумів, що все, що мені потрібно, було if (!kill(0,$pid) && $! =~ /No such process/){ exit; }подібне. Мені більше подобається ваше Errnoрішення, дякую. Хоча я, мабуть, піду з цим, я зачекаю деякий час, якщо хтось зможе відповісти на основне питання Linux.
terdon

2
Якщо /procвін встановлений, то кожен PID, видимий у просторі імен, буде присутній, тож ваш -d /proc/$pidтест спрацював би ... але він передбачає вихід у файлову систему, а не використання викликів системи.
Стівен Харріс

Саме цього я хотів уникнути, так.
terdon

2
@terdon: Я щойно зрозумів, що моя плутанина пов'язана з тим, що під "системним викликом" ви насправді мали на увазі " systemдзвінок" - тобто виклик самої systemфункції, а не "системний виклик" . Останнього ви не можете уникнути, але перше ви, безумовно, можете. Має сенс зараз!
користувач541686

6
  • Я на 99,9% впевнений, що перевірка наявності (і чи є каталогу) 98% настільки ж надійна, як і техніка. Причина, чому 98% не є 100%, - це те, що Стівен Харріс торкнувся (і відскочив) у коментарі, а саме - файлова система може бути встановлена. Це може бути дійсним для затвердження , що система Linux не є пошкодженим, деградує система - в кінці кінців, речі , як , і , ймовірно , не працюватиме - і тому це може не бути проблемою для виробничої системи. Але це (теоретично) можливо, що він ніколи не був змонтований (хоча це може перешкодити приведенню системи в нормальний стан), безумовно, можливе її відключення (я протестував це 1/proc/PIDkill 0/proc/procpstoplsof), і я вважаю, що немає жодної гарантії існування (тобто POSIX не вимагається). І, якщо система повністю не killбуде розміщена, запрацює.
  • У коментарі Стівена йдеться про "вихід у файлову систему" та "використання нативних системних дзвінків". Я вважаю, що це багато в чому червона оселедець.
    • Так, будь-яка спроба доступу /proc вимагає читання кореневого каталога , щоб знайти в /procфайлової системі. Це вірно для будь-якої спроби отримати доступ до будь-якої файл, повне складене ім'я, в тому числі речей , в /bin, /etcі /dev. Це трапляється так часто, що кореневий каталог, безумовно, зберігається в пам’яті протягом усього життя (часу роботи), тому цей крок можна зробити без жодного дискового вводу-виводу. І, як тільки у вас є індея /proc, все інше, що відбувається, залишається в пам'яті.
    • Як ви отримуєте доступ /proc? З stat, open, readdirі т.д., які є рідні системних викликів кожен біт стільки , скільки kill.
  • Питання говорить про запущений процес. Це слизька фраза. Якщо ви на справді хочете перевірити , чи є процес запущений (тобто, в черзі виконання, може бути , поточний процес на деякому процесорі, не спить, чекаючи, чи зупинений), ви , можливо , доведеться робити і читати висновок , чи подивитися на . Але я не бачу жодного натяку у вашому запитанні чи коментарях, що вас це хвилює.ps PID /proc/PID/stat

    Однак слон у кімнаті полягає в тому, що процес зомбі 2 важко відрізнити від живого і здорового процесу.  kill 0працює на зомбі, і існує. Ви можете ототожнити зомбі за допомогою технік, перелічених у попередньому пункті (робити та читати результати, або дивитись ). Мій дуже швидко і випадковим (тобто, не дуже ретельно) тестування передбачає , що ви можете зробити це робити або на , або - вони будуть терпіти невдачу на зомбі. (Однак вони також не працюватимуть у процесах, якими ви не володієте.)/proc/PIDps PID/proc/PID/statreadlinklstat/proc/PID/cwd/proc/PID/root/proc/PID/exe

____________
1,  якщо варіант -f( f orce) не працює, спробуйте -l( l azy).
2,  тобто процес, який закінчився / помер / закінчився, але батько якого ще не зробив wait.


Дякуємо за Ваш коментар до моєї відповіді, яку я видалив, оскільки вона була неправильною. Я не вірю, що сторінка kill(2)вказує безпосередньо на поведінку, на яку ви вказали, але ця сторінка perlfuncробить. Я надішлю електронній пошті Майклу Керріску, щоб побачити, що він має сказати про системну сторінку.
jrw32982 підтримує Моніку

Я подав звіт про помилку, щоб уточнити kill(2)
довідкову

@ jrw32982: Що ж, сторінка man каже: "Аргумент sig ... може бути 0; у цьому випадку перевірка помилок виконується ..." та " ПОМИЛКИ - системний виклик kill () не вдасться, і сигнал не надсилатиметься, якщо: … Процес відправки не є суперкористувачем, і його ефективний ідентифікатор користувача не відповідає ефективному ідентифікатору користувача в процесі отримання. ... ”Тепер, коли ви це згадуєте, я вважаю, що це можна інтерпретувати не одним способом, але, на жаль, багато сторінок Unix написані в цьому стилі, що вимагає читати між рядків. Майкл може вважати, що це досить зрозуміло, як є.
G-Man каже: "Відновіть Моніку"

Майкл вніс зміни до сторінки сторінки kill(2)(я її ще не бачу в Інтернеті): "Якщо sig - 0, то сигнал не надсилається, але перевірки існування та дозволу все ще виконуються; це можна використовувати для перевірки наявності ідентифікатор процесу або ідентифікатор групи процесу, про який дозволений абонент може подавати сигнал. "
jrw32982 підтримує Моніку
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.