如何确保应用程序在Linux上保持运行


83

我试图确保脚本仍在开发服务器上运行。它整理统计数据并提供Web服务,因此应该可以持续使用,但是一天几次,它会由于未知原因而死掉。当我们注意到我们只是再次启动它时,但是后部很痛苦,有些用户没有权限(或专有技术)来启动它。

我内的程序员想花几个小时来解决问题的根源,但内心的忙碌的人认为必须有一种简便的方法来检测应用程序是否未运行,然后重新启动它。

我知道我可以通过grep cron-script ps:

ps -A | grep appname

但是,这又是我生命中另一个小时的浪费,因为它必须做一些必须已经存在的事情……难道没有一个预制的应用程序,我可以传递一个可执行文件(可选地带有参数),并且可以使进程无限期地运行吗?

如果有什么不同,那就是Ubuntu。


1
这取决于在脚本不运行时是否会丢失统计信息,但是我认为您中的程序员是正确的-您应该了解有关脚本为什么不会无限期继续的更多信息。
乔纳森·莱夫勒

1
它更多是按需服务实用程序,而不是不断处理数字的东西。如果在保存数据之前崩溃,则不会丢失任何内容;它将在下次运行时完成工作。
奥利


这个问题是通过init.dStandard或保持活动进程的最佳方式回答的。解决方案包括使用systemd和/etc/inittab
koppor

Answers:


37

注意:Upstart处于维护模式,被使用systemd的Ubuntu放弃。一个人应该查阅系统手册,详细了解如何编写服务定义。

由于您使用的是Ubuntu,因此您可能会对Upstart感兴趣,它已取代了传统的sysV init。一个关键功能是,如果服务意外终止,它可以重新启动服务。Fedora已步入新贵,而Debian处于试验阶段,因此可能值得研究。

但是,对于这种情况,这可能是过大的,因为cron脚本将需要2分钟才能实现。

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

我必须注意,配置新贵来管理服务并保持其运行非常简单(您编写了小的配置文件)。与任何其他基于“简单” cron / shell脚本的监视相比,该解决方案更加干净,简单和更好。
2012年

@thor-(请注意,这是从2008年开始的,当时是新贵,而且文档也很难提供)。我同意,“简单”的cron脚本只是为了说明脚本也不需要复杂即可完成工作。
JimB 2012年

我懂了。把我的意见时,我已反正upvoted你的答案
托尔

85

我已使用带有cron的简单脚本来确保程序正在运行。如果不是,它将启动它。这可能不是您正在寻找的完美解决方案,但是它很简单并且效果很好。

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

然后每分钟或每5分钟添加一次cron作业。


2
天才。它可以在重启后幸存下来,而无需安装任何内容。
伊恩·普顿

我自己使用了它,因为它不需要root特权即可安装。
JohnMudd

将在什么process name,如果我想保持一个Python脚本运行?
用户

@User用于ps ax | grep XXX仅列出您的进程,然后是XXX。
strongwillow

11
作为单行程序,每分钟运行一次:* * * * * ps aux|grep -v grep|grep -q YourProcessName || /usr/bin/program &
ACK_stoverflow,2016年

43

Monit非常适合此:)

您可以编写简单的配置文件来告诉监控程序,例如TCP端口,PID文件等

当监视的进程不可用/使用过多的内存/将CPU固定的时间太长/等等时,monit会运行您指定的命令。它还会弹出一封电子邮件警报,告诉您发生了什么以及它是否可以采取任何措施。

我们用它来保持我们网站的负载,同时在出现问题时给我们预警。

-您忠实的员工Monit


19
如何保持Monit运行?
JohnMudd

2
这个很难学。我只想重新启动脚本(而不是服务),并且阅读了数小时的文档,但无法弄清楚。
泰勒·朗

21

如果您使用的是基于系统的发行版(例如Fedora和最新的Ubuntu版本),则可以使用systemd的“重新启动”功能来提供服务。如果需要由特定用户管理并以特定用户运行,则可以将其设置为系统服务或用户服务,这在OP的特定情况下更可能发生。

重新启动选项需要之一 noon-successon-failureon-abnormalon-watchdogon-abort,或always

要以用户身份运行,只需将以下文件放入~/.config/systemd/user/something.service

