我写了一个Python脚本,检查一个特定的电子邮件地址,并将新的电子邮件传递给一个外部程序。如何让这个脚本全天候执行,比如在Linux中将其转换为守护进程或服务。我是否还需要一个在程序中永不结束的循环,或者可以通过多次重新执行代码来完成?
当前回答
要创建一些像service一样运行的东西,你可以使用这个东西:
你必须做的第一件事是安装水泥框架: 水泥框架是一个CLI框架,您可以在其上部署应用程序。
app命令行界面:
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
其他回答
一个简单且受支持的版本是Daemonize。
从Python包索引(PyPI)安装它:
$ pip install daemonize
然后用like:
...
import os, sys
from daemonize import Daemonize
...
def main()
# your code here
if __name__ == '__main__':
myname=os.path.basename(sys.argv[0])
pidfile='/tmp/%s' % myname # any name
daemon = Daemonize(app=myname,pid=pidfile, action=main)
daemon.start()
你应该使用python-daemon库,它会处理所有的事情。
从PyPI:库实现一个行为良好的Unix守护进程。
首先,仔细研究邮件别名。邮件别名将在邮件系统内完成此任务,而无需您在守护进程或服务或任何类似的东西上瞎忙活。
您可以编写一个简单的脚本,每次将邮件消息发送到特定邮箱时,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
我推荐这个解决方案。您需要继承和重写方法运行。
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()
假设您真的希望您的循环作为后台服务全天候运行
对于一个不需要向代码中注入库的解决方案,你可以简单地创建一个服务模板,因为你使用的是linux:
[Unit]
Description = <Your service description here>
After = network.target # Assuming you want to start after network interfaces are made available
[Service]
Type = simple
ExecStart = python <Path of the script you want to run>
User = # User to run the script as
Group = # Group to run the script as
Restart = on-failure # Restart when there are errors
SyslogIdentifier = <Name of logs for the service>
RestartSec = 5
TimeoutStartSec = infinity
[Install]
WantedBy = multi-user.target # Make it accessible to other users
将该文件放在您的守护进程服务文件夹(通常是/etc/systemd/system/)中,*. .使用以下systemctl命令安装它(可能需要sudo权限):
systemctl enable <service file name without .service extension>
systemctl daemon-reload
systemctl start <service file name without .service extension>
然后你可以使用命令检查你的服务是否在运行:
systemctl | grep running
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 在Bash中检查变量是否存在于列表中
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 查看PS命令的全部输出