Làm thế nào để tự động khởi động lại một quá trình nền linux nếu nó thất bại?


32

Tôi có một quá trình được thực thi bởi tập lệnh init.d trên nền. Ví dụ:

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

Trong một số điều kiện nhất định, quá trình của tôi có thể thất bại và trở lại. Có cách nào (tiêu chuẩn) làm thế nào để phát hiện lỗi của nó và tự động khởi động lại không?


Chắc chắn, nhưng nó thay đổi dựa trên phân phối. Khá nhiều trong số họ cung cấp một số loại quản lý dịch vụ.
David Schwartz

Không có phân phối tiêu chuẩn, nhưng buildroot. Vì vậy, tôi phải làm bằng tay ...
Honza

Câu trả lời:


14

Cách dễ nhất là thêm nó vào / etc / inittab , được thiết kế để thực hiện loại việc này:

hồi sinh Nếu quá trình không tồn tại, bắt đầu quá trình. Đừng đợi kết thúc của nó (tiếp tục quét tệp / etc / inittab). Khởi động lại quá trình khi nó chết. Nếu quá trình tồn tại, không làm gì cả và tiếp tục quét tệp / etc / inittab.

Ví dụ: bạn có thể làm điều này:

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

Lưu ý, /etc/inittabhoạt động (hoặc thậm chí tồn tại) nếu và chỉ khi bạn có hệ thống init dựa trên sysvinit. Với upstart và với systemd thì không. Bạn phải cài đặt busybox (shell rất nguyên thủy làm cho các tác vụ phục hồi sysadm trở nên đau đớn, nhưng nó có thể thay thế một initd tương thích sysvinit) hoặc sysvinit (nó là một hóa thạch). Trong một container docker, chỉ có cái đầu tiên là không đau.
peterh nói phục hồi Monica

27

Buildroot có ba hệ thống init có thể, vì vậy có ba cách để làm điều này:

BusyBox init

Với điều này, người ta thêm một mục vào /etc/inittab.

::respawn:/bin/myprocess

Lưu ý rằng BusyBox init/etc/inittabđịnh dạng idiosyncratic . Trường thứ hai là vô nghĩa và trường thứ nhất không phải là ID mà là tên cơ sở của thiết bị.

Linux "Hệ thống V" init

Một lần nữa, người ta thêm một mục vào /etc/inittab.

myprocess:2345:respawn:/bin/myprocess

systemd

Một người viết một tập tin đơn vị trong, nói , /etc/systemd/system/myprocess.service:

[Unit]
Description=My Process

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

[Install]
WantedBy=multi-user.target

Cho phép điều này để tự khởi động khi khởi động với:

systemctl enable myprocess.service

Bắt đầu bằng tay với:

systemctl start myprocess.service

đọc thêm


Nhưng khi bạn sử dụng phương pháp này inittab thì quy trình của bạn không còn truy cập được qua giao diện 'dịch vụ' phải không? tức là bạn không thể đi service mything starthay service mything stopnữa .... có cách nào để có thứ tốt nhất của cả hai không? tức là dịch vụ sysvinit không đáng tin cậy, nhưng cũng có thể sử dụng được thông qua 'dịch vụ'?
Horseyguy

25

Điều gì về việc tạo một lớp con với một vòng lặp gọi liên tục cùng một quá trình?

Nếu nó kết thúc, lần lặp tiếp theo của vòng lặp sẽ tiếp tục và bắt đầu lại.

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

Nếu subshell chết, nó sẽ kết thúc. Khả năng duy nhất trong trường hợp đó là tạo ra một quy trình khác (tôi sẽ gọi nó là necromancer) để kiểm tra xem quy trình của bạn có còn sống hay không, khởi động nó nếu không và chạy chương trình necromancer này bằng cron, để bạn có thể kiểm tra thường xuyên.

Bước tiếp theo sẽ tự hỏi điều gì có thể xảy ra nếu cron chết, nhưng đến một lúc nào đó bạn sẽ cảm thấy an toàn và ngừng lo lắng.


3

Bạn có thể sử dụng Monit . Nó thực sự dễ sử dụng và khá linh hoạt. Xem ví dụ cấu hình này để khởi động lại quá trình Tomcat khi thất bại.

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

Nó cũng có rất nhiều ví dụ cấu hình cho nhiều trường hợp sử dụng.


1

Nếu bạn không phải là siêu người dùng hoặc root và nếu hệ thống Linux của bạn đã cài đặt Docker, thì bạn có thể tạo hình ảnh docker của quy trình của mình, sử dụng docker để khởi động lại quy trình của bạn nếu hệ thống được khởi động lại.

Tập tin: 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

Để bắt đầu container docker của bạn,

docker-compose up -d

Tôi thấy thật dễ dàng để xử lý quy trình của riêng tôi với tự động khởi động lại nếu tôi không phải là siêu người dùng của hệ thống.

Đối với một ví dụ mẫu về cách tạo hình ảnh docker, đây là một ví dụ nhanh:

Tập tin: 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

Trong trường hợp của tôi, như là một cách khắc phục nhanh, tôi đã sửa đổi và sử dụng giải pháp @Trylks để gói chương trình tôi đang khởi chạy. Tôi muốn nó chỉ kết thúc trên lối ra sạch.

Nên chạy trong hầu hết các shell:

#!/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

Bạn có thể sử dụng restarter

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

Trên các hệ thống mới hơn sử dụng systemd để giải quyết tất cả các vấn đề tầm thường đó

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.