Як я можу вбити процес і переконатися, що PID не використовувався повторно


40

Припустимо, наприклад, у вас є сценарій оболонки, подібний до:

longrunningthing &
p=$!
echo Killing longrunningthing on PID $p in 24 hours
sleep 86400
echo Time up!
kill $p

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


3
Ви впевнені, що якщо ваш цілеспрямований процес загине, він вбиває вбивцю в процесі.
mikeserv

2
Використовуйте killallвідповідність по імені, так що ви принаймні вбиваєте лише процес з такою ж назвою, як longrunningthing. Якщо припустити, що у вас буде працювати лише один із них.
LawrenceC

8
Ви можете зберегти час початку оригінального процесу і, перш ніж вбивати, перевірити, чи відповідає час запуску процесу із цим під, тому що ви зберегли. Пара pid, час початку - це унікальний ідентифікатор процесів у Linux.
Бакуріу

1
Чи можу я запитати, навіщо вам це потрібно? що є фундаментальним, що ви намагаєтесь досягти? (щось, що працює постійно, але скидається кожні 24 години?)
Олів'є Дулак,

2
@mikeserv Процес не може гарантувати, що щось трапиться у випадку власної смерті.
kasperd

Відповіді:


29

Найкраще було б використовувати timeoutкоманду, якщо у вас є її, яка призначена для цього:

timeout 86400 cmd

Поточна (8.23) реалізація GNU, щонайменше, працює з використанням alarm()або еквіваленту під час очікування дочірнього процесу. Схоже, це не захищає від SIGALRMдоставки між waitpid()поверненням та timeoutвиходом (фактично скасовуючи цю тривогу ). Під час цього невеликого вікна timeoutможна навіть писати повідомлення на stderr (наприклад, якщо дитина скинув ядро), що ще більше збільшило б це вікно гонки (нескінченно, якщо, наприклад, stderr - це повна труба).

Я особисто можу жити з таким обмеженням (яке, мабуть, буде зафіксовано в наступній версії). timeoutВи також докладете уваги, щоб повідомити про правильний стан виходу, обробляти інші кутові випадки (наприклад, SIGALRM заблокований / проігнорований під час запуску, обробляти інші сигнали ...) краще, ніж вам, напевно, вдасться зробити вручну.

Як наближення, ви можете записати це perlтак:

perl -MPOSIX -e '
  $p = fork();
  die "fork: $!\n" unless defined($p);
  if ($p) {
    $SIG{ALRM} = sub {
      kill "TERM", $p;
      exit 124;
    };
    alarm(86400);
    wait;
    exit (WIFSIGNALED($?) ? WTERMSIG($?)+128 : WEXITSTATUS($?))
  } else {exec @ARGV}' cmd

Існує timelimitкоманда на веб- сайті http://devel.ringlet.net/sysutils/timelimit/ (раніше GNU timeout- кілька місяців).

 timelimit -t 86400 cmd

Цей використовується alarm()механізм -подобний, але встановлює обробник SIGCHLD(ігноруючи зупинених дітей), щоб виявити, що дитина гине. Він також скасовує будильник перед запуском waitpid()(який не скасовує доставку, SIGALRMякщо він був у очікуванні, але так, як написано, я не можу побачити, що це проблема) і вбиває перед викликом waitpid()(тому не можу вбити повторно використаний pid ).

netpipes також має timelimitкоманду. Цей передує всім іншим за десятиліття, використовує ще один підхід, але не працює належним чином для зупинених команд і повертає 1статус виходу після таймауту.

В якості більш прямої відповіді на ваше запитання ви можете зробити щось на кшталт:

if [ "$(ps -o ppid= -p "$p")" -eq "$$" ]; then
  kill "$p"
fi

Тобто перевірте, чи процес все ще є нашою дитиною. Знову ж таки, є невелике вікно для перегонів (між тим, як psотримати статус цього процесу та killвбити його), під час якого процес може загинути, а його під буде повторно використаний іншим процесом.

