一、 前言
-
Windows
和Linux
平臺下有時候需要后臺啟動, 脫離界面(拋去黑色cmd和脫離終端)運行程序并常駐內(nèi)存;同時能夠具備一定的日志記錄和異常自啟動等特點。 - 對于后臺啟動和守護(hù)進(jìn)程概念上不做過多區(qū)分;當(dāng)然我們可以通過使用Web服務(wù)器托管或者直接運行啟動;但這些與后臺運行相違背
- 由于筆者是golang開發(fā)的web項目,并且已經(jīng)打包成可執(zhí)行文件,就簡單了解下目前已知的偏后端后臺啟動的幾種方式(前端的推薦一個pm2挺不錯的)。當(dāng)然通過docker部署是個不錯的策略,但是與今天討論的話題是有很大區(qū)別的。
二、 Windows環(huán)境程序后臺運行
對于windows環(huán)境很少會用來作為服務(wù)器,由于系統(tǒng)的定位和其一定的封閉性使得在這快能夠選擇的方式不多。
1. 對于c#程序winform和.net
對于這類可以直接通過隱藏窗體任務(wù)欄或直接創(chuàng)建windows服務(wù)程序(推薦),這塊內(nèi)容請移步至微軟官方文檔 創(chuàng)建windows服務(wù)了解
2. 對于不是通過打包執(zhí)行
這里很多是通過安裝使用第三方庫用代碼控制,如golang的github.com/kardianos/service
3. 對于其他程序打包后生成的可執(zhí)行文件
例如 golang 或者 python等程序打包后生成的.exe可執(zhí)行文件,如果想實現(xiàn)脫離命令行、脫離終端運行,則需要將 可執(zhí)行文件注冊成windows服務(wù)。
(備注): 有了解到網(wǎng)上說使用:sc命令
、start /b xxx.exe命令
、.vbs文件
、.bat
、c/c++懵圈代碼
和修改注冊表
等。個人觀點不推薦,原因有二:簡便性和通用性。
這里有兩個程序,但是推薦最后一個b
a. 微軟Microsoft Windows Resource Kits工具集中提供的兩個小工具“instsrv.exe”和“srvany.exe” 但是要求手動修改注冊表,所以不太建議用:
先下載這兩個程序然后放在同一個目錄,例如都放在D盤,然后進(jìn)入到DOS命令行下面輸入如下命令注冊服務(wù):d:\instsrv.exe mySharedService d:\srvany.exe //mySharedService是服務(wù)名 // 這個命令是把srvany.exe這個程序注冊成了系統(tǒng)服務(wù)
接下來需要修改注冊表
同時按住windows鍵
和r鍵
在彈出的運行框中輸入regedit
,然后回車。修改HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services 路徑下找到剛剛注冊的服務(wù)名mySharedService,右擊新建一個項,名稱為“Parameters”,單擊選中它然后在右側(cè)的窗口新建一個字符串值名稱為“Application”,將其值設(shè)置為要注冊的可執(zhí)行文件exe的路徑。同樣的方式也可以指定再建立一個AppDirectory指定程序運行的初始目錄;AppParameters 值為程序啟動所需要的參數(shù)等。
然后運行net start mySharedService即可啟動,停止刪除服務(wù),見net 命令
b. 通過使用nssm程序來實現(xiàn)可執(zhí)行程序的注冊服務(wù),簡單高效
首先,安裝官網(wǎng)安裝 nssm 解壓選里面的64位系統(tǒng)的執(zhí)行程序,將nssm.exe添加到系統(tǒng)環(huán)境變量(或者跟上面一樣放到d盤)
然后注冊服務(wù),通過如下命令(mgt_test_service為服務(wù)名)nssm install mgt_test_service
會出現(xiàn)窗口提示,通過配置如下
nssm配置圖.png
右邊的details可以配置服務(wù)的展示名稱和描述信息,以及啟動方式
nssm-details配置圖.png
點擊 install service即可注冊服務(wù);
服務(wù)管理主要有啟動、停止和重啟,其命令如下:
啟動服務(wù):nssm start mgt_test_service
停止服務(wù): nssm stop mgt_test_service
重啟服務(wù): nssm restart mgt_test_service
當(dāng)然,也可以使用系統(tǒng)自帶的服務(wù)管理器操作和使用系統(tǒng)的命令
如果需要修改參數(shù)可以使用: nssm edit mgt_test_service
如果刪除服務(wù)可以使用: nssm remove mgt_test_service
通過在運行窗口輸入services.msc
可以找到mgt_test_service這個服務(wù)。
三、Linux環(huán)境程序后臺運行
其實Linux系統(tǒng)有自己的守護(hù)進(jìn)程管理工具 Systemd,直接和內(nèi)核的交互可以將服務(wù)變成系統(tǒng)服務(wù),性能也很強,本文不進(jìn)行介紹。這里推薦幾個常用的工具和命令并簡述他們之間的區(qū)別。
命令:nohup
、screen
工具:supervisor
1. nohup命令
用法 nohup ./web_pack &
(web_pack是打包后的可執(zhí)行文件, '&'可以將當(dāng)前進(jìn)程變成后臺任務(wù))
nohup的特點:
- 該命令會阻止SIGHUP信號發(fā)到這個進(jìn)程
- 關(guān)閉標(biāo)準(zhǔn)輸入,該進(jìn)程不再能夠接收任何輸入
- 重定向標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤到文件nohup.out
2. screen命令
- 首先安裝
# 安裝screen 多數(shù)linux系統(tǒng)已經(jīng)安裝了
apt-get install screen
操作流程如下:
- 新建一個screen會話
# 新建一個session
screen
# 創(chuàng)建多個session, 需要指定name區(qū)分
screen -S name1
screen -S name2
# 查看已經(jīng)創(chuàng)建的session
screen -ls
- 出現(xiàn)如下頁面,表示安裝成功,依據(jù)提示我們按一個
空格鍵
新建screen會話頁面.png - 接下我們執(zhí)行啟動項目的命令
# 進(jìn)入項目,啟動運行服務(wù)(web_pack是我打包后的可執(zhí)行文件,這里依據(jù)情況執(zhí)行自己項目的啟動命令)
./web_pack
可以看到我的服務(wù)啟動并監(jiān)聽了8088端口,但是還沒有脫離終端,當(dāng)前仍處于上面創(chuàng)建的screen session。我們需要退出跳出這個screen,執(zhí)行如下命令。
- 離開當(dāng)前的screen 會話
按住ctrl + A
和ctrl + D
,會跳出當(dāng)前創(chuàng)建的screen,可以看到下面的頁面
跳出screen界面.png
通過測試訪問本地8088端口得到返回數(shù)據(jù),確實服務(wù)已經(jīng)后臺啟動了。
測試本地服務(wù).png
關(guān)閉終端后并不影響后臺程序運行。 - 刪除已經(jīng)創(chuàng)建的screen
先進(jìn)入,如果只有一個可以直接screen -r
,多個可以通過screen -r name1
;
然后停掉服務(wù),關(guān)閉退出,按住ctrl + C
和ctrl + D
,即可關(guān)閉如下圖所示
關(guān)閉session會話.png
screen的特點:
- 可在當(dāng)前screen session 里新建另一個或多個 session;
- 當(dāng)前 session是否關(guān)閉不影響創(chuàng)建的session;
- 以后重新登錄,還可以再連上早先新建的 session;
- 不具備服務(wù)托管特性,沒有出錯重啟或日志跟蹤等
3. supervisor進(jìn)程托管工具
supervisor是我用的較多的守護(hù)進(jìn)程管理工具,python開發(fā)的可將一個普通的命令行進(jìn)程變?yōu)楹笈_daemon,并監(jiān)控進(jìn)程狀態(tài),支持異常重啟和支持運行日志的記錄。
詳細(xì)文檔說明參考supervisor 官網(wǎng)
- 安裝supervisor
# ubuntu系統(tǒng)通過apt安裝
apt-get install supervisor
# pip 安裝
pip install supervisor
- 配置supervisor
進(jìn)入到/etc/supervisor可以看到如下目錄內(nèi)容
supervisor配置目錄結(jié)構(gòu).png
supervisor的配置文件supervisord.conf
需要管理的子進(jìn)程配置文件目錄/conf.d
本人已添加的配置文件hexo_auto.conf
這里貼一下網(wǎng)上的關(guān)于配置文件的說明,了解下即可,被管理的進(jìn)程配置見后。
[unix_http_server]
file=/tmp/supervisor.sock ;UNIX socket 文件,supervisorctl 會使用
;chmod=0700 ;socket文件的mode,默認(rèn)是0700
;chown=nobody:nogroup ;socket文件的owner,格式:uid:gid
;[inet_http_server] ;HTTP服務(wù)器,提供web管理界面
;port=127.0.0.1:9001 ;Web管理后臺運行的IP和端口,如果開放到公網(wǎng),需要注意安全性
;username=user ;登錄管理后臺的用戶名
;password=123 ;登錄管理后臺的密碼
[supervisord]
logfile=/tmp/supervisord.log ;日志文件,默認(rèn)是 $CWD/supervisord.log
logfile_maxbytes=50MB ;日志文件大小,超出會rotate,默認(rèn) 50MB,如果設(shè)成0,表示不限制大小
logfile_backups=10 ;日志文件保留備份數(shù)量默認(rèn)10,設(shè)為0表示不備份
loglevel=info ;日志級別,默認(rèn)info,其它: debug,warn,trace
pidfile=/tmp/supervisord.pid ;pid 文件
nodaemon=false ;是否在前臺啟動,默認(rèn)是false,即以 daemon 的方式啟動
minfds=1024 ;可以打開的文件描述符的最小值,默認(rèn) 1024
minprocs=200 ;可以打開的進(jìn)程數(shù)的最小值,默認(rèn) 200
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ;通過UNIX socket連接supervisord,路徑與unix_http_server部分的file一致
;serverurl=http://127.0.0.1:9001 ; 通過HTTP的方式連接supervisord
; [program:xx]是被管理的進(jìn)程配置參數(shù),xx是進(jìn)程的名稱
[program:xx]
command=/opt/apache-tomcat-8.0.35/bin/catalina.sh run ; 程序啟動命令
autostart=true ; 在supervisord啟動的時候也自動啟動
startsecs=10 ; 啟動10秒后沒有異常退出,就表示進(jìn)程正常啟動了,默認(rèn)為1秒
autorestart=true ; 程序退出后自動重啟,可選值:[unexpected,true,false],默認(rèn)為unexpected,表示進(jìn)程意外殺死后才重啟
startretries=3 ; 啟動失敗自動重試次數(shù),默認(rèn)是3
user=tomcat ; 用哪個用戶啟動進(jìn)程,默認(rèn)是root
priority=999 ; 進(jìn)程啟動優(yōu)先級,默認(rèn)999,值小的優(yōu)先啟動
redirect_stderr=true ; 把stderr重定向到stdout,默認(rèn)false
stdout_logfile_maxbytes=20MB ; stdout 日志文件大小,默認(rèn)50MB
stdout_logfile_backups = 20 ; stdout 日志文件備份數(shù),默認(rèn)是10
; stdout 日志文件,需要注意當(dāng)指定目錄不存在時無法正常啟動,所以需要手動創(chuàng)建目錄(supervisord 會自動創(chuàng)建日志文件)
stdout_logfile=/opt/apache-tomcat-8.0.35/logs/catalina.out
stopasgroup=false ;默認(rèn)為false,進(jìn)程被殺死時,是否向這個進(jìn)程組發(fā)送stop信號,包括子進(jìn)程
killasgroup=false ;默認(rèn)為false,向進(jìn)程組發(fā)送kill信號,包括子進(jìn)程
;包含其它配置文件
[include]
files = relative/directory/*.ini ;可以指定一個或多個以.ini結(jié)束的配置文件
上面的配置文件中"[program:xx]"部分也說明了被管理進(jìn)程的配置參數(shù),這里放一下上面我的hexo_auto.conf
的簡單配置
[program:hexo-blog]
command=/usr/local/node/bin/hexo server
directory=/root/hexo/my-hexo-blog
autostart=true
startsecs=10
autorestart=true
startretries=3
# 執(zhí)行的用戶
user=root
# 值小的優(yōu)先啟動
priority=999
# 把stderr重定向到stdout,默認(rèn)false
redirect_stderr=true
stdout_logfile_maxbytes=20MB
# 備份文件數(shù)目
stdout_logfile_backups = 20
# 日志文件
stdout_logfile=/root/hexo/my-hexo-blog.log
# 默認(rèn)為false,進(jìn)程被殺死時,是否向這個進(jìn)程組發(fā)送stop信號,包括子進(jìn)程
stopasgroup=false
# 默認(rèn)為false,向進(jìn)程組發(fā)送kill信號,包括子進(jìn)程
killasgroup=false
這個配置是用來在/root/hexo/my-hexo-blog路徑下啟動hexo服務(wù)的代碼,服務(wù)起名為hexo-blog
- 運行supervisor并添加子進(jìn)程任務(wù)hexo-blog,最后啟動任務(wù)即可。
# 啟動服務(wù)
sudo service supervisor start
# 更新下配置
sudo supervisorctl update
# 啟動任務(wù)
sudo supervisorctl start hexo-blog
如果修改了子進(jìn)程任務(wù)的配置,則需要重新加載運行。參考下面命令:
常用的supervisor命令有:
supervisorctl status //查看所有進(jìn)程的狀態(tài)
supervisorctl stop hexo-blog //停止hexo-blog
supervisorctl start hexo-blog //啟動hexo-blog
supervisorctl restart //重啟hexo-blog
supervisorctl update //配置文件修改后使用該命令加載新的配置
supervisorctl reload //重新啟動配置中的所有程序
四、結(jié)語
由于調(diào)研、搭建環(huán)境、編寫文章時間倉促和能力有限,文章難免存在用詞不當(dāng)或知識錯誤,歡迎指正。如果有更好的后臺程序運行或者守護(hù)進(jìn)程的管理的見解,歡迎評論區(qū)討論交流。