我编写了一个Python脚本,用于检查某个电子邮件地址并将新的电子邮件传递给外部程序。如何使此脚本在Linux中成为守护进程或服务并24/7运行?是否需要在程序中添加不断循环的代码,还是可以通过多次重新执行代码来实现?
apt-get install screen
创建一个名为abc的虚拟终端:screen -dmS abc
现在连接到abc:screen -r abc
现在,我们可以运行Python脚本:python keep_sending_mails.py
从此以后,您可以直接关闭终端,但是Python脚本将继续运行而不被关闭。keep_sending_mails.py
的PID是虚拟屏幕而不是终端(ssh)的子进程,screen -r abc
。您可以编写一个简单的脚本,每次向特定邮箱发送邮件时都会被sendmail执行。
请参见 http://www.feep.net/sendmail/tutorial/intro/aliases.html。
如果您真的想编写一个毫无必要的复杂服务器,您可以这样做。
nohup python myscript.py &
import time
def do_the_work():
# one round of polling -- checking email, whatever.
while True:
time.sleep( 600 ) # 10 min.
try:
do_the_work()
except:
pass
do_the_work()
可能会导致脚本崩溃,没有人会再次运行它。 - Ivan Nevostruevrun
。import sys
import os
from signal import SIGTERM
from abc import ABCMeta, abstractmethod
class Daemon(object):
__metaclass__ = ABCMeta
def __init__(self, pidfile):
self._pidfile = pidfile
@abstractmethod
def run(self):
pass
def _daemonize(self):
# decouple threads
pid = os.fork()
# stop first thread
if pid > 0:
sys.exit(0)
# write pid into a pidfile
with open(self._pidfile, 'w') as f:
print >> f, os.getpid()
def start(self):
# if daemon is started throw an error
if os.path.exists(self._pidfile):
raise Exception("Daemon is already started")
# create and switch to daemon thread
self._daemonize()
# run the body of the daemon
self.run()
def stop(self):
# check the pidfile existing
if os.path.exists(self._pidfile):
# read pid from the file
with open(self._pidfile, 'r') as f:
pid = int(f.read().strip())
# remove the pidfile
os.remove(self._pidfile)
# kill daemon
os.kill(pid, SIGTERM)
else:
raise Exception("Daemon is not started")
def restart(self):
self.stop()
self.start()
如果您想创建类似服务的东西,可以使用以下内容:
首先,您必须安装Cement框架: Cement框架是一个CLI框架,您可以在其中部署应用程序。
应用程序的命令行界面为:
interface.py
from cement.core.foundation import CementApp
from cement.core.controller import CementBaseController, expose
from YourApp import yourApp
class Meta:
label = 'base'
description = "your application description"
arguments = [
(['-r' , '--run'],
dict(action='store_true', help='Run your application')),
(['-v', '--version'],
dict(action='version', version="Your app version")),
]
(['-s', '--stop'],
dict(action='store_true', help="Stop your application")),
]
@expose(hide=True)
def default(self):
if self.app.pargs.run:
#Start to running the your app from there !
YourApp.yourApp()
if self.app.pargs.stop:
#Stop your application
YourApp.yourApp.stop()
class App(CementApp):
class Meta:
label = 'Uptime'
base_controller = 'base'
handlers = [MyBaseController]
with App() as app:
app.run()
YourApp.py类:
import threading
class yourApp:
def __init__:
self.loger = log_exception.exception_loger()
thread = threading.Thread(target=self.start, args=())
thread.daemon = True
thread.start()
def start(self):
#Do every thing you want
pass
def stop(self):
#Do some things to stop your application
python interface.py --help
subprocess.Popen(arguments, close_fds=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, stdin=subprocess.DEVNULL)
或者使用现成的工具
使用系统提供的任何服务管理器 - 例如在Ubuntu下使用upstart。这将为您处理所有细节,如启动时自动启动,崩溃后重新启动等。
systemd
的现代 Linux 上,您可以按照此处所述的方式创建一个以daemon
模式运行的 systemd 服务。另请参阅:https://www.freedesktop.org/software/systemd/man/systemd.service.html - ccpizza