Как запустить длительный процесс на событии 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, самый простой и технически самый безопасный способ - использовать устройство .

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

Кроме того, вы сможете проверить состояние устройства и подключенного к нему сервиса, запустив его systemctl status my-ppp-thing.device.

Смотрите также этот пост в блоге для некоторых дополнительных примеров и деталей.


6

В настоящее время udev использует cgroups для поиска и уничтожения порожденных задач. Одним из решений является использование «сейчас» или «партия». Другое решение - сделать двойной ответвление и «переместить» процесс в другую группу. Это пример кода Python (аналогичный код может быть написан на любом языке):

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

Отладочный вывод может быть отправлен, например, в системный журнал.


1
Зачем udev идти на такие меры, чтобы уничтожить порожденные процессы?
user30747

Я предполагаю, что это потому, что программы, запускаемые udev, блокируют демона (например, с помощью правила udev, подключенного к подключению внешнего дисплея, долго работающая программа предотвратит фактическое использование нового дисплея). Я уверен, что у этого есть свои технические причины, но это означает, что порожденные процессы могут задерживать основные части системы и должны быть убиты.
Тобек

2

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

(

lots of code

) &

Команды, сгруппированные по скобкам с амперсандом после них, будут выполняться асинхронно в подоболочке. Я использую это для автоматического подключения, когда USB-модем вставлен и переключен. Это занимает около 20 секунд и прекрасно работает под Udev.


Вы можете перенаправить stderr, stdout и stderr в такой ситуации.
mdpc

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

1

Я получил его для работы с setsid. Моя 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.