Systemd และกระบวนการวางไข่


14

ปกติจะไม่โพสต์ที่นี่ แต่ฉันกำลังฉีกผมออกไปมากกว่านี้ ฉันมีสคริปต์ Python ที่เรียกใช้เมื่อมันเปิดตัวและมีหน้าที่รับผิดชอบในการเริ่มต้นกระบวนการอื่น ๆ สคริปต์นี้เคยเปิดตัวเมื่อเริ่มต้นผ่าน sysvinit แต่เมื่อเร็ว ๆ นี้ฉันอัพเกรดเป็น Debian Jessie ดังนั้นจึงได้ปรับให้เปิดใช้งานผ่าน systemd

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

เมื่อเปิดตัว Via systemd หากกระบวนการหลักออกไปเด็ก ๆ ก็ออกจากกันด้วย (หน้าจอก็จะเริ่มตายและปรากฏเป็น Dead ???)

เป็นการดีที่ฉันจะต้องสามารถเริ่มต้นสคริปต์แม่โดยไม่ต้องฆ่ากระบวนการลูกทั้งหมดมีบางสิ่งที่ฉันหายไป?

ขอบคุณ!

[Unit]
Description=Server commander
After=network.target

[Service]
User=serveruser
Type=forking
PIDFile=/var/Server/Server.pid

ExecStart=/var/Server/Server.py
ExecStop=/bin/kill -s TERM $MAINPID

[Install]
WantedBy=multi-user.target

แก้ไข: มันอาจเกี่ยวข้องกับฉันที่จะชี้ให้เห็นว่าสคริปต์ Python นั้นเป็น 'ตัวควบคุม' สำหรับกระบวนการลูก มันเริ่มและหยุดเซิร์ฟเวอร์ในหน้าจอ gnu ตามที่ร้องขอจากเซิร์ฟเวอร์กลาง โดยปกติแล้วจะทำงานอยู่ตลอดเวลาไม่ส่งผลให้เกิดบริการและออก อย่างไรก็ตามมีบางกรณีที่ฉันต้องการโหลดสคริปต์ซ้ำโดยไม่ฆ่ากระบวนการลูกแม้ว่านั่นหมายความว่ากระบวนการนั้นถูกปิดใช้งานไปยัง pid 1 จริงๆแล้วมันไม่สำคัญว่าสคริปต์ Python จะเริ่มต้นกระบวนการเป็น กระบวนการหลักถ้าเป็นไปได้

คำอธิบายที่ดีขึ้นเกี่ยวกับวิธีการทำงาน:

  • Systemd วางไข่ /Server.py
  • Server.py หาและเขียนไฟล์ pid สำหรับ Systemd
  • Server.py จะวางกระบวนการของเซิร์ฟเวอร์ในหน้าจอ gnu ตามคำแนะนำ
  • Server.py จะทำงานต่อไปเพื่อทำการรีสตาร์ทที่ร้องขอจากเซิร์ฟเวอร์

เมื่อเรียกใช้โดยไม่ใช้ Systemd คุณสามารถเริ่มต้น Server.py ได้ใหม่และหน้าจอ gnu ที่เปิดใช้จะไม่ได้รับผลกระทบใด ๆ เมื่อเรียกใช้งานด้วย Systemd เมื่อ Server.py ปิดตัวลงแทนที่จะเป็นกระบวนการหน้าจอที่ถูกปิดใช้งานเป็น pid 1 จะถูกฆ่า


1
เป็นการยากที่จะให้บริการโซลูชันโดยไม่ต้องมีServer.pyรหัสและคำอธิบายของ fork การบริการที่เรียกใช้ (ถ้ามีการแยก) แต่โดยทั่วไปพูดนี้เป็นความพร้อมโปรโตคอลไม่ตรงกันปัญหา
intelfx

BTW ExecStop=ไม่จำเป็นต้องใช้ การดำเนินการเริ่มต้นของ systemd เมื่อหยุดคือการฆ่ากระบวนการ คุณอาจต้องการดูเอกสารประกอบสำหรับKillMode=คำสั่ง
intelfx

1
และในที่สุด ... ถ้าไม่มีโปรโตคอลการเตรียมความพร้อมที่เหมาะสม (หนึ่งsimpleหรือforkingจริง) สุดท้ายจะเป็นType=oneshot, และRemainAfterExit=yes KillMode=control-group
intelfx

