วิธี“ เหมาะสม” ในการรันเชลล์สคริปต์เป็น daemon


20

ฉันจะเขียนสคริปต์เชลล์ที่ผมอยากจะทำงานเป็นภูตในการเริ่มต้นโดยไม่ต้องใช้เครื่องมือภายนอกเช่นdaemontoolsหรือ daemonize


Linux Daemon การเขียน HOWTO

ตามที่ลินุกซ์ภูตเขียน HOWTOที่เหมาะสมภูตมีลักษณะดังต่อไปนี้:

  • ส้อมจากกระบวนการหลัก
  • ปิดทั้งหมดอธิบายไฟล์ (เช่นstdin, stdout, stderr)
  • เปิดบันทึกสำหรับการเขียน (ถ้ากำหนดค่า)
  • เปลี่ยนไดเรกทอรีการทำงานอย่างใดอย่างหนึ่งที่เป็นถาวร (ปกติ/)
  • รีเซ็ตหน้ากากโหมดไฟล์ (umask)
  • สร้างSession ID ที่ไม่ซ้ำกัน(SID)

daemonizeบทนำ

daemonizeบทนำไปไกลระบุว่าภูตทั่วไปเพิ่มเติม:

  • ยกเลิกการเชื่อมโยงจากเทอร์มินัลการควบคุม (หากมี) และจะละเว้นสัญญาณเทอร์มินัลทั้งหมด
  • ยกเลิกการเชื่อมโยงจากกลุ่มกระบวนการ
  • จับ SIGCLD

ฉันจะทำทั้งหมดนี้ในsh, dashหรือbashสคริปต์ด้วยเครื่องมือลินุกซ์ร่วมกันเท่านั้น?

สคริปต์ควรสามารถทำงานบน distros ได้มากที่สุดโดยไม่ต้องมีซอฟต์แวร์เพิ่มเติมแม้ว่าDebianจะเป็นจุดสนใจหลักของเรา


หมายเหตุ:ฉันรู้ว่ามีคำตอบมากมายในเครือข่ายStackExchange ที่แนะนำให้ใช้nohupหรือsetsidแต่วิธีการเหล่านี้ไม่ได้จัดการข้อกำหนดทั้งหมดข้างต้น


แก้ไข: ภูต (7) manpageยังช่วยให้คำแนะนำบางส่วนแม้ดูเหมือนจะมีความแตกต่างบางอย่างระหว่างแบบเก่าSysVภูตและใหม่กว่าsystemdคน เนื่องจากความเข้ากันได้กับความหลากหลายของ distros เป็นสิ่งสำคัญโปรดตรวจสอบให้แน่ใจว่าคำตอบนั้นชัดเจนแตกต่างกัน



1
วิธีที่ "เหมาะสม" เพื่องานฝีมือเชลล์สคริปต์ของคุณเองคือการทำให้มันทำการเข้าสู่ระบบของตัวเองให้วิธีการสำหรับการเปิดตัวเป็นภูต ฯลฯ สิ่งที่ชอบdaemonและสิ่งอื่น ๆ เหล่านั้นมีการทำงานโดยพลสคริปต์เปลือกไม่มีบทบัญญัติสำหรับการทำงานเป็น ภูต เนื่องจากคุณเป็นผู้แต่งควบคุมการเขียนสคริปต์ให้สมบูรณ์ดังนั้นจึงสามารถเปิดใช้งานได้จาก systemd unitfile หรือสคริปต์ rc.d คุณไม่ระบุ "เหมาะสม"!
รวย

คำตอบ:


16

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

/usr/bin/mydaemonสมมติว่าคุณมีสคริปต์

#!/bin/sh

while true; do
  date;
  sleep 60;
done

/etc/systemd/system/mydaemon.serviceคุณสามารถสร้างหน่วย

[Unit]
Description=My daemon

[Service]
ExecStart=/usr/bin/mydaemon
Restart=on-failure

[Install]
WantedBy=multi-user.target 

ในการเริ่มปีศาจคุณวิ่ง

systemctl start mydaemon.service 

