จะรีสตาร์ทกระบวนการพื้นหลัง linux โดยอัตโนมัติได้อย่างไรหากล้มเหลว?


32

ฉันมีกระบวนการที่ดำเนินการโดยสคริปต์ init.d บนพื้นหลัง เช่น:

case "$1" in 
    start)
       /bin/myprocess &
    stop)
       killall myprocess
    restart)
       killall myprocess
       /bin/myprocess &
esac

ในบางเงื่อนไข myprocess สามารถล้มเหลวและส่งคืนได้ มีวิธีใด (มาตรฐาน) ในการตรวจสอบความล้มเหลวและเริ่มต้นใหม่โดยอัตโนมัติหรือไม่?


แน่นอน แต่มันก็แตกต่างกันไปตามการกระจาย ค่อนข้างมากพวกเขามีผู้จัดการบริการบางประเภท
David Schwartz

ไม่มีการแจกแจงมาตรฐาน แต่เป็น buildroot ดังนั้นผมจึงต้องทำด้วยตนเอง ...
Honza

คำตอบ:


14

วิธีที่ง่ายที่สุดคือการเพิ่มลงใน/ etc / inittabซึ่งออกแบบมาเพื่อทำสิ่งนี้:

respawn หากกระบวนการไม่มีอยู่ให้เริ่มต้นกระบวนการ อย่ารอการยกเลิก (สแกนไฟล์ / etc / inittab ต่อไป) รีสตาร์ทกระบวนการเมื่อมันตาย หากกระบวนการนี้มีอยู่แล้วอย่าทำอะไรเลยและทำการสแกนไฟล์ / etc / inittab ต่อไป

ตัวอย่างเช่นคุณสามารถทำสิ่งนี้:

# Run my stuff
myprocess:2345:respawn:/bin/myprocess

หมายเหตุใช้/etc/inittabงานได้ (หรือแม้กระทั่งมีอยู่) ถ้าหากคุณมีระบบเริ่มต้นที่ใช้ sysvinit ด้วยการพุ่งพรวดและด้วย systemd มันไม่ได้ คุณต้องติดตั้งbusybox (เชลล์แบบดั้งเดิมมากซึ่งทำให้ sysadm กู้คืนงานที่เจ็บปวด แต่มันสามารถแทนที่ initd ที่เข้ากันได้กับsysvinit ) หรือsysvinit (เป็นฟอสซิล) ในภาชนะนักเทียบท่าเพียงคนแรกไม่เจ็บปวด
peterh กล่าวว่าคืนสถานะโมนิก้า

27

Buildroot มีระบบเริ่มต้นที่เป็นไปได้สามระบบดังนั้นจึงมีสามวิธีในการทำสิ่งนี้:

BusyBox init

/etc/inittabด้วยวิธีนี้อย่างใดอย่างหนึ่งเพิ่มรายการไปยัง

::respawn:/bin/myprocess

โปรดทราบว่า BusyBox initมี/etc/inittabรูปแบบที่แปลกประหลาด ฟิลด์ที่สองนั้นไม่มีความหมายและฟิลด์แรกไม่ใช่ IDแต่เป็นชื่ออุปกรณ์พื้นฐาน

Linux "System V" init

/etc/inittabอีกครั้งหนึ่งเพิ่มรายการไปยัง

myprocess:2345:respawn:/bin/myprocess

systemd

หนึ่งเขียนไฟล์หน่วยในพูด/etc/systemd/system/myprocess.service:

[Unit]
Description=My Process

[Service]
ExecStart=/bin/myprocess
Restart=always

[Install]
WantedBy=multi-user.target

เปิดใช้งานสิ่งนี้เพื่อเริ่มอัตโนมัติเมื่อบูตเครื่องด้วย:

systemctl enable myprocess.service

เริ่มด้วยตนเองด้วย:

systemctl start myprocess.service

อ่านเพิ่มเติม