З деякими оболонками ( zsh, bash, mksh), ви можете передати функції завдання замість ИДП.

cmd &
sleep 86400
kill %
wait "$!" # to retrieve the exit status

Це працює лише в тому випадку, якщо ви нерестуєте лише одну фонову роботу (інакше отримати потрібну роботуспеціалу не завжди можливо надійно).

Якщо це проблема, просто запустіть новий екземпляр оболонки:

bash -c '"$@" & sleep 86400; kill %; wait "$!"' sh cmd

Це працює, тому що оболонка видаляє роботу з таблиці роботи, коли дитина помирає. Тут не повинно бути жодного вікна гонки, оскільки до моменту виклику оболонки kill()або сигнал SIGCHLD не обробляється, і pid не може бути використаний повторно (оскільки його не чекали), або його обробляли і завдання було видалено з таблиці процесів (і killповідомило б про помилку). bash«S по killкрайней мере блоків SIGCHLD , перш ніж він отримує доступ до таблиці завдань , щоб розширити %і розблокує його після kill().

Інший варіант, щоб уникнути того, щоб sleepпроцес висів навколо, навіть після того, як cmdвін помер, з bashабо ksh93використовувати трубу, read -tа не sleep:

{
  {
    cmd 4>&1 >&3 3>&- &
    printf '%d\n.' "$!"
  } | {
    read p
    read -t 86400 || kill "$p"
  }
} 3>&1

У цього ще є умови перегонів, і ви втрачаєте статус виходу команди. Він також передбачає, cmdщо не закриває свій fd 4.

Ви можете спробувати реалізувати рішення без гонок у такому perlвигляді:

perl -MPOSIX -e '
   $p = fork();
   die "fork: $!\n" unless defined($p);
   if ($p) {
     $SIG{CHLD} = sub {
       $ss = POSIX::SigSet->new(SIGALRM); $oss = POSIX::SigSet->new;
       sigprocmask(SIG_BLOCK, $ss, $oss);
       waitpid($p,WNOHANG);
       exit (WIFSIGNALED($?) ? WTERMSIG($?)+128 : WEXITSTATUS($?))
           unless $? == -1;
       sigprocmask(SIG_UNBLOCK, $oss);
     };
     $SIG{ALRM} = sub {
       kill "TERM", $p;
       exit 124;
     };
     alarm(86400);
     pause while 1;
   } else {exec @ARGV}' cmd args...

(хоча це потребує вдосконалення для обробки інших видів кутових справ).

Інший метод без раси може використовувати групи процесів:

set -m
((sleep 86400; kill 0) & exec cmd)

Однак зауважте, що використання груп процесів може мати побічні ефекти, якщо є введення-виведення для термінального пристрою. Це має додаткову вигоду, хоча знищити всі інші зайві процеси, породжені цим cmd.


4
Чому б спочатку не згадати найкращий метод?
дельтаб

2
@deltab: timeoutне є портативним, у відповіді спочатку згадується портативне рішення.
cuonglm

1
@deltab: це дає уявлення про те, як все працює, і особливо, як підхід "здорового глузду" може зазнати невдач (Стефан вважає за краще навчити спочатку рибалити, що мені подобається). Один, як очікується, прочитає всю відповідь
Олів'є Дулак

@Stephane: для "отримання потрібних робочих місць не завжди можливо надійно": ви не можете спочатку порахувати результат, jobsа потім знати, що (як це ваша власна оболонка, в якій ви маєте контроль над тим, що буде далі), наступний фон робота буде N + 1? [тоді ви можете зберегти N, а пізніше вбити% N + 1])
Олів'є Дулак

1
@OlivierDulac, це припускає, що жодна минула робота не припиняється до моменту початку нової (оболонки повторно використовують номери завдань).
Стефан Шазелас

28

