Як запустити тривалий процес на Udev події?


11

Я хочу запустити ppp- з'єднання, коли підключений мій USB-модем, тому я використовую це udevправило:

ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="16d8",\
    RUN+="/usr/local/bin/newPPP.sh $env{DEVNAME}"

(Мій модем відображається /devяк ttyACM0)

newPPP.sh:

#!/bin/bash
/usr/bin/pon prov $1 >/dev/null 2>&1 &

Проблема:

В udevспрацьовує подія, і newPPP.sh працює, але newPPP.shпроцес був убитий після ~ 4-5s. pppне встигає підключитися (його час очікування становить 10 секунд для набору номера).

Як я можу довго запускати процес, щоб не загинули?

Я спробував використовувати nohup, але і це не вийшло.

Система: Arch Linux

Оновлення

Я знайшов рішення тут , завдяки maxschlepzig .

Я використовую at nowдля запуску своєї роботи, відірваної від процесу udev.

Але одне питання залишається без відповіді: Чому nohupі &не працювати?

Відповіді:


11

Якщо ви використовуєте гідний дистрибутив із систематизованою підтримкою, найпростіший та технічно найбезпечніший спосіб - це використовувати пристрій пристрою .

Таким чином, systemd буде повністю контролювати тривалий сценарій і навіть зможе належним чином припинити процес після вимкнення / видалення пристрою - від'єднання процесу означає, що ви відмовляєтесь від повного контролю над станом процесу та її історія.

Окрім цього, ви зможете перевірити стан пристрою та його доданої послуги, запустивши systemctl status my-ppp-thing.device.

Дивіться також цю публікацію в блозі для отримання додаткових прикладів та деталей.


6

У наш час udev використовує групи для пошуку n-знищення породжених завдань. Одне рішення - використовувати "зараз" або "пакетно". Ще одне рішення - зробити подвійний форк і "переїхати" процес в іншу групу. Це приклад пітонного коду (подібний код може бути написаний будь-якою мовою):

os.closerange(0, 65535)  # just in case
pid = os.fork()
if not pid:
  pid = os.fork()  # fork again so the child would adopted by init
  if not pid:
    # relocate this process to another cgroup
    with open("/sys/fs/cgroup/cpu/tasks", "a+") as fd:
      fd.write(str(os.getpid()))
    sleep(3)  # defer execution by XX seconds
    # YOUR CODE GOES HERE
sleep(0.1)  # get forked process chance to change cgroup

Вихід з налагодження може бути надісланий, наприклад, в syslog.


1
Чому б удев піти настільки довго, щоб знищити породжені процеси?
користувач30747

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

2

Shell має можливість запускати команди у фоновому режимі:

(

lots of code

) &

Команди, згруповані за дужками з амперсом і після них, будуть виконані асинхронно в підгруппі. Я використовую це для автоматичного підключення, коли вставляється та перемикається USB-модем. Це займає близько 20 секунд і працює нормально під udev.


Ви можете захотіти перенаправити stderr, stdout та stderr у такій ситуації.
mdpc

@mdpc хм ... чому? Я бачив, що usb_modeswitch закриває потоки за цим сценарієм: exec 1 <& - 2 <& - 5 <& - 7 <& -
user42295

1

Я змусив його працювати з setid. Моя RUN частина правила udev:

RUN+="/bin/bash script.sh"

потім у сценарії:

#!/bin/bash
if [ "$1" != "fo_real" ]; then
  /usr/bin/setsid $(/usr/bin/dirname $0)/$(/usr/bin/basename $0) fo_real &
  exit
fi

Rest of script is here....

Перший виклик сценарію повертається зі статусом виходу 0, але другий виклик сценарію продовжує працювати з PPID = 1.


0

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

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