วิธีกำหนดค่า systemd เพื่อฆ่าและรีสตาร์ท daemon เมื่อโหลดซ้ำ


12

ฉันมีภูตโรงเรียนเก่าที่ฉันต้องการควบคุมโดยใช้ systemd เมื่อไฟล์การกำหนดค่าเปลี่ยนแปลงจะต้องถูกฆ่าและรีสตาร์ท กล่าวอีกนัยหนึ่งหลังจากแก้ไขไฟล์ปรับแต่งแล้วsystemctl reload MYSERVICEควรจะทำให้กระบวนการหยุดทำงานและเริ่มต้นใหม่

ความพยายามที่ 1: ลองใช้ค่าเริ่มต้น สิ่งนี้บอกให้ systemd ทราบว่าจะเริ่มดีมอนได้อย่างไร แต่ไม่ใช่วิธีโหลดซ้ำ

[Service]
ExecStart=/usr/bin/MYSERVICE
Type=simple

เป็นผลstartและrestartทำงานได้ แต่reloadให้ข้อผิดพลาดนี้:

# systemctl reload MYSERVICE
Failed to reload MYSERVICE.service: Job type reload is not applicable for unit MYSERVICE.service.

พยายาม 2: บอกวิธีฆ่ากระบวนการ นี่เป็นการฆ่ากระบวนการ แต่ systemd ไม่รีสตาร์ทสำหรับฉัน

[Service]
ExecStart=/usr/bin/MYSERVICE
Type=simple
ExecReload=/bin/kill -HUP $MAINPID

...ติดตามโดย...

# systemctl daemon-reload
# systemctl reload MYSERVICE

... ฆ่ากระบวนการ แต่จะไม่เริ่มต้นใหม่โดยอัตโนมัติ

ความพยายามที่ 3: ใช้ ExecReload เพื่อเริ่มกระบวนการใหม่เช่นกัน สิ่งนี้ล้มเหลวด้วยเหตุผลบางประการ:

ExecReload=/bin/kill -HUP $MAINPID ; /usr/bin/MYSERVICE

... ข้อความแสดงข้อผิดพลาดที่ฉันได้รับ ... :

# systemctl daemon-reload
# systemctl reload MYSERVICE
Job for MYSERVICE.service failed because the control process exited with error code. See "systemctl status MYSERVICE.service" and "journalctl -xe" for details.

ฉันคาดหวังว่าจะมี ReloadType = kill_and_restart หรืออะไรบางอย่าง แต่ไม่มีโชคเช่นนั้น

จะบอก systemd ให้ฆ่าและรีสตาร์ท daemon เมื่อโหลดซ้ำได้อย่างไร


สิ่งนี้จำเป็นต้องใส่รองเท้าหรือไม่ในการบรรจุซ้ำซึ่งไม่พอดีจริงหรือ คุณไม่สามารถทำให้ภูตทำงานอย่างสมเหตุสมผลได้หรือไม่?
Michael Hampton

ขอบคุณ @MichaelHampton แต่นี่ไม่ใช่สถานการณ์ที่ฉันสามารถเขียนโปรแกรมใหม่ได้ ฉันขอขอบคุณข้อเสนอแนะที่เป็นประโยชน์ของคุณ ที่กล่าวว่าฉันแน่ใจว่านี่เป็นกรณีใช้ systemd ทั่วไปและคำตอบที่ยอมรับได้อาจช่วยผู้คนจำนวนมาก
TomOnTime

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

คำตอบ:


16

คำตอบคือ "คุณไม่ได้"! แต่เรามีข่าวดี

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

แต่คุณควรใช้systemctl reload-or-restartซึ่งจะทำการรีโหลดถ้ามันมีอยู่และรีสตาร์ทถ้ามันไม่

จากหน้าคน ...

   reload-or-restart PATTERN...
       Reload one or more units if they support it. If not, restart them
       instead. If the units are not running yet, they will be started.

   reload-or-try-restart PATTERN...
       Reload one or more units if they support it. If not, restart them
       instead. This does nothing if the units are not running. Note that,
       for compatibility with SysV init scripts, force-reload is
       equivalent to this command.

ดังนั้น: (1) ปล่อยให้ ExecReload ว่างเปล่า (2) ใช้งานsystemctl reload-or-restart MYSERVICEและ (3) คุณควรจะตั้งค่าทั้งหมด

หากคุณลองใช้ ExecReload เพื่อกำหนดวิธีการฆ่าและเริ่มบริการมันจะมี PID ใหม่และ systemd จะสับสน


3

ปรัชญา systemd คือว่าreloadเป็นตัวเลือกและการใช้งานของ systemd ควรรู้สำหรับทุกบริการไม่ว่าจะควรจะเรียกหรือของปลอมโดยเรียกreloadrestart

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

กล่าวอีกนัยหนึ่ง systemd ต้องการให้คุณใช้ " reload " เฉพาะเมื่อบริการพื้นฐานรองรับฟังก์ชันการโหลดที่แท้จริง ... นั่นคือการโหลดซ้ำที่ไม่ฆ่าและรีสตาร์ทบริการหรือทำให้บริการเปลี่ยน PID กล่าวอีกนัยหนึ่ง systemd เพียงต้องการสะท้อนให้เห็นถึงคุณสมบัติที่มีอยู่

คุณอาจถามตัวเองว่า: แต่มันจะง่ายกว่าไหมถ้าฉันสามารถใช้การโหลด "ปลอม" ด้วยการอนุญาตให้ExecReloadฆ่าและรีสตาร์ทบริการ จากนั้นฉันสามารถใช้systemctl reload FOOกับบริการทั้งหมดของฉันและฉันไม่ต้องจำคนที่สนับสนุนและคนที่ไม่ได้?

ใช่มันจะง่ายขึ้น แต่นั่นไม่ใช่วิธีของ systemd Systemd ต้องการให้ผู้โทรเป็นสิ่งที่รู้ว่าreloadมีอยู่สำหรับบริการหรือไม่ Systemd ต้องการอินเทอร์เฟซทั่วไปสำหรับคุณลักษณะที่มีอยู่ไม่ต้องการรับผิดชอบในการเติมช่องว่าง

ตัวอย่างเช่นสมมติว่าหุ่นบริการ systemd ขับเคลื่อนไม่มีreloadและค่าเริ่มต้นที่จะฆ่าและเริ่มกระบวนการ หากประเภทบริการ [] เพิ่มวิธีการระบุว่ามีการโหลดซ้ำและควรใช้ในการแจ้งเตือนจะต้องเรียนรู้ว่าบริการใดมีหรือไม่มีการโหลดซ้ำแบบดั้งเดิม Chef และระบบอื่น ๆ ทั้งหมดก็ต้องเรียนรู้สิ่งเดียวกันเพราะ systemd ต้องการให้มันแก้ไขในชั้นนั้น (MiniRant: สำหรับการเริ่มต้นกระบวนการ systemd น่าจะเป็นสิ่งที่ทุกคนรู้, การติดตั้งทั้งหมด, เนมสเปซ - ปรับแต่งระบบ i-do-Everything-at-my-layer ดังนั้นฉันไม่สามารถบอกคุณได้ว่าทำไมมันถึงไม่ ขยายปรัชญานี้เพื่อโหลดซ้ำบางทีหนึ่งในผู้แต่งสามารถตีระฆังที่นี่)


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