Взагалі, не можна. Усі відповіді, що даються дотепер, - це невдала евристика. Є лише один випадок, коли ви можете сміливо використовувати під для надсилання сигналів: коли цільовий процес є прямим дочірнім процесом, який буде надсилати сигнал, а батьків ще не дочекався його. У цьому випадку, навіть якщо він вийшов, під зарезервується (ось що таке "процес зомбі"), поки батько не чекає на нього. Я не знаю жодного способу зробити це чисто із шкаралупою.

Альтернативний безпечний спосіб вбити процеси - це запустити їх з керуючого tty, встановленого на псевдотерміналі, для якого ви володієте стороною master. Потім ви можете надсилати сигнали через термінал, наприклад, записувати символ для SIGTERMабо SIGQUITбільше pty.

Ще один спосіб, зручніший для сценаріїв, - це використовувати названий screenсеанс і надсилати команди на екрані, щоб закінчити його. Цей процес відбувається через трубу або unix-сокет, названий відповідно до екранного сеансу, який автоматично не буде повторно використаний, якщо вибрати безпечне унікальне ім’я.


4
Я не бачу, чому цього не можна було зробити в оболонках. Я дав кілька рішень.
Стефан Шазелас

3
Скажіть, будь ласка, пояснення та якусь кількісну дискусію щодо вікон гонок та інших недоліків? Без цього "Всі відповіді, що даються на даний момент, - це евристика баггі", є просто необгрунтованою конфронтацією без жодних переваг.
петерф

3
@peterph: Загалом, будь-яке використання pid - це гонка TOCTOU - незалежно від того, як ви перевіряєте, чи все ще посилається на той самий процес, на який ви очікуєте посилання, він може перестати посилатися на цей процес і посилатися на якийсь новий обробляти в інтервалі перед тим, як використовувати його (відправлення сигналу). Єдиний спосіб запобігти цьому - це можливість блокувати звільнення / повторне використання pid, і єдиний процес, який може це зробити, - це безпосередній батьків.
Р ..

2
@ StéphaneChazelas: Як завадити шкаралупі чекати на під фоновому процесі, який завершився? Якщо ви можете це зробити, проблема легко вирішується у разі потреби ОП.
Р ..

5
@peterph: "Вікно гонки невелике" - це не рішення. І рідкість гонки залежить від послідовного присвоєння pid. Помилки, які викликають щось дуже погане, трапляються раз на рік, набагато гірші, ніж помилки, які трапляються постійно, тому що їх практично неможливо діагностувати та виправити.
Р ..

10
  1. Під час запуску збережіть час його початку:

    longrunningthing &
    p=$!
    stime=$(TZ=UTC0 ps -p "$p" -o lstart=)
    
    echo "Killing longrunningthing on PID $p in 24 hours"
    sleep 86400
    echo Time up!
    
  2. Перш ніж спробувати вбити процес, зупиніть його (це не справді важливо, але це спосіб уникнути перегонів: якщо ви зупините процес, його не можна використовувати повторно)

    kill -s STOP "$p"
    
  3. Переконайтеся, що процес із цим PID має однаковий час запуску, і якщо так, введіть його, інакше нехай процес продовжується:

    cur=$(TZ=UTC0 ps -p "$p" -o lstart=)
    
    if [ "$cur" = "$stime" ]
    then
        # Okay, we can kill that process
        kill "$p"
    else
        # PID was reused. Better unblock the process!
        echo "long running task already completed!"
        kill -s CONT "$p"
    fi
    

Це працює, тому що може бути лише один процес з тим самим PID і час запуску в даній ОС.

Припинення процесу під час перевірки умови гонки не є проблемою. Очевидно, це проблема, що якийсь випадковий процес може бути зупинений на кілька мілісекунд. Залежно від типу процесу це може бути, а може і не бути проблемою.


Особисто я просто використовую python і psutilавтоматично обробляє повторне використання PID:

import time

import psutil

