Bagaimana cara menjalankan proses lama pada acara Udev?

11

Saya ingin menjalankan koneksi ppp ketika modem USB saya terhubung, jadi saya menggunakan udevaturan ini :

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

(Modem saya muncul /devsebagai ttyACM0)

newPPP.sh:

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

Masalah:

The udevkebakaran acara, dan newPPP.sh berjalan, tetapi newPPP.shproses tewas setelah ~ 4-5s. ppptidak punya waktu untuk terhubung (batas waktu 10-an untuk dial up).

Bagaimana saya bisa menjalankan proses waktu yang lama, itu tidak akan dibunuh?

Saya mencoba menggunakan nohup, tetapi tidak berhasil juga.

Sistem: Arch Linux

Memperbarui

Saya menemukan solusi di sini , terima kasih kepada maxschlepzig .

Saya gunakan at nowuntuk menjalankan pekerjaan saya terlepas dari proses udev.

Namun satu pertanyaan masih belum terjawab: Mengapa nohupdan &tidak bekerja?

Komunitas
sumber

Jawaban:

11

Jika Anda menjalankan distribusi yang layak dengan dukungan systemd, cara termudah dan paling aman secara teknis adalah dengan menggunakan unit perangkat .

Dengan cara ini, systemd akan berada dalam kendali penuh atas skrip yang sudah berjalan lama dan bahkan akan dapat menghentikan proses dengan benar begitu perangkat dimatikan / dihapus - melepaskan proses berarti Anda menyerah berada dalam kontrol penuh dari keadaan proses dan sejarahnya.

Selain itu, Anda dapat memeriksa status perangkat dan layanan terlampir dengan menjalankan systemctl status my-ppp-thing.device.

Lihat juga posting blog ini untuk beberapa contoh dan detail lainnya.

Elias Probst
sumber
6

Saat ini udev menggunakan cgroup untuk mencari-n-menghancurkan tugas yang muncul. Salah satu solusinya adalah dengan menggunakan "sekarang" atau "batch". Solusi lain adalah melakukan proses garpu ganda dan "pindah" ke cgroup lain. Ini adalah contoh kode python (kode serupa dapat ditulis dalam bahasa apa pun):

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

Output debug dapat dikirim ke, misalnya, syslog.

Alexandre Kandalintsev
sumber
1
Mengapa udev akan berusaha sedemikian rupa untuk menghancurkan proses melahirkan?
user30747
Saya menduga itu karena program yang dimulai dengan udev memblokir daemon (mis. Dengan aturan udev yang terhubung ke mencolokkan pada layar eksternal, program yang sudah berjalan lama akan mencegah tampilan baru dari benar-benar digunakan). Saya yakin itu memiliki alasan teknis sendiri di baliknya, tetapi berarti bahwa proses yang muncul dapat menahan bagian utama dari sistem dan perlu dibunuh.
tobek
2

Shell memiliki kemampuan untuk menjalankan perintah di latar belakang:

(

lots of code

) &

Perintah yang dikelompokkan oleh kawat gigi dengan ampersand setelahnya akan dijalankan secara tidak bersamaan dalam sebuah subkulit. Saya menggunakan ini untuk menghubungkan otomatis ketika modem USB dimasukkan dan diaktifkan. Dibutuhkan sekitar 20 detik dan berfungsi dengan baik di bawah udev.

pengguna42295
sumber
Anda mungkin ingin mengarahkan ulang stderr, stdout, dan stderr dalam situasi seperti itu.
mdpc
@ mdpc hmm ... kenapa? Saya melihat usb_modeswitch menutup aliran dalam skenario ini: exec 1 <& - 2 <& - 5 <& - 7 <& -
user42295
1

Saya membuatnya bekerja dengan setsid. RUN saya bagian dari aturan udev:

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

lalu dalam skrip:

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

Panggilan pertama ke skrip kembali dengan status keluar 0, tetapi panggilan kedua ke skrip terus berjalan dengan PPID = 1.

Hidup
sumber
0

Mungkin karena proses induknya dihentikan dan sinyal terminasi merambat ke anak-anaknya, yang tidak memblokirnya (dan jika SIGKILLmereka bahkan tidak bisa).

peterph
sumber