Làm thế nào để chạy quá trình thời gian dài trên sự kiện Udev?


11

Tôi muốn chạy kết nối ppp khi modem USB của tôi được kết nối, vì vậy tôi sử dụng udevquy tắc này :

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

(Modem của tôi xuất hiện /devdưới dạng ttyACM0)

newPPP.sh:

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

Vấn đề:

Sự udevkiện này kích hoạt và newPPP.sh đang chạy, nhưng newPPP.shquá trình bị hủy sau ~ 4-5 giây. pppkhông có thời gian để kết nối (thời gian chờ của nó là 10 giây để quay số).

Làm thế nào tôi có thể chạy một quá trình lâu dài, điều đó sẽ không bị giết?

Tôi đã thử sử dụng nohup, nhưng nó cũng không hoạt động.

Hệ thống: Arch Linux

Cập nhật

Tôi tìm thấy một giải pháp ở đây , nhờ maxschlepzig .

Tôi sử dụng at nowđể điều hành công việc của mình tách ra khỏi quá trình udev.

Nhưng một câu hỏi vẫn chưa được trả lời: Tại sao làm nohup&không hoạt động?

Câu trả lời:


11

Nếu bạn chạy một bản phân phối hợp lý với sự hỗ trợ của systemd, cách dễ nhất và an toàn nhất về mặt kỹ thuật là sử dụng một đơn vị thiết bị .

Bằng cách này, systemd sẽ kiểm soát hoàn toàn tập lệnh chạy dài và thậm chí có thể chấm dứt đúng quy trình một khi thiết bị được tắt / xóa - tách quy trình có nghĩa là bạn đang từ bỏ quyền kiểm soát hoàn toàn trạng thái quy trình và lịch sử của nó.

Ngoài ra, bạn sẽ có thể kiểm tra trạng thái của thiết bị và dịch vụ được đính kèm bằng cách chạy systemctl status my-ppp-thing.device.

Xem thêm bài viết blog này để biết thêm một số ví dụ và chi tiết.


6

Ngày nay udev sử dụng các nhóm để tìm kiếm các nhiệm vụ sinh sản. Một giải pháp là sử dụng "ngay bây giờ" hoặc "lô". Một giải pháp khác là thực hiện quá trình nhân đôi và "di dời" sang một nhóm khác. Đây là một ví dụ mã python (mã tương tự có thể được viết bằng bất kỳ ngôn ngữ nào):

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

Đầu ra gỡ lỗi có thể được gửi đến, ví dụ, syslog.


1
Tại sao udev sẽ đi đến chiều dài như vậy để phá hủy các quá trình sinh sản?
dùng30747

Tôi đoán đó là vì các chương trình được bắt đầu bởi udev chặn trình nền (ví dụ: với quy tắc udev được kết nối với việc cắm vào màn hình ngoài, một chương trình chạy dài sẽ ngăn màn hình mới thực sự được sử dụng). Tôi chắc chắn rằng có lý do kỹ thuật riêng đằng sau nó, nhưng có nghĩa là các quy trình được sinh ra có thể nắm giữ các phần chính của hệ thống và cần phải bị giết.
biết

2

Shell có khả năng chạy các lệnh trong nền:

(

lots of code

) &

Các lệnh được nhóm bởi các dấu ngoặc với dấu và sau chúng sẽ được thực hiện không đồng bộ trong một lớp con. Tôi sử dụng điều này để tự động kết nối khi cắm USB và chuyển đổi. Phải mất khoảng 20 giây và hoạt động tốt dưới udev.


Bạn có thể muốn chuyển hướng stderr, stdout và stderr trong tình huống như vậy.
mdpc

@mdpc hmm ... tại sao? Tôi thấy usb_modeswitch đóng luồng trong kịch bản này: exec 1 <& - 2 <& - 5 <& - 7 <& -
user42295 04

1

Tôi đã nhận nó để làm việc với setsid. Phần RUN của tôi trong quy tắc udev:

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

sau đó trong kịch bản:

#!/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....

Cuộc gọi đầu tiên tới tập lệnh trả về với trạng thái thoát 0, nhưng cuộc gọi thứ hai đến tập lệnh tiếp tục chạy với PPID = 1.


0

Có lẽ bởi vì quá trình cha mẹ của nó bị chấm dứt và tín hiệu kết thúc truyền đến con cái của nó, điều này không chặn nó (và trong trường hợp SIGKILLchúng thậm chí không thể).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.