# note: it would be better if you were able to avoid using
#       shell=True here.
proc = psutil.Process('longrunningtask', shell=True)
time.sleep(86400)

# PID reuse handled by the library, no need to worry.
proc.terminate()   # or: proc.kill()

Правила Python в UNIX ... Я не впевнений, чому більше відповідей не починається там, оскільки я впевнений, що більшість систем не забороняє їх використовувати.
Містер Маскаро

Раніше я використовував аналогічну схему (використовуючи час початку), але ваші навички сценаріїв ш - акуратніші, ніж у мене! Спасибі.
FJL

Це означає, що ви потенційно зупиняєте неправильний процес. Зауважте, що ps -o start=формат змінюється з 18:12 до Jan26 через деякий час. Остерігайтеся також змін DST. Якщо в Linux, ви, мабуть, віддасте перевагу TZ=UTC0 ps -o lstart=.
Стефан Шазелас

@ StéphaneChazelas Так, але ви дозволяєте це продовжувати і надалі. Я прямо сказав: залежно від типу завдання, який виконує цей процес, у вас можуть виникнути проблеми з тим, щоб зупинити його кілька мілісекунд. Дякую за підказку lstart, я її відредагую.
Bakuriu

Зауважте, що (якщо ваша система не обмежує кількість процесів на користувача), хтось може легко заповнити таблицю процесів зомбі. Після того, як залишилось лише 3 доступних під-програми, кожен може легко запустити сотні різних процесів з одним і тим же під за одну секунду. Отже, строго кажучи, ваше "може бути лише один процес з тим самим PID і час початку роботи в даній ОС" , не обов'язково відповідає дійсності.
Стефан Шазелас

7

У системі Linux ви можете запевнити, що pid не буде повторно використаний, зберігаючи його простір імен живим. Це можна зробити через /proc/$pid/ns/pidфайл.

  • man namespaces -

    Прив’яжіть встановлення (див. mount(2)) Одного з файлів у цьому каталозі десь ще у файловій системі, зберігаючи відповідний простір імен процесу, визначеного pid, навіть у тому випадку, якщо всі процеси, що перебувають зараз у просторі імен, закінчуються.

    Відкриваючи один з файлів у цьому каталозі (або файл, прив’язаний до одного з цих файлів), повертається обробка файлу для відповідного простору імен процесу, визначеного pid. Поки цей дескриптор файлу залишається відкритим, простір імен залишатиметься живим, навіть якщо всі процеси в просторі імен закінчуються. Дескриптор файлу може бути переданий до setns(2).

Ви можете виділити групу процесів - в основному будь-яку кількість процесів - шляхом зміни їх імен init.

  • man pid_namespaces -

    Перший процес, створений у новому просторі імен (тобто процес, створений за clone(2) допомогою прапора CLONE_NEWPID , або перший дочір , створений процесом після виклику з unshare(2)використанням прапора CLONE_NEWPID ), має PID 1 і є initпроцесом для простору імен ( див. init(1)) . Дочірній процес, осиротівший у просторі імен, буде відновлений до цього процесу, а не init(1) (якщо один з предків дитини в тому ж просторі імен PID не використовував команду prctl(2) PR_SET_CHILD_SUBREAPER, щоб позначити себе як реалізацію осиротілих нащадків процесів) .

    Якщо initпроцес простору імен PID закінчується, ядро ​​припиняє всі процеси в просторі імен за допомогою сигналу SIGKILL . Така поведінка відображає той факт, що initпроцес є важливим для правильної роботи простору імен PID .

util-linuxПакет надає безліч корисних інструментів для маніпулювання просторів імен. Наприклад, є unshare, якщо ви ще не домовилися про його права в просторі імен користувачів, для нього знадобляться права суперкористувача:

unshare -fp sh -c 'n=
    echo "PID = $$"
    until   [ "$((n+=1))" -gt 5 ]
    do      while   sleep 1
            do      date
            done    >>log 2>/dev/null   &
    done;   sleep 5' >log
