Cách đảm bảo ứng dụng tiếp tục chạy trên Linux


83

Tôi đang cố gắng đảm bảo tập lệnh vẫn chạy trên máy chủ phát triển. Nó đối chiếu số liệu thống kê và cung cấp một dịch vụ web để nó phải tồn tại, nhưng một vài lần trong ngày, nó chết đi không rõ lý do. Khi chúng tôi nhận thấy, chúng tôi chỉ khởi chạy lại, nhưng thật khó khăn ở phía sau và một số người dùng không có quyền (hoặc bí quyết) để khởi chạy nó.

Lập trình viên trong tôi muốn dành vài giờ để đi sâu tìm hiểu vấn đề nhưng con người bận rộn trong tôi nghĩ rằng phải có một cách dễ dàng để phát hiện nếu một ứng dụng không chạy và khởi chạy lại nó.

Tôi biết tôi có thể cron-script ps thông qua grep:

ps -A | grep appname

Nhưng một lần nữa, đó là một giờ nữa của cuộc đời tôi lãng phí vào việc làm một thứ gì đó đã tồn tại ... Không có một ứng dụng được tạo sẵn nào mà tôi có thể chuyển một tệp thực thi (tùy chọn với các đối số) và điều đó sẽ giữ cho một quy trình chạy vô thời hạn?

Trong trường hợp nó tạo ra bất kỳ sự khác biệt nào, đó là Ubuntu.


1
Nó phụ thuộc vào việc số liệu thống kê có bị mất khi tập lệnh không chạy hay không, nhưng tôi nghĩ lập trình viên trong bạn đã đúng - bạn nên tìm hiểu thêm về lý do tại sao tập lệnh không tiếp tục vô thời hạn.
Jonathan Leffler

1
Đó là một tiện ích dịch vụ theo yêu cầu hơn là một thứ liên tục có những con số khủng khiếp. Nếu nó bị treo trước khi nó lưu dữ liệu, không có gì bị mất; nó sẽ chỉ hoàn thành công việc trong lần chạy tiếp theo.
Oli


Câu hỏi đã được trả lời tại Standard hoặc cách tốt nhất để giữ cho quá trình sống bắt đầu bởi init.d . Các giải pháp bao gồm sử dụng systemd và /etc/inittab.
koppor

Câu trả lời:


37

Lưu ý: Upstart đang ở chế độ bảo trì và đã bị Ubuntu sử dụng systemd bỏ qua. Người ta nên kiểm tra hướng dẫn sử dụng hệ thống để biết chi tiết cách viết định nghĩa dịch vụ.

Vì bạn đang sử dụng Ubuntu, bạn có thể quan tâm đến Upstart , đã thay thế init sysV truyền thống . Một tính năng chính là nó có thể khởi động lại một dịch vụ nếu nó chết bất ngờ. Fedora đã chuyển sang giai đoạn mới nổi và Debian đang trong giai đoạn thử nghiệm, vì vậy nó có thể đáng xem xét.

Tuy nhiên, điều này có thể là quá mức cần thiết đối với tình huống này, vì tập lệnh cron sẽ mất 2 phút để thực hiện.

#!/bin/bash
if [[ ! `pidof -s yourapp` ]]; then
    invoke-rc.d yourapp start
fi

Tôi phải lưu ý rằng việc định cấu hình phiên bản mới để quản lý dịch vụ của bạn và giữ cho nó hoạt động khá đơn giản (bạn viết tệp cấu hình nhỏ). Giải pháp này rõ ràng hơn, đơn giản hơn và tốt hơn bất kỳ cách giám sát dựa trên các tập lệnh cron / shell "đơn giản" nào khác.
thor

@thor - (lưu ý, đây là từ năm 2008, khi công ty mới thành lập, và tài liệu khó có hơn). Tôi đồng ý, tập lệnh cron "đơn giản" chỉ để minh họa rằng một tập lệnh cũng không cần phải phức tạp để thực hiện công việc.
JimB

Tôi hiểu rồi. Tôi đã ủng hộ câu trả lời của bạn dù sao khi đặt bình luận của tôi
thor

85

Tôi đã sử dụng một tập lệnh đơn giản với cron để đảm bảo rằng chương trình đang chạy. Nếu không, thì nó sẽ khởi động nó. Đây có thể không phải là giải pháp hoàn hảo mà bạn đang tìm kiếm, nhưng nó đơn giản và hoạt động khá tốt.

#!/bin/bash
#make-run.sh
#make sure a process is always running.

export DISPLAY=:0 #needed if you are running a simple gui app.

process=YourProcessName
makerun="/usr/bin/program"

if ps ax | grep -v grep | grep $process > /dev/null
then
    exit
else
    $makerun &
fi

exit

Sau đó, thêm một công việc cron mỗi phút hoặc 5 phút một lần.


2
Đó là thiên tài. Nó sẽ tồn tại sau khi khởi động lại và không có gì để cài đặt.
Ian Purton

Bản thân tôi đã sử dụng cái này vì nó không yêu cầu quyền root để cài đặt.
JohnMudd

