วิธีการเรียกใช้กระบวนการนานในเหตุการณ์ 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เหตุการณ์ fires และ 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 ใช้กลุ่ม cg ในการค้นหางานที่ถูกทำลาย ทางออกหนึ่งคือการใช้ "ตอนนี้" หรือ "แบทช์" วิธีแก้ปัญหาอื่นก็คือทำDouble forkและกระบวนการ "ย้าย" ไปยัง cgroup อื่น นี่คือตัวอย่างโค้ดไพ ธ อน (โค้ดที่คล้ายกันสามารถเขียนในภาษาใดก็ได้):

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
ทำไม udev ถึงความยาวดังกล่าวเพื่อทำลายกระบวนการที่เกิดขึ้น?
30747

ฉันเดาว่าเป็นเพราะโปรแกรมที่เริ่มต้นโดย udev บล็อก daemon (เช่นด้วยกฎ udev ที่เชื่อมต่อกับการเสียบในจอแสดงผลภายนอกโปรแกรมที่รันนานจะป้องกันการแสดงผลใหม่จากการใช้งานจริง) ฉันแน่ใจว่ามีเหตุผลทางเทคนิคของตัวเองอยู่เบื้องหลัง แต่หมายความว่ากระบวนการที่เกิดขึ้นสามารถทำให้ส่วนสำคัญของระบบและต้องถูกฆ่า
tobek

2

เชลล์มีความสามารถในการเรียกใช้คำสั่งในพื้นหลัง:

(

lots of code

) &

คำสั่งที่จัดกลุ่มโดยวงเล็บปีกกาที่มีเครื่องหมายและหลังจากนั้นจะถูกดำเนินการแบบอะซิงโครนัสในเชลล์ย่อย ฉันใช้สิ่งนี้เพื่อเชื่อมต่ออัตโนมัติเมื่อโมเด็ม USB ถูกใส่และเปลี่ยน ใช้เวลาประมาณ 20 วินาทีและทำงานได้ดีภายใต้ udev


คุณอาจต้องการเปลี่ยนเส้นทาง stderr, stdout และ stderr ในสถานการณ์เช่นนี้
mdpc

@mdpc hmm ... ทำไมล่ะ ฉันเห็น 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พวกเขาไม่สามารถทำได้)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.