cat log; sleep 2
echo 2 secs later...
tail -n1 log

Якщо ви не влаштували простір імен користувачів, тоді ви все одно можете безпечно виконувати довільні команди, негайно скинувши привілеї. runuserКоманда інший (НЕ УИП) бінарна забезпечується util-linuxпакетом і включення може виглядати наступним чином :

sudo unshare -fp runuser -u "$USER" -- sh -c '...'

...і так далі.

У наведеному вище прикладі два перемикача передаються unshare(1)на --forkпрапор , який робить Викликаний sh -cпроцес створений перший дитина і забезпечує його initстатус, і --pidпрапор , який інструктує unshare(1)для створення Pid простору імен.

В sh -cпроцесі породжує п'яти дочірніх оболонок фонових - кожен представляє собою inifinite whileциклу , який буде продовжувати додавати висновок dateдо кінця log, поки sleep 1повертає значення ІСТИНИ. Після нересту цих процесів shвиклики ще sleepпротягом 5 секунд потім припиняються.

Можливо, варто відзначити, що якби -fпрапор не був використаний, жодна з фонових whileциклів не припиниться, але з ним ...

ВИХІД:

PID = 1
Mon Jan 26 19:17:45 PST 2015
Mon Jan 26 19:17:45 PST 2015
Mon Jan 26 19:17:45 PST 2015
Mon Jan 26 19:17:45 PST 2015
Mon Jan 26 19:17:45 PST 2015
Mon Jan 26 19:17:46 PST 2015
Mon Jan 26 19:17:46 PST 2015
Mon Jan 26 19:17:46 PST 2015
Mon Jan 26 19:17:46 PST 2015
Mon Jan 26 19:17:46 PST 2015
Mon Jan 26 19:17:47 PST 2015
Mon Jan 26 19:17:47 PST 2015
Mon Jan 26 19:17:47 PST 2015
Mon Jan 26 19:17:47 PST 2015
Mon Jan 26 19:17:47 PST 2015
Mon Jan 26 19:17:48 PST 2015
Mon Jan 26 19:17:48 PST 2015
Mon Jan 26 19:17:48 PST 2015
Mon Jan 26 19:17:48 PST 2015
Mon Jan 26 19:17:48 PST 2015
2 secs later...
Mon Jan 26 19:17:48 PST 2015

Цікава відповідь, яка здається надійною. Можливо, трохи зайвого набору для базового використання, але варто подумати.
Уріель

Я не бачу, як і чому збереження простору імен PID не запобігає повторному використанню PID. Сама сторінка, яку ви цитуєте - Поки цей дескриптор файлу залишається відкритим, простір імен залишатиметься живим, навіть якщо всі процеси в просторі імен закінчуються - говорить про те, що процеси все ще можуть закінчуватися (і, таким чином, імовірно, їх ідентифікатор процесу утилізується). Що стосується збереження живого простору імен PID, щоб не допустити повторного використання самого PID іншим процесом?
davmac

5