[Unit]
Description=Something

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

[Install]
WantedBy=graphical.target

然后:

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

无需root特权/无需修改系统文件,无需cron作业,无需安装任何内容,灵活如地狱(请参阅文档中的所有相关服务选项)。

另请参阅https://wiki.archlinux.org/index.php/Systemd/User,以获取有关使用每用户systemd实例的更多信息。


很好的答案,但是〜/ .config / systemd / user / something.service对我来说有点模棱两可。“用户”部分是字面上的“用户”还是“您的用户名”?如果它是“ yourusername”,那是多余的,因为您是在主目录中创建此文件的。编辑:看起来像是名副其实的“用户”
Fivedogit

8

我从cron使用“ killall -0程序名|| /etc/init.d/programname开始”。如果该进程不存在,kill将会出错。如果确实存在,它将向进程传递一个空信号(内核将忽略该信号,并且不会继续传递。)

这个成语很容易记住(IMHO)。通常,在我仍试图发现服务本身为何失败时,我会使用它。恕我直言,程序不应该只是突然消失:)


7

将您的运行置于循环中-因此,当它退出时,它将再次运行... while(true){运行我的应用程序。


4
如果脚本死于未知原因,很可能它也会取消循环脚本,不是吗?
Gareth

4
我和Garath在一起,如果它的系统杀死了长时间运行的进程,则建议的循环-将在应用程序之前启动-首先被杀死。
ekerner's

2
要回答您的两个评论:否,如果脚本因未知原因而死,则循环脚本不会受到影响,因为它是在单独的进程中运行的;但是,是的,如果系统随机杀死长时间运行的进程,那么这仍然是一个问题-但是,我怀疑情况确实如此。尚未报告系统的其余部分受到影响,并且充满了其他本应重新启动的长时间运行的进程(仅提及此脚本有问题)。
Klathzazt 2012年

4

由于某种原因,我无法使Chris Wendt解决方案正常工作,而且调试起来很困难。这几乎相同,但更易于调试,将bash排除在模式匹配之外。要调试,只需运行:bash ./root/makerun-mysql.sh。在下面的例子与MySQL服务器只需更换变量的值process,并makerun为您的过程。

  • 像这样创建一个BASH脚本(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
  • 通过添加适当的文件权限(例如chmod 700 /root/makerun-mysql.sh)来确保其可执行

  • 然后将其添加到您的crontab(crontab -e):

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

1
请注意,与Chris Wendt的解决方案相比,该脚本不是在此处作为后台任务启动的。
梅森


1

首先,您如何启动该应用程序?它会将自己分叉到后台吗?是从nohup ..&etc开始的吗?如果是后者,请检查为什么它在nohup.out中死亡,如果是后者,则构建日志记录。

关于您的主要问题:您可以将其设置为cron,或在后台运行另一个进程(不是最佳选择),并在bashscript中使用pidof,这很容易:

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

1

您可以将其设为从inittab启动的服务(尽管某些Linux迁移到了/etc/event.d中的较新版本)。这些内置的系统可确保您的服务保持运行,而无需编写自己的脚本或安装新的东西。


1

这是DMD(守护程序监视守护程序)的工作。周围有一些 但是我通常只是编写一个脚本来检查守护程序是否正在运行,如果没有运行,则将其放到cron中以每分钟运行一次。



1

一个不错的简单方法如下:

  1. 如果无法侦听期望的端口,则将服务器写死
  2. 设置cronjob尝试每分钟启动服务器

如果没有运行,它将启动,如果正在运行,它将不会启动。无论如何,您的服务器将始终处于运行状态。


0

我认为更好的解决方案是同时测试功能。例如,如果必须测试apache,仅测试系统上是否存在“ apache”进程是不够的。

如果要测试apache OK是否正常,请尝试下载一个简单的网页,然后测试输出中是否包含唯一的代码。

如果不是,请使用-9杀死Apache,然后重新启动。并将邮件发送到根(这是转发到公司/服务器/项目的根的邮件地址)。


1
这是真的。其他答案中建议的许多监视解决方案确实提供协议监视。
奥利

0

它甚至更简单:

#!/bin/bash

export DISPLAY=:0

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

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

您必须记住,但要确保进程名是唯一的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.