@intelfx เป็นหลักสคริปต์ Python เปิดตัวเซิร์ฟเวอร์ในหน้าจอโดยใช้ Subprocess.call มันซับซ้อนกว่านั้นเพราะสคริปต์รับคำสั่งจากที่อื่นบอกให้หน้าจอเริ่มต้นและไม่ควรทำ หน้าจอใดที่พร้อมใช้งานเป็นแบบไดนามิกด้วยเหตุนี้จึงไม่สามารถให้บริการ systemd ด้วยตนเองได้ เป็นการดีที่ฉันไม่ต้องการให้ systemd รักษาหน้าจอเหล่านี้เป็นส่วนหนึ่งของบริการเลย แต่ปัจจุบันพวกเขาถูกทิ้งในกลุ่มกระบวนการเดียวกันและตายกับต้นแบบถ้าเริ่มต้นใหม่
Bottswana

ลางสังหรณ์ของฉันคือ systemd ไม่ "จัดการ" กระบวนการควบคุมแบบนั้น (มันแค่มองหา PID ในเวลาเริ่มต้นไม่รู้จักคนที่ใหม่กว่า ... ): |
rogerdpack

คำตอบ:


9

ฉันจัดการเพื่อแก้ไขปัญหานี้เพียงแค่ตั้งค่า KillMode ให้ดำเนินการแทนกลุ่มควบคุม (ค่าเริ่มต้น) ขอบคุณทุกคน


ที่ดูเหมือนว่าบางสิ่งบางอย่างของการทำงานมากกว่าแก้ไข แต่ดูคำตอบอื่น ๆ ... ถ้าคุณทำเช่นนี้และทำ "systemctl หยุด" แล้วมันจะไม่ฆ่ากระบวนการลูกพวกเขาจะยังคงทำงาน [?] นอกการกำกับดูแลของ systemctl?
rogerdpack

5

ฉันมีสคริปต์ Python ที่เรียกใช้เมื่อมันเปิดตัวและมีหน้าที่รับผิดชอบในการเริ่มต้นกระบวนการอื่น ๆ

ซึ่งแสดงว่าคุณทำผิดไป เพิ่มเติมในช่วงเวลานี้

เมื่อสคริปต์ออกจากกระบวนการที่เด็กกำพร้าและยังคงทำงานต่อไป

สิ่งนี้ไม่ถูกต้องพฤติกรรมของdæmon หากกระบวนการ "หลัก" - ในกรณีนี้เด็กที่คุณได้แยกจากกันเนื่องจากคุณได้ระบุไว้Type=forking- ออก, systemd จะพิจารณาบริการที่จะปิดการใช้งานและยุติกระบวนการที่ทำงานอยู่อื่น ๆ (ในกลุ่มควบคุม) เพื่อจัดระเบียบ .

บางครั้งการแปลงจากrcสคริปต์System 5 เป็น systemd ไม่ตรงไปตรงมาเนื่องจากวิธีที่ถูกต้องในการทำสิ่งต่าง ๆ ภายใต้ systemd นั้นแตกต่างกันมาก วิธีที่ถูกต้องในการทำ (พูด) OpenVPN หรือ OpenStack หรือ OSSEC HIDS ใน systemd นั้นไม่เหมือนกับที่เคยทำกับrcสคริปต์ ความจริงที่ว่าคุณมีสคริปต์ที่ฟอร์กแล้ววางไข่กระบวนการลูกหลานทั้งหมดแล้วออกจากการคาดหวังว่าลูกหลานเหล่านั้นจะทำงานต่อไปแสดงว่าคุณกำลังสร้างความสยองขวัญแบบเดียวกันossec-controlแม้ว่าจะมีการตีระดับน้อยกว่าสองระดับ หากคุณพบว่าตัวเองเขียน "ต้นแบบ" สคริปต์ที่ตรวจสอบ "เปิดใช้งาน" ธงและวิ่งกระบวนการที่เด็กสำหรับ "เปิด" ossec-controlส่วนของระบบของคุณแล้วคุณจะทำผิดพลาดเช่นเดียวกับที่น่ากลัว

