如何在 Udev 事件上运行长时间进程?

13 linux udev ppp

我想在连接 USB 调制解调器时运行ppp连接,因此我使用以下udev规则:

ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="16d8",\
    RUN+="/usr/local/bin/newPPP.sh $env{DEVNAME}"
Run Code Online (Sandbox Code Playgroud)

(我的调制解调器显示/devttyACM0

新建PPP.sh:

#!/bin/bash
/usr/bin/pon prov $1 >/dev/null 2>&1 &
Run Code Online (Sandbox Code Playgroud)

问题:

udev事件触发,并newPPP.sh正在运行,但newPPP.sh过程后〜4-5s杀害。ppp没有时间连接(拨号超时为 10 秒)。

我怎样才能运行很长时间的进程,不会被杀死?

我尝试使用nohup,但它也不起作用。

系统:Arch Linux

更新

感谢maxschlepzig,我在这里找到了解决方案。

at now用来运行与 udev 进程分离的作业。

但有一个问题仍未得到解答:为什么有效nohup&无效?

Eli*_*bst 10

如果您运行具有 systemd 支持的不错的发行版,最简单且技术上最安全的方法是使用设备单元

这样,systemd 将完全控制长时间运行的脚本,甚至可以在设备关闭/移除后正确终止进程 - 分离进程意味着您放弃对进程状态的完全控制及其历史。

除此之外,您还可以通过运行来检查设备的状态及其附加的服务systemctl status my-ppp-thing.device

有关更多示例和详细信息,另请参阅此博客文章


小智 7

现在 udev 使用 cgroups 来寻找-n-销毁产生的任务。一种解决方案是使用“at now”或“batch”。另一种解决方案是进行双叉并将“重定位”过程到另一个 cgroup。这是一个 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
Run Code Online (Sandbox Code Playgroud)

调试输出可以发送到例如系统日志。

  • 为什么 udev 会不遗余力地破坏生成的进程? (2认同)

pet*_*rph -1

但有一个问题仍未得到解答:为什么 nohup 和 & 不起作用?

可能是因为它的父进程被终止并且终止信号传播到它的子进程,而子进程不会阻止它(如果SIGKILL它们甚至不能)。

您可以将信号处理程序添加到脚本中并记录收到的信号。对于 shell 脚本,您可以使用trap内置的 shell。