แต่เมื่อคุณใช้วิธีการนี้ inittab กระบวนการของคุณจะไม่สามารถเข้าถึงได้อีกต่อไปผ่านส่วนต่อประสาน 'บริการ' ใช่ไหม เช่นคุณไม่สามารถไปservice mything startหรือservice mything stopอีกต่อไป .... จะมีวิธีการมีที่ดีที่สุดของทั้งสองหรือไม่? เช่นบริการ sysvinit ที่ไม่สามารถลบได้ แต่ยังใช้งานผ่าน 'บริการ' ได้หรือไม่
horseyguy

25

สิ่งที่เกี่ยวกับการสร้าง subshell ด้วยการวนรอบที่เรียกกระบวนการเดียวกันตลอดเวลา?

ถ้ามันจบลงการวนซ้ำครั้งต่อไปจะเริ่มขึ้นอีกครั้ง

(while true; do 
    /bin/myprocess
done) &

ถ้า subshell ตายมันก็จบไปแล้ว ความเป็นไปได้เพียงอย่างเดียวในกรณีนั้นก็คือการสร้างกระบวนการอื่น (ฉันจะเรียกมันว่าหมอผี) ว่าตรวจสอบว่ากระบวนการของคุณยังมีชีวิตอยู่หรือไม่เริ่มถ้ามันไม่ได้และเรียกใช้หมอผีนี้ด้วย cron เพื่อให้คุณสามารถตรวจสอบ

ขั้นตอนต่อไปจะสงสัยว่าจะเกิดอะไรขึ้นถ้า cron ตาย แต่ในบางจุดคุณควรรู้สึกปลอดภัยและหยุดกังวล


3

คุณสามารถใช้Monitได้ มันใช้งานง่ายและมีความยืดหยุ่นมาก ดูตัวอย่างการกำหนดค่านี้เพื่อเริ่มต้นกระบวนการ Tomcat ใหม่เมื่อเกิดความล้มเหลว

check process tomcat with pidfile /var/run/tomcat.pid
   start program = "/etc/init.d/tomcat start"
   stop  program = "/etc/init.d/tomcat stop"
   if failed port 8080 type tcp then restart

นอกจากนี้ยังมีตัวอย่างการกำหนดค่าจำนวนมากสำหรับกรณีใช้งานจำนวนมาก


1

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

ไฟล์: docker-compose.yml

version: "3"
services:
  lserver:
    image: your_docker_image:latest
    ports:
    - 8080:8080   # just use 8080 as an example
    restart: always  # this is where your process can be guaranteed to restart

ในการเริ่มคอนเทนเนอร์นักเทียบท่าของคุณ

docker-compose up -d

ฉันพบว่ามันง่ายในการจัดการกับกระบวนการของฉันเองด้วยการรีสตาร์ทอัตโนมัติหากฉันไม่ใช่ผู้ใช้ขั้นสูงของระบบ

สำหรับตัวอย่างตัวอย่างวิธีสร้างอิมเมจนักเทียบท่านี่คือตัวอย่างด่วน:

ไฟล์: Dockerfile

FROM alpine:3.5

RUN apk update && apk upgrade && rm -rf /var/cache/apk/*
WORKDIR /app
COPY my-process-server /app
RUN ln -s /app/my-process-server /usr/local/bin/my-process-server

EXPOSE 8080

CMD ["my-process-server"]

0

ในกรณีของฉันเป็นการแก้ไขด่วนฉันแก้ไขและใช้โซลูชันของ @Trylks เพื่อรวมโปรแกรมที่ฉันเปิดใช้ ฉันอยากให้มันจบลงที่ทางออกที่สะอาดเท่านั้น

ควรรันใน shells ส่วนใหญ่:

#!/bin/sh

echo ""
echo "Use: $0 ./program"
echo ""

#eg="/usr/bin/apt update"

echo "Executing $1 ..."

EXIT_CODE=1
(while [ $EXIT_CODE -gt 0 ]; do
    $1
    # loops on error code: greater-than 0
    EXIT_CODE=$?
done) &

0

คุณสามารถใช้restarter

start)
   restarter -c /bin/myprocess &
stop)
   pkill -f myprocess

ในระบบที่ใหม่กว่าใช้ systemd ซึ่งแก้ไขปัญหาเล็กน้อยทั้งหมด

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