Подумайте про те, щоб longrunningthingповодити себе трохи краще, трохи більше, як демона. Наприклад, ви можете змусити його створити pidfile, який дозволить принаймні деякий обмежений контроль над процесом. Існує кілька способів зробити це, не змінюючи оригінальний двійковий файл, при цьому всі включають обгортку. Наприклад:

  1. простий скрипт обгортки, який запустить необхідну роботу у фоновому режимі (з необов'язковим перенаправленням виводу), запишіть PID цього процесу у файл, потім зачекайте, поки процес закінчиться (використовуючи wait) та видаліть файл. Якщо під час очікування процес загине, наприклад, через щось подібне

    kill $(cat pidfile)
    

    обгортка просто переконається, що pidfile видалений.

  2. моніторна обгортка, яка покладе свій власний PID кудись і буде вловлювати (і реагувати на) надіслані на нього сигнали. Простий приклад:

    #!/bin/bash
    p=0
    trap killit USR1

    killit () {
        printf "USR1 caught, killing %s\n" "$p"
        kill -9 $p
    }

    printf "monitor $$ is waiting\n"
    therealstuff &
    p=%1
    wait $p
    printf "monitor exiting\n"

Зараз, як вказували @R .. та @ StéphaneChazelas, ці підходи часто мають десь стан перегонів або накладають обмеження на кількість процесів, які можна породити. Крім того, він не обробляє випадки, коли longrunningthingвилка та діти відриваються (це, мабуть, не те, що було проблемою в оригінальному питанні).

З недавнім (прочитала пару років) ядра Linux, це може бути добре оброблено за допомогою контрольних груп , а саме морозильника - який, я вважаю, що деякі сучасні Linux ініціалізації система використовує.


Дякую, і всім. Я читаю щоразу зараз. Справа в longrunningthingтому, що ти не маєш контролю над тим, що це таке. Я також дав приклад сценарію оболонки, тому що це пояснило проблему. Мені подобаються ваші та всі інші творчі рішення тут, але якщо ви використовуєте Linux / bash, для цього вбудований "тайм-аут". Я вважаю, що мені слід було б отримати джерело до цього і подивитися, як це робиться!
FJL

@FJL, timeoutце НЕ оболонка вбудований. Існували різні реалізації timeoutкоманди для Linux, нещодавно (2008 р.) Було додано до GNU coreutils (тобто не специфічно для Linux), і саме цим сьогодні користуються більшість дистрибутивів Linux.
Стефан Шазелас

@ Stéphane - Дякую - згодом я знайшов посилання на основні елементи GNU. Вони можуть бути портативними, але, якщо це не в базовій системі, на нього не можна покластися. Мені більше цікаво дізнатися, як це працює, хоча я зауважу, що ваш коментар в іншому місці свідчить про те, що він не на 100% надійний. З огляду на те, як ця нитка пішла, я не здивований!
FJL

1

Якщо ви працюєте в Linux (і декількох інших * nixes), ви можете перевірити, чи все ще використовується процес, який ви збираєтеся вбити, і чи відповідає командний рядок вашому довгому процесу. Щось на зразок :

echo Time up!
grep -q longrunningthing /proc/$p/cmdline 2>/dev/null
if [ $? -eq 0 ]
then
  kill $p
fi

Альтернативою може бути перевірка, наскільки триває процес, який ви збираєтесь вбити, чимось подібним ps -p $p -o etime=. Ви можете зробити це самостійно, витягнувши цю інформацію з /proc/$p/stat, але це було б складно (час вимірюється в міг, і вам також доведеться використовувати режим без роботи /proc/stat).

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


Це все ще не правильно, оскільки це не позбавляється від стану гонки.
strcat

@strcat Дійсно, жодної гарантії успіху немає, але більшість сценаріїв навіть не намагаються робити таку перевірку і лише тупо вбивають cat pidfileрезультат. Я не можу згадати про чистий спосіб зробити це тільки в оболонці. Пропонована відповідь на простір імен здається цікавою, проте ...
Уріель,

-1

Це насправді дуже гарне питання.

Спосіб визначення унікальності процесу полягає у перегляді (а) місця, де він знаходиться в пам'яті; і (b) що містить ця пам'ять. Щоб бути конкретним, ми хочемо знати, де в пам’яті знаходиться програмний текст для початкового виклику, оскільки ми знаємо, що текстова область кожного потоку займе інше місце в пам’яті. Якщо процес відмирає, а інший запускається з тим же під, текст програми для нового процесу не буде займати те саме місце в пам’яті і не буде містити однакової інформації.

Тож одразу після запуску процесу зробіть md5sum /proc/[pid]/mapsі збережіть результат. Пізніше, коли ви хочете вбити процес, зробіть ще один md5sum і порівняйте його. Якщо вона збігається, тоді вбийте під. Якщо ні, не варто.

щоб переконатися в цьому самі, запустіть дві однакові снаряди. Вивчіть /proc/[pid]/mapsїх, і ви побачите, що вони різні. Чому? Тому що, навіть якщо це одна і та ж програма, вони займають різні місця в пам'яті, а адреси їх стека різні. Отже, якщо ваш процес вмирає, а його PID повторно використовується, навіть якщо однакова команда буде перезапущена одними і тими ж аргументами , файл "map" буде іншим, і ви будете знати, що ви не маєте справу з оригінальним процесом.

Див.: Сторінка Proc для детальної інформації.

Зауважте, що файл /proc/[pid]/statвже містить всю інформацію, яку згадували інші афіші у своїх відповідях: вік процесу, батьківський під тощо. Цей файл містить як статичну, так і динамічну інформацію, тому, якщо ви вважаєте за краще використовувати цей файл як базовий для порівняння, тоді, запустивши своє longrunningthing, потрібно витягнути з нього такі статичні поля statта зберегти їх для порівняння пізніше:

pid, ім'я файлу, pid батьків, ідентифікатор групи процесів, керуючий термінал, час, запущений після завантаження системи, розмір набору резидента, адреса початку стака,

У сукупності вищезазначене однозначно ідентифікує процес, і тому це означає ще один шлях. Насправді ви могли б уникнути нічого, крім "pid" та "часу, який розпочався після завантаження системи" з високим ступенем впевненості. Просто витягніть ці поля з statфайлу та збережіть його десь після запуску процесу. Пізніше, перш ніж вбити його, витягніть його ще раз і порівняйте. Якщо вони відповідають, то ви впевнені, що дивитесь на оригінальний процес.


1
Це, як правило, не буде /proc/[pid]/mapsзмінюватися з часом, оскільки виділяється додаткова пам'ять або збільшується стек або створюються нові файли ... І що означає одразу після запуску ? Після того, як всі бібліотеки були зроблені на картах? Як ви це визначите?
Стефан Шазелас

Зараз я роблю тест на своїй системі з двома процесами, одним додатком java та іншим сервером cfengine. Кожні 15 хвилин я роблю md5sumїх файли карт. Я дозволю йому пробігти день-два і повідомляти тут про результати.
Майкл Мартінес

@ StéphaneChazelas: Я перевіряв два процеси вже 16 годин, і в md5sum не було змін
Michael Martinez

-1

Іншим способом було б перевірити вік процесу, перш ніж його вбити. Таким чином, ви можете переконатися, що ви не вбиваєте процес, який не породжується менш ніж за 24 години. Ви можете додати ifумову на основі цього перед тим, як вбити процес.

if [[ $(ps -p $p -o etime=) =~ 1-. ]] ; then
    kill $p
fi

Ця ifумова перевірить, чи $pменше ідентифікатор процесу менше 24 годин (86400 секунд).

PS: - Команда ps -p $p -o etime=матиме формат<no.of days>-HH:MM:SS


Програма mtimeне /proc/$pмає нічого спільного з часом початку процесу.
Стефан Шазелас

Спасибі @ StéphaneChazelas Ти правий. Я змінив відповідь, щоб змінити ifумову. Будь ласка, не соромтесь коментувати, якщо його баггі.
Sree

-3

Що я роблю, це після того, як убив процес, зроби це ще раз. Щоразу, коли я роблю, що відповідь повертається, "такого процесу немає"

allenb   12084  5473  0 08:12 pts/4    00:00:00 man man
allenb@allenb-P7812 ~ $ kill -9 12084
allenb@allenb-P7812 ~ $ kill -9 12084
bash: kill: (12084) - No such process
allenb@allenb-P7812 ~ $ 

Не могло бути простіше, і я роблю це роками без проблем.


Це відповідь на питання "як мені зробити це гірше", а не на те, "як я можу це виправити".
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.