ในการเริ่มต้นเมื่อคุณเปิดใช้งาน

systemctl enable mydaemon.service

หากในระบบที่อิงกับ systemd ซึ่งส่วนใหญ่ของลีนุกซ์กระจายอยู่ทุกวันนี้นี่ไม่ใช่เครื่องมือภายนอกจริง ๆ ข้อเสียก็คือมันจะไม่ทำงานได้ทุกที่


3
ในขณะที่ฉันชอบวิธีการของ systemd ผู้ใช้กล่าวว่า มี Linux ดิสทริบิวชันที่ยังไม่มี systemd หรือให้คุณใช้เลือกระหว่าง systemd กับอย่างอื่นเช่น OpenRC
Cristian Ciupitu

5
สำหรับ distros ว่าการใช้ systemd, systemdไม่มากของ "เครื่องมือภายนอก" bashกว่า
Alexander

7

ฉันอาจจะพลาดอะไรบางอย่างที่นี่; เหตุใดจึงไม่nohupเหมาะสม แน่นอนมันไม่เพียงพอเพียงอย่างเดียวแต่การเสริมดูเหมือนว่าตรงไปตรง

#!/bin/bash

if [ "$1" = "DAEMON" ]; then
    # is this necessary? Add other signals at will (TTIN TTOU INT STOP TSTP)
    trap '' INT
    cd /tmp
    shift
    ### daemonized section ######
    for i in $( seq 1 10 ); do
        date
        sleep 5
    done
    #### end of daemonized section ####
    exit 0
fi

export PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin
umask 022
# You can add nice and ionice before nohup but they might not be installed
nohup setsid $0 DAEMON $* 2>/var/log/mydaemon.err >/var/log/mydaemon.log &

เท่าที่ฉันเห็น:

  • เอาต์พุตถูกเปลี่ยนทิศทางอย่างเหมาะสม (ใช้ / dev / null หากจำเป็น)
  • umask เป็นมรดก
  • stdin อย่างไรก็ตามในตอนท้ายของสคริปต์ผู้ปกครอง
  • สคริปต์ daemon.sh ถูก reparented ไปที่init(หรือsystemd)

ฉันมีความรู้สึกที่แข็งแกร่งฉันขาดความชัดเจน Downvote แต่โปรดบอกฉันว่า :-)


2
ฉันกำลังจะแนะนำสิ่งที่คล้ายกันมาก ฉันใช้การเปลี่ยนเส้นทางnohupด้วย&และ I / O เพื่อเรียกใช้Cยูทิลิตีnon- daemon หลายตัวพร้อมกับเพิ่มความปลอดภัยของการห่อnohupคำสั่งของคุณภายในsu -c "nohup ... &" -s /bin/bash systemUserเพื่อรัน daemon ในฐานะผู้ใช้ที่ไม่มีสิทธิพิเศษ
111 ---

4

screenคำสั่งLinux ที่อยู่ใน distros ส่วนใหญ่สามารถ daemonize เชลล์สคริปต์ได้ ฉันใช้มันบ่อยๆ นี่คือตัวอย่างรวดเร็วในการเริ่มต้นรายการและออกจากเซสชันหน้าจอที่แยกออก ...

# screen -dmS Session_Name  bash -c "while true; do date; sleep 60; done"

# screen -ls
There are screens on:
        8534.Session_Name       (04/04/2018 08:46:27 PM)        (Detached)

# screen -S Session_Name -X quit

2
screenไม่ทำให้เชลล์สคริปต์เสียรูป เพียงเรียกใช้พวกมันในเทอร์มินัลที่โดดเด่นและสามารถแยกออกจากเทอร์มินัลนี้ (เช่นแป้นพิมพ์ถอดปลั๊กจากพีซี) โดยไม่ต้องปิดเซสชัน ดังนั้นโปรแกรมที่รันในเทอร์มินัลที่แยกออกมากำลังทำงานในพื้นหลัง ดังนั้น - แยกโปรแกรมส่งผ่านในพื้นหลัง
Yurij Goncharuk
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.