Điều gì sẽ process namexảy ra nếu tôi muốn giữ một tập lệnh Python chạy?
Người dùng

@User Sử dụng ps ax | grep XXXđể chỉ liệt kê quy trình của bạn, sau đó XXX sẽ là nó.
strongwillow vào

11
Là một cron một lót, chạy một lần một phút:* * * * * ps aux|grep -v grep|grep -q YourProcessName || /usr/bin/program &
ACK_stoverflow

43

Monit là hoàn hảo cho việc này :)

Bạn có thể viết các tệp cấu hình đơn giản cho phép theo dõi, ví dụ như cổng TCP, tệp PID, v.v.

SYN sẽ chạy một lệnh bạn chỉ định khi quá trình mà nó đang theo dõi không khả dụng / sử dụng quá nhiều bộ nhớ / đang gắn CPU quá lâu / v.v. Nó cũng sẽ bật ra một cảnh báo qua email cho bạn biết điều gì đã xảy ra và liệu nó có thể làm gì với nó hay không.

Chúng tôi sử dụng nó để duy trì hoạt động của các trang web đồng thời đưa ra cảnh báo sớm khi có sự cố.

- Nhân viên trung thành của bạn, Monit


19
Làm thế nào để bạn giữ cho Monit hoạt động?
JohnMudd

2
Cái này khá khó học. Tôi chỉ muốn khởi động lại một tập lệnh (thay vì một dịch vụ) và tôi đã đọc tài liệu của nó trong nhiều giờ nhưng không thể tìm ra.
Tyler Long

21

Nếu bạn đang sử dụng bản phân phối dựa trên systemd như Fedora và các bản phát hành Ubuntu gần đây, bạn có thể sử dụng khả năng "Khởi động lại" của systemd cho các dịch vụ. Nó có thể được thiết lập như một dịch vụ hệ thống hoặc một dịch vụ người dùng nếu nó cần được quản lý và chạy với tư cách là một người dùng cụ thể, điều này có nhiều khả năng xảy ra trong tình huống cụ thể của OP.

Các tùy chọn Restart mất một trong những no , on-success, on-failure, on-abnormal, on-watchdog, on-abort, hoặc always.

Để chạy nó với tư cách người dùng, chỉ cần đặt một tệp như sau vào ~/.config/systemd/user/something.service:

[Unit]
Description=Something

[Service]
ExecStart=/path/to/something
Restart=on-failure

[Install]
WantedBy=graphical.target

sau đó:

systemctl --user daemon-reload
systemctl --user [status|start|stop|restart] something

Không cần đặc quyền root / sửa đổi tệp hệ thống, không cần công việc cron, không cần cài đặt, linh hoạt như địa ngục (xem tất cả các tùy chọn dịch vụ liên quan trong tài liệu).

Xem thêm https://wiki.archlinux.org/index.php/Systemd/User để biết thêm thông tin về cách sử dụng phiên bản systemd cho mỗi người dùng.


Câu trả lời tuyệt vời, nhưng ~ / .config / systemd / user / something.service, đối với tôi, hơi mơ hồ. Phần "người dùng" có nghĩa đen là "người dùng" hay giống như "tên người dùng của bạn"? Nếu đó là "tên người dùng của bạn", điều đó theo tôi là thừa vì bạn đang tạo tệp này trong thư mục chính của mình. Chỉnh sửa: có vẻ như đó là "người dùng" theo nghĩa đen
fivedogit.

8

Tôi đã sử dụng từ cron "killall -0 tên chương trình || /etc/init.d/programname start". kill sẽ bị lỗi nếu quá trình không tồn tại. Nếu nó tồn tại, nó sẽ cung cấp một tín hiệu rỗng cho tiến trình (mà hạt nhân sẽ bỏ qua và không bận tâm truyền lại.)

Thành ngữ này rất dễ nhớ (IMHO). Nói chung, tôi sử dụng điều này trong khi tôi vẫn đang cố gắng khám phá lý do tại sao bản thân dịch vụ bị lỗi. IMHO một chương trình không nên biến mất một cách bất ngờ :)


7

Đặt quá trình chạy của bạn trong một vòng lặp- để khi thoát, nó sẽ chạy lại ... trong khi (true) {chạy ứng dụng của tôi ..}


4
Nếu tập lệnh đang chết vì lý do không xác định, có khả năng nó cũng sẽ hủy tập lệnh lặp, phải không?
Gareth

4
Tôi với Garath, nếu hệ thống của nó giết chết các quy trình đang chạy dài, thì vòng lặp được đề xuất - sẽ bắt đầu trước ứng dụng - sẽ bị giết trước.
ekerner

2
Để trả lời hai nhận xét của bạn: Không, nếu tập lệnh chết vì lý do không xác định thì tập lệnh vòng lặp không bị ảnh hưởng vì nó được chạy trong một quy trình riêng biệt - nhưng có, nếu hệ thống đang giết chết các quy trình đang chạy dài một cách ngẫu nhiên thì đây vẫn sẽ là một vấn đề - tuy nhiên tôi nghi ngờ đó là trường hợp. Phần còn lại của hệ thống không được báo cáo là bị ảnh hưởng và có đầy đủ các quy trình chạy lâu khác cũng sẽ được khởi động lại (chỉ đề cập đến một tập lệnh này có sự cố).
Klathzazt 19/09/12