ไม่จำเป็นต้องใช้กลไกที่ปลูกเองในบ้านกับ systemd มันเป็นผู้จัดการบริการอยู่แล้ว ตาม/unix//a/200365/5132วิธีที่ถูกต้องในเรื่องนี้ใน systemd คือไม่ต้องมีบริการหนึ่งบริการที่จะพยายาม "บริการย่อย" ที่แปลกประหลาดและสับสน มันคือการให้เด็กแต่ละกระบวนการเป็นบริการ systemd เต็มเปี่ยมในสิทธิของตนเอง จากนั้นจะเปิดใช้งานและปิดใช้งานและเริ่มและหยุดส่วนต่าง ๆ ของระบบโดยใช้การควบคุม systemd ปกติ อย่างที่คุณเห็นในกรณี OSSEC HIDS หน่วยบริการเทมเพลตอย่างง่ายครอบคลุมเกือบทั้งหมด (ข้อยกเว้นหนึ่งข้อคือที่ /ubuntu//a/624871/43344 ) บริการช่วยให้ผู้ใช้สามารถทำสิ่งต่าง ๆ เช่นsystemctl enable ossec@agentlessd.serviceเปิดใช้งานตัวเลือกagentlessdบริการโดยไม่จำเป็นเลยสำหรับน่ากลัวสคริปต์ "ต้นแบบ" กลไกที่จำเป็นกับระบบใด ๆ rc5

มีหลายกรณีที่อาจไม่รุนแรงเท่า OSSEC HIDS ซึ่งจำเป็นต้องมีการคิดใหม่ MTS เช่น exim และ sendmail มีสองอย่างนี้ หนึ่งอาจมีrcสคริปต์เดียวที่วางไข่คิวรองชนะเลิศ, การส่งต่อ SMTP และการส่งต่อ SMTP พร้อมกับตัวแปร ad hoc shell ในไฟล์การกำหนดค่าเพื่อควบคุมการทำงานที่แน่นอน แต่วิธีที่ถูกต้องในการทำสิ่งนี้กับ systemd คือการมีหน่วยบริการที่เหมาะสมสามหน่วย (สองแห่งมีหน่วยซ็อกเก็ตที่เกี่ยวข้อง) และไม่มีหน่วยเฉพาะกิจอะไรเลยเพียงกลไกปกติของผู้จัดการบริการ


ฉันขอขอบคุณข้อเสนอแนะเกี่ยวกับเรื่องนี้ ในขณะที่ฉันตกลงที่จะให้บริการชุดย่อยที่เหมาะสมแล้วก็ทำใน Python ด้วยเหตุผลที่ฉันไม่สามารถเข้าไปได้ ทางออกเดียวของฉันคือการหาวิธีที่จะทำให้วิธีนี้ใช้งานได้ ขอบคุณ ฉันชอบที่จะทำอย่างถูกต้อง
Bottswana

'sub'services ที่สคริปต์เปิดใช้เป็นเพียงเซิร์ฟเวอร์ที่ทำงานในหน้าจอ gnu ในฐานะผู้ใช้เฉพาะ เซิร์ฟเวอร์เหล่านี้มีการเปลี่ยนแปลงจำนวนมากถูกเพิ่มเข้ามาบางส่วนจะถูกลบออกและนี่ถูกควบคุมที่อื่นดังนั้นจึงไม่สามารถให้บริการจริง ๆ ได้ใน systemd เนื่องจากเพิ่มความซับซ้อนและไม่สามารถจัดการจากส่วนกลางได้ นอกจากนี้สคริปต์เดียวกันนี้ยังใช้กับเซิร์ฟเวอร์ที่ไม่ใช่ systemd
Bottswana

systemd มีสิ่งอำนวยความสะดวกที่ชัดเจนเพื่อให้บริการสามารถเพิ่มและลบออกได้โดยไม่จำเป็นต้องเข้าถึงรูท "ใช้กับบริการที่ไม่ใช่ systemd" เป็นข้อโต้แย้งเพียงข้อเดียวด้านบนที่ไม่สามารถแก้ไขได้ด้วยการเพิ่ม systemd ... อีกมากถึงแม้ว่าจะเป็นเช่นนั้นก็ตาม :)
Charles Duffy

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