『壹』 ubuntu python怎麼作為守護進程一直運行
測試程序
先寫一個測試程序,用於輸出日誌和列印到控制台。
#-*- coding: utf-8 -*-
import logging
import time
from logging.handlers import RotatingFileHandler
def func():
init_log()
while True:
print "output to the console"
logging.debug("output the debug log")
logging.info("output the info log")
time.sleep(3);
def init_log():
logging.getLogger().setLevel(logging.DEBUG)
console = logging.StreamHandler()
console.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
console.setFormatter(formatter)
logging.getLogger().addHandler(console)
# add log ratate
Rthandler = RotatingFileHandler("backend_run.log", maxBytes=10 * 1024 * 1024, backupCount=100,
encoding="gbk")
Rthandler.setLevel(logging.INFO)
# formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
Rthandler.setFormatter(formatter)
logging.getLogger().addHandler(Rthandler)
if __name__ == '__main__':
func()
後台啟動Python腳本
可以使用下面的命令來啟動上面的腳本,讓Python在後台運行。
nohup python -u main.py > test.out 2>&1 &
來解釋一下這幾個命令的參數。這一段來自
其中 0、1、2分別代表如下含義:
0 – stdin (standard input)
1 – stdout (standard output)
2 – stderr (standard error)
nohup python -u main.py > test.out 2>&1 &
nohup+最後面的& 是讓命令在後台執行
>out.log 是將信息輸出到out.log日誌中
2>&1 是將標准錯誤信息轉變成標准輸出,這樣就可以將錯誤信息輸出到out.log 日誌裡面來。
運行命令後,會返回一個pid。像下面這樣:
[1] 9208
後續可以學習Hadoop它們,把pid存起來,到時候stop的時候就把它殺掉。
跟蹤輸出文件變化
為了驗證腳本可以在後台繼續運行,我們退出當前會話。然後重新連接一個Session,然後輸入下面的命令來跟蹤文件的輸出:
tail -f test.out
輸出內容如下:
output to the console
2017-03-21 20:15:02,632 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:02,632 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:05,635 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:05,636 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:08,637 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:08,638 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:11,640 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:11,642 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:14,647 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:14,647 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:17,653 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:17,654 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:20,655 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:20,656 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:23,661 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:23,661 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:26,665 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:26,666 main.py[line:12] INFO output the info log
output to the console
2017-03-21 20:15:29,670 main.py[line:11] DEBUG output the debug log
2017-03-21 20:15:29,671 main.py[line:12] INFO output the info log
說明我們的腳本確實在後台持續運行。
結束程序
可以直接通過之前的那個pid殺掉腳本,或者可以通過下面的命令查找pid。
ps -ef | grep python
輸出的內容如下:
root 1659 1 0 17:40 ? 00:00:00 /usr/bin/python /usr/lib/python2.6/site-packages/ambari_agent/AmbariAgent.py start
root 1921 1659 0 17:40 ? 00:00:48 /usr/bin/python /usr/lib/python2.6/site-packages/ambari_agent/main.py start
user 8866 8187 0 20:03 ? 00:00:06 /usr/bin/python3 /usr/bin/update-manager --no-update --no-focus-on-map
root 9208 8132 0 20:12 pts/16 00:00:00 python -u main.py
root 9358 8132 0 20:17 pts/16 00:00:00 grep --color=auto python
可以看到我們的pid是9208,調用kill殺掉就可以了。
kill -9 9208
編寫啟動及停止腳本
啟動腳本
#!/bin/sh
pid=`ps -ef|grep "python -u main.py"| grep -v "grep"|awk '{print $2}'`
if [ "$pid" != "" ]
then
echo "main.py already run, stop it first"
kill -9 ${pid}
fi
echo "starting now..."
nohup python -u main.py > test.out 2>&1 &
pid=`ps -ef|grep "python -u main.py"| grep -v "grep"|awk '{print $2}'`
echo ${pid} > pid.out
echo "main.py started at pid: "${pid}
停止腳本
#!/bin/sh
pid=`ps -ef|grep "python -u main.py"| grep -v "grep"|awk '{print $2}'`
if [ "$pid" != "" ]
then
kill -9 ${pid}
echo "stop main.py complete"
else
echo "main.py is not run, there's no need to stop it"
fi
稍後我會把實例代碼上傳到資料共享裡面。
『貳』 如何給腳本寫一個守護進程
在我們日常運維中,寫腳本監控一個進程是比較常見的操作,比如我要監控mysql進程是否消失,如果消失就重啟mysql,用下面這段代碼就可以實現:
#!/bin/sh
Date=` date '+%c'`
while :
do
if ! psaux | grep -w mysqld | grep -v grep >/dev/null 2>&1
then
/etc/init.d/mysqldstart
echo $Datemysqldwasreboot >>/var/log/reboot_mysql.log
fi
done
本篇這是以mysql為例子,但實際中如果是監控的腳本出了問題,報警沒發出來,那就比較尷尬了,所以為保證我們的檢查腳本能實時運行,我們需要一個進程來守護這個腳本,這就是我們今天要說的主題,如何給腳本寫一個daemon,我們先上代碼:
#!/usr/bin/python
import subprocess
from daemonimport runner
cmd = "/root/demo_script/restart_mysql.sh"
class App():
def __init__(self):
self.stdin_path = '/dev/null'
self.stdout_path = '/dev/tty'
self.stderr_path = '/dev/tty'
self.pidfile_path = '/tmp/hello.pid'
self.pidfile_timeout = 5
def start_subprocess(self):
return subprocess.Popen(cmd, shell=True)
def run(self):
p = self.start_subprocess()
while True:
res = p.poll()
if resis not None:
p = self.start_subprocess()
if __name__ == '__main__':
app = App()
daemon_runner = runner.DaemonRunner(app)
daemon_runner.do_action()
腳本比較簡單,沒什麼特別的邏輯,關於daemon這個模塊如何使用,我這里給出官方的解釋,注意喲,是英文的,我就不翻譯了,如果有生詞就查查字典,就當多學幾個了單詞吧。
__init__(self, app)
| Setuptheparametersof a new runner.
|
| The `app` :
|
| * `stdin_path`, `stdout_path`, `stderr_path`: Filesystem
| pathsto openand replacetheexisting `sys.stdin`,
| `sys.stdout`, `sys.stderr`.
|
| * `pidfile_path`: Absolutefilesystempathto a filethat
| willbeusedas thePIDfilefor thedaemon. If
| ``None``, noPIDfilewillbeused.
|
| * `pidfile_timeout`: Usedas thedefault acquisition
| timeoutvaluesuppliedto therunner's PIDlockfile.
|
| * `run`:
| started.
|
| do_action(self)
| Performtherequestedaction.
|
| parse_args(self, argv=None)
| Parsecommand-linearguments.
這樣就完成了,守護進程的啟動比較高大上,輸入以上代碼後,可以直接在終端輸入:
#python monitor.py start
當然還有stop,restart等參數。
這里我介紹的是其中一個應用場景,實際中可以靈活運用,比如1台伺服器上啟動的程序過多,環境配置比較復雜,就可以先啟動daemon進程,然後通過daemon來啟動其它所有應用程序,就不用一個一個應用程序啟動了,這篇就到這里,有問題可以給我留言。
『叄』 如何把 python predict程序 做成 windows 守護進程
importos,sys,commands,time
defdaemonize(stdin='/dev/null',stdout='/dev/null',stderr='/dev/null'):
"""setdaemonize"""
try:
pid=os.fork()
ifpid>0:
sys.exit(0)
exceptOSError,e:
sys.stderr.write("fork#1failed(%d)%s "%(e.errno,e.strerror))
sys.exit(0)
os.setsid()
os.chdir('.')
os.umask(0)
try:
pid=os.fork()
ifpid>0:
sys.exit(0)
exceptOSError,e:
sys.stderr.write("fork#2failed(%d)%s "%(e.errno,e.strerror))
sys.exit(0)
ifnotstderr:stderr=stdout
si=file(stdin,"r")
so=file(stdout,"w+")
se=file(stderr,"a+")
pid=str(os.getpid())
print"startwithpid:[%s]"%pid
fp=open("pid","w")
print>>fp,pid
fp.close()
sys.stderr.flush()
sys.stdout.flush()
sys.stderr.flush()
os.p2(si.fileno(),sys.stdin.fileno())
os.p2(so.fileno(),sys.stdout.fileno())
os.p2(se.fileno(),sys.stderr.fileno())
defmain():
daemonize(stdout='test.log',stderr='test.log')
cmd="ls"
while1:
(status,ret)=commands.getstatusoutput(cmd)
printstatus
printret
time.sleep(10)
if__name__=="__main__":
main()
『肆』 如何把crontab的時間觸發用python來實現守護進程式控制制
既然要用python來控制,為什麼還要crontab呢?直接通過python調用相應的命令執行 不就可以了么?
『伍』 如何用python編寫一個程序,在伺服器後台運行,每天刪除一些文件
首先利用
os.remove() will remove a file.
os.rmdir() will remove an empty directory.
shutil.rmtree() will delete a directory and all its contents.
寫你的模塊
利用Linux crontab定時任務運行這個模塊。
還可以以守護進程的方式運行你的腳本。nohup <程序名> &
『陸』 如何使用Python守護進程和腳本
項目過程中,經常會有很多的腳本,Shell腳本、PHP腳本、Python腳本等,更有一些腳本是需要常駐內存執行的,簡而言之就是需要while(true){}的模式執行。
但是有的時候,一個常駐內存的進程會因為某些耗時操作而夯住,不再往下繼續執行,成為了一個僵屍進程;或者因為某個操作偶然出錯,直接退出了;
所以我們需要有一套簡單的機制來保證進程一直處於活躍狀態。
『柒』 如何在python腳本中新建一個守護子進程
函數實現
[html] view plain
#!/usr/bin/env python
#coding: utf-8
import sys, os
'''將當前進程fork為一個守護進程
注意:如果你的守護進程是由inetd啟動的,不要這樣做!inetd完成了
所有需要做的事情,包括重定向標准文件描述符,需要做的事情只有chdir()和umask()了
'''
def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
#重定向標准文件描述符(默認情況下定向到/dev/null)
try:
pid = os.fork()
#父進程(會話組頭領進程)退出,這意味著一個非會話組頭領進程永遠不能重新獲得控制終端。
if pid > 0:
sys.exit(0) #父進程退出
except OSError, e:
sys.stderr.write ("fork #1 failed: (%d) %s\n" % (e.errno, e.strerror) )
sys.exit(1)
#從母體環境脫離
os.chdir("/") #chdir確認進程不保持任何目錄於使用狀態,否則不能umount一個文件系統。也可以改變到對於守護程序運行重要的文件所在目錄
os.umask(0) #調用umask(0)以便擁有對於寫的任何東西的完全控制,因為有時不知道繼承了什麼樣的umask。
os.setsid() #setsid調用成功後,進程成為新的會話組長和新的進程組長,並與原來的登錄會話和進程組脫離。
#執行第二次fork
try:
pid = os.fork()
if pid > 0:
sys.exit(0) #第二個父進程退出
except OSError, e:
sys.stderr.write ("fork #2 failed: (%d) %s\n" % (e.errno, e.strerror) )
sys.exit(1)
#進程已經是守護進程了,重定向標准文件描述符
for f in sys.stdout, sys.stderr: f.flush()
si = open(stdin, 'r')
so = open(stdout, 'a+')
se = open(stderr, 'a+', 0)
os.p2(si.fileno(), sys.stdin.fileno()) #p2函數原子化關閉和復制文件描述符
os.p2(so.fileno(), sys.stdout.fileno())
os.p2(se.fileno(), sys.stderr.fileno())
#示例函數:每秒列印一個數字和時間戳
def main():
import time
sys.stdout.write('Daemon started with pid %d\n' % os.getpid())
sys.stdout.write('Daemon stdout output\n')
sys.stderr.write('Daemon stderr output\n')
c = 0
while True:
sys.stdout.write('%d: %s\n' %(c, time.ctime()))
sys.stdout.flush()
c = c+1
time.sleep(1)
if __name__ == "__main__":
daemonize('/dev/null','/tmp/daemon_stdout.log','/tmp/daemon_error.log')
main()
可以通過命令ps -ef | grep daemon.py查看後台運行的繼承,在/tmp/daemon_error.log會記錄錯誤運行日誌,在/tmp/daemon_stdout.log會記錄標准輸出日誌。
『捌』 Linux下的守護進程的概念daemon.py是什麼意思
守護進程一般是伺服器類程序中用來無限循環等待事件發生的一個進程或線程,也就是說,它的作用是等待一個事件發生,事件發生後調用另外的進程區完成相應的工作,自己再回去等事件發生。
用ps aux查看進程的進程號,然後用kill殺掉
py是後綴名,意思是用python語言寫的。
至於如何重啟,這個沒有統一的方法。你可以查看相關的文檔,或者在google上搜索,或者man一下。。
守護進程一個或者多個都是可能的。
『玖』 如何使用Python的Supervisor來管理進程
在python開發中,如何使用supervisor來管理進程呢?Supervisor是什麼?Supervisor是如何管理進程的,現在就跟隨小編一起來看看使用python的supervisor管理經常的方法。
Supervisor可以啟動、停止、重啟*nix系統中的程序。也可以重啟崩潰的程序。
supervisord的一個守護進程,用於將指定的進程當做子進程來運行。
supervisorctl是一個客戶端程序,可以查看日誌並通過統一的會話來控制進程。
看例子:
我們寫了一個py腳本,用於往log文件中記錄一條當前的時間。
[python]view plain
1.root@ubuntu:/home/zoer#catdaemon.py
2.#!/usr/bin/envpython
3.
4.importtime
5.importos
6.time.sleep(1)
7.f=open("log",'a')
8.t=time.time()
9.f.write(str(t))
10.f.write("\n")
11.f.close()
安裝過程就不說了。
安裝完畢supervisor之後【將配置文件放在/etc下】。修改配置文件,在最後增加如下內容:
[program:ddd]
command=/home/zoer/daemon.py
autorestart=true
然後我們啟動supervisor並啟動daemon.py的執行。
[python]view plain
1.root@ubuntu:/home/zoer#supervisord
2./usr/local/lib/python2.7/dist-packages/supervisor-3.0b1-py2.7.egg/supervisor/options.py:286:UserWarning:aultlocations();youprobablywanttospecifya"-c"y.
3.''
4.root@ubuntu:/home/zoer#supervisorctl
5.dddSTARTING
6.supervisor>startddd
7.ddd:ERROR(alreadystarted)
8.supervisor>stopddd
9.ddd:stopped
10.supervisor>startddd
11.ddd:started
12.supervisor>
從上面的例子中,看到,可以通過start或者stop命令來啟動或者停止ddd這個進程。ddd這里就是我們在配置文件中增加的內容(daemon.py這個腳本)。
也可以使用restart。如下:
supervisor> restart ddd
ddd: stopped
ddd: started
-------------------------------------------------------
下面我們測試一下,假設說我們手動kill掉了ddd這個進程,那麼ddd會自動恢復執行嗎?
為了做實驗,把代碼修改如下:
[python]view plain
1.root@ubuntu:/home/zoer#catdaemon.py
2.#!/usr/bin/envpython
3.
4.importtime
5.importos
6.whileTrue:
7.time.sleep(1)
8.f=open("log",'a')
9.t=time.time()
10.f.write(str(t))
11.f.write("\n")
12.f.close()
通過ps可以找到這個進程的id:
[plain]view plain
1.root93540.20.4109244200?S23:160:00python/home/zoer/daemon.py
2.root93950.00.04392832pts/3S+23:170:00grep--color=autodaemon
3.root@ubuntu:/home/zoer#
看下面的操作:
[plain]view plain
1.root@ubuntu:/home/zoer#rmlog;touchlog;kill9354
2.root@ubuntu:/home/zoer#catlog
3.1364710712.51
4.root@ubuntu:/home/zoer#catlog
5.1364710712.51
6.1364710713.51
7.root@ubuntu:/home/zoer#catlog
8.1364710712.51
9.1364710713.51
10.root@ubuntu:/home/zoer#catlog
11.1364710712.51
12.1364710713.51
13.1364710714.52
14.root@ubuntu:/home/zoer#catlog
15.1364710712.51
16.1364710713.51
17.1364710714.52
18.1364710715.52
刪除了log文件,並且重新創建。然後幹掉了daemon.py的那個進程。會發現log內容又重新有新的內容了。再次ps查看進程號。
[plain]view plain
1.root94290.10.4109244200?S23:180:00python/home/zoer/daemon.py
2.root94400.00.04392828pts/3S+23:190:00grep--color=autodaemon
3.root@ubuntu:/home/zoer#
會發現進程號已經變成9429了。說明supervisor已經重啟了被幹掉了的進程。
『拾』 python 怎麼設置守護進程
thread[i].join()
用join()方法去設置守護線程。
不過此方法只在threading中才有。