4

Tôi không thể làm cho giải pháp của Chris Wendt hoạt động vì một số lý do và rất khó để gỡ lỗi. Cái này khá giống nhau nhưng dễ gỡ lỗi hơn, loại trừ bash khỏi khớp mẫu. Để debug chỉ cần chạy: bash ./root/makerun-mysql.sh. Trong ví dụ sau với mysql-server, chỉ cần thay thế giá trị của các biến cho processmakeruncho quy trình của bạn.

  • Tạo một BASH-script như sau ( nano /root/makerun-mysql.sh):
#!/bin/bash
process="mysql"
makerun="/etc/init.d/mysql restart"
if ps ax | grep -v grep | grep -v bash | grep --quiet $process
then
    printf "Process '%s' is running.\n" "$process"
    exit
else
    printf "Starting process '%s' with command '%s'.\n" "$process" "$makerun"
    $makerun
fi
exit
  • Đảm bảo rằng nó có thể thực thi bằng cách thêm các quyền tệp thích hợp (tức là chmod 700 /root/makerun-mysql.sh)

  • Sau đó, thêm cái này vào crontab ( crontab -e) của bạn :

# Keep processes running every 5 minutes
*/5 * * * * bash /root/makerun-mysql.sh

1
Hãy chú ý, so với giải pháp của Chris Wendt, tập lệnh không được bắt đầu như tác vụ nền ở đây.
Mason

2

Công supervisecụ từ daemontoolssẽ là sở thích của tôi - nhưng sau đó mọi thứ Dan J Bernstein viết là sở thích của tôi :)

http://cr.yp.to/daemontools/supervise.html

Bạn phải tạo một cấu trúc thư mục cụ thể cho tập lệnh khởi động ứng dụng của mình, nhưng nó rất đơn giản để sử dụng.


1

trước hết, làm thế nào để bạn khởi động ứng dụng này? Nó có tự phân nhánh với nền không? Nó được bắt đầu bằng nohup .. & etc? Nếu là cái sau, hãy kiểm tra lý do tại sao nó chết trong nohup.out, nếu là cái đầu tiên, hãy xây dựng nhật ký.

Đối với câu hỏi chính của bạn: bạn có thể cron nó hoặc chạy một quy trình khác trên nền (không phải là lựa chọn tốt nhất) và sử dụng pidof trong bashscript, đủ dễ dàng:

if [ `pidof -s app` -eq 0 ]; then
    nohup app &
fi

1

Bạn có thể đặt nó thành một dịch vụ được khởi chạy từ inittab (mặc dù một số Linux đã chuyển sang một thứ gì đó mới hơn trong /etc/event.d). Những hệ thống tích hợp này đảm bảo dịch vụ của bạn tiếp tục chạy mà không cần viết tập lệnh của riêng bạn hoặc cài đặt thứ gì đó mới.


1

Đó là một công việc cho DMD (daemon giám sát daemon). có một vài xung quanh; nhưng tôi thường chỉ viết một tập lệnh để kiểm tra xem daemon có đang chạy hay không, và chạy nếu không, và đặt nó vào cron để chạy mỗi phút.



1

Một cách hay và đơn giản để làm điều này như sau:

  1. Viết máy chủ của bạn chết nếu nó không thể nghe trên cổng mà nó mong đợi
  2. Đặt cronjob để cố gắng khởi chạy máy chủ của bạn mỗi phút

Nếu nó không chạy, nó sẽ bắt đầu và nếu nó đang chạy, nó sẽ không. Trong mọi trường hợp, máy chủ của bạn sẽ luôn hoạt động.


0

Tôi nghĩ rằng một giải pháp tốt hơn là nếu bạn cũng kiểm tra chức năng. Ví dụ, nếu bạn phải kiểm tra một apache, thì chỉ kiểm tra thôi là chưa đủ, nếu các quy trình "apache" trên hệ thống tồn tại.

Nếu bạn muốn kiểm tra xem apache có OK hay không, hãy thử tải xuống một trang web đơn giản và kiểm tra xem mã duy nhất của bạn có trong đầu ra hay không.

Nếu không, hãy giết apache bằng -9 và sau đó khởi động lại. Và gửi thư tới thư mục gốc (là địa chỉ thư được chuyển tiếp tới thư mục gốc của công ty / máy chủ / dự án).


1
Đây là sự thật. Rất nhiều giải pháp giám sát được đề xuất trong các câu trả lời khác cung cấp theo dõi giao thức.
Oli

0

Nó thậm chí còn đơn giản hơn:

#!/bin/bash

export DISPLAY=:0

process=processname
makerun="/usr/bin/processname"

if ! pgrep $process > /dev/null
then
    $makerun &
fi

Tuy nhiên, bạn phải nhớ để đảm bảo rằng tên quy trình là duy nhất.

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.