從零開始nodejs系列文章,將介紹如何利Javascript作爲服務端腳本,經過Nodejs框架web開發。Nodejs框架是基於V8的引擎,是目前速度最快的Javascript引擎。chrome瀏覽器就基於V8,同時打開20-30個網頁都很流暢。Nodejs標準的web開發框架Express,能夠幫助咱們迅速創建web站點,比起PHP的開發效率更高,並且學習曲線更低。很是適合小型網站,個性化網站,咱們本身的Geek網站!!javascript
關於做者html
轉載請註明出處:
http://blog.fens.me/nodejs-server-forever/java
目前node
又說到服務器管理了,上次說的時候用的是Linux系統服務upstart, 今天準備嘗試一下Nodejs本身模塊化解決方案forever。linux
服務器管理是系統上線後,必需要面對的問題。最好有一個軟件能夠提供整套的服務器運行解決方案:要求運行穩定,支持高併發,啓動/中止命令簡單,支持熱部署,宕機重啓,監控界面和日誌,集羣環境。程序員
接下來,就讓咱們看看forever能不能實現目標。web
前言chrome
forever是一個簡單的命令式nodejs的守護進程,可以啓動,中止,重啓App應用。forever徹底基於命令行操做,在forever進程之下,建立node的子進程,經過monitor監控node子進程的運行狀況,一旦文件更新,或者進程掛掉,forever會自動重啓node服務器,確保應用正常運行。express
全局安裝forevernpm
~ D:\workspace\javascript>npm install -g forever D:\toolkit\nodejs\forever -> D:\toolkit\nodejs\node_modules\forever\bin\forever D:\toolkit\nodejs\foreverd -> D:\toolkit\nodejs\node_modules\forever\bin\foreverd
查看forever幫助
~ D:\workspace\javascript>forever -h help: usage: forever [action] [options] SCRIPT [script-options] help: help: Monitors the script specified in the current process or as a daemon help: help: actions: help: start Start SCRIPT as a daemon help: stop Stop the daemon SCRIPT help: stopall Stop all running forever scripts help: restart Restart the daemon SCRIPT help: restartall Restart all running forever scripts help: list List all running forever scripts help: config Lists all forever user configuration help: set <key> <val> Sets the specified forever config <key> help: clear <key> Clears the specified forever config <key> help: logs Lists log files for all forever processes help: logs <script|index> Tails the logs for <script|index> help: columns add <col> Adds the specified column to the output in `forever list` help: columns rm <col> Removed the specified column from the output in `forever list` help: columns set <cols> Set all columns for the output in `forever list` help: cleanlogs [CAREFUL] Deletes all historical forever log files help: help: options: help: -m MAX Only run the specified script MAX times help: -l LOGFILE Logs the forever output to LOGFILE help: -o OUTFILE Logs stdout from child script to OUTFILE help: -e ERRFILE Logs stderr from child script to ERRFILE help: -p PATH Base path for all forever related files (pid files, etc.) help: -c COMMAND COMMAND to execute (defaults to node) help: -a, --append Append logs help: -f, --fifo Stream logs to stdout help: -n, --number Number of log lines to print help: --pidFile The pid file help: --sourceDir The source directory for which SCRIPT is relative to help: --minUptime Minimum uptime (millis) for a script to not be considered "spinning" help: --spinSleepTime Time to wait (millis) between launches of a spinning script. help: --colors --no-colors will disable output coloring help: --plain alias of --no-colors help: -d, --debug Forces forever to log debug output help: -v, --verbose Turns on the verbose messages from Forever help: -s, --silent Run the child script silencing stdout and stderr help: -w, --watch Watch for file changes help: --watchDirectory Top-level directory to watch from help: --watchIgnore To ignore pattern when watch is enabled (multiple option is allowed) help: -h, --help You're staring at it help: help: [Long Running Process] help: The forever process will continue to run outputting log messages to the console. help: ex. forever -o out.log -e err.log my-script.js help: help: [Daemon] help: The forever process will run as a daemon which will make the target process start help: in the background. This is extremely useful for remote starting simple node.js scripts help: without using nohup. It is recommended to run start with -o -l, & -e. help: ex. forever start -l forever.log -o out.log -e err.log my-daemon.js help: forever stop my-daemon.js help:
經過「Commander寫本身的Nodejs命令」一文的介紹,咱們已經知道如何看懂,並實現自定義的命令行了。雖然,forever不是基於Commander的,而是基於另外一個命令行開發包optimist,原理都是相似的。
因此,咱們看到forever支持的命令和配置項確實很多,應該是偏命令行的管理工具。
子命令actions:
配置參數options:
建立一個web項目(express3+ejs),使用forever管理服務器。
安裝express3
~ D:\workspace\javascript>express -e nodejs-forever ~ D:\workspace\javascript>cd nodejs-forever && npm install
經過forever啓動應用
~ D:\workspace\javascript\nodejs-forever>forever start app.js warn: --minUptime not set. Defaulting to: 1000ms warn: --spinSleepTime not set. Your script will exit if it does not stay up for at least 1000ms info: Forever processing file: app.js
打開瀏覽器: http://localhost:3000,能夠看到web界面
在win下面查看forever狀態
~ D:\workspace\javascript\nodejs-forever>forever list info: No forever processes running ~ D:\workspace\javascript\nodejs-forever>forever stop app.js error: Forever cannot find process with index: app.js
咱們發現forever的程序,工做不對了!!程序明明是運行狀態,經過list確看不到。接下來,切換成Linux Ubuntu繼續測試。
Linux的系統環境
初始化項目:安裝命令不解釋了
~ cd /home/conan/nodejs ~ express -e nodejs-forever ~ cd nodejs-forever && npm install ~ sudo npm install forever -g
啓動forever
~ forever start app.js warn: --minUptime not set. Defaulting to: 1000ms warn: --spinSleepTime not set. Your script will exit if it does not stay up for at least 1000ms info: Forever processing file: app.js
查看node服務器狀態
~ forever list info: Forever processes running data: uid command script forever pid logfile uptime data: [0] L2tY /usr/local/bin/node app.js 18276 18279 /home/conan/.forever/L2tY.log 0:0:0:37.792 # 系統進程 ~ ps -aux|grep node Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html conan 18296 0.5 1.1 597696 23776 ? Ssl 15:48 0:00 /usr/local/bin/node /usr/local/lib/node_modules/forever/bin/monitor app.js conan 18299 0.4 0.8 630340 18392 ? Sl 15:48 0:00 /usr/local/bin/node /home/conan/nodejs/nodejs-forever/app.js # 端口占用 ~ netstat -nltp|grep node tcp 0 0 0.0.0.0:3000 0.0.0.0:* LISTEN 18299/node
中止服務器
~ forever stop app.js info: Forever stopped process: data: uid command script forever pid logfile uptime [0] L2tY /usr/local/bin/node app.js 18276 18279 /home/conan/.forever/L2tY.log 0:0:0:45.621
咱們看到在Linux Ubuntu環境中是正常的。
兩種測試方案:
1). 用Linux命令,直接殺死node進程
# 查看node進程,PID=18299 ~ ps -aux|grep node conan 18296 0.0 1.1 597696 23776 ? Ssl 15:48 0:00 /usr/local/bin/node /usr/local/lib/node_modules/forever/bin/monitor app.js conan 18299 0.0 0.8 630340 18392 ? Sl 15:48 0:00 /usr/local/bin/node /home/conan/nodejs/nodejs-forever/app.js conan 18315 0.0 0.0 13584 956 pts/5 R+ 15:52 0:00 grep --color=auto node # 殺死PID=19299 ~ kill -9 18299 # 再看node進程,node自動重啓,新的PID=18324 ~ ps -aux|grep node conan 18296 0.0 1.1 597696 23916 ? Ssl 15:48 0:00 /usr/local/bin/node /usr/local/lib/node_modules/forever/bin/monitor app.js conan 18316 2.6 0.8 630340 18412 ? Sl 15:52 0:00 /usr/local/bin/node /home/conan/nodejs/nodejs-forever/app.js conan 18324 0.0 0.0 13584 956 pts/5 R+ 15:52 0:00 grep --color=auto node
咱們看到看殺死node進程,forever會幫助咱們,重啓node。
殺死forever的monitor
~ kill -9 18296 ~ ps -aux|grep node conan 18316 0.0 0.9 630340 18644 ? Sl 15:52 0:00 /usr/local/bin/node /home/conan/nodejs/nodejs-forever/app.js conan 18333 0.0 0.0 13584 952 pts/5 S+ 15:57 0:00 grep --color=auto node # 再殺死node進程 ~ kill -9 18316 ~ ps -aux|grep node conan 18336 0.0 0.0 13584 956 pts/5 S+ 15:58 0:00 grep --color=auto node
咱們嘗試殺死了forever的monitor,monitor程序沒有自動重啓,而後再殺死node進程後,node也不會自動重啓了。
2). 在應用中,模擬異常退出
修改文件:app.js
~ vi app.js //.. http.createServer(app).listen(app.get('port'), function(){ console.log(new Date()); console.log('Express server listening on port ' + app.get('port')); }); setTimeout(function(){ console.log(new Date()); throw new Error('App is error from inner!'); },10*1000);
經過node命令啓動
~ node app.js Thu Sep 26 2013 16:08:44 GMT+0800 (CST) Express server listening on port 3000 Thu Sep 26 2013 16:08:54 GMT+0800 (CST) /home/conan/nodejs/nodejs-forever/app.js:41 throw new Error('App is error from inner!'); ^ Error: App is error from inner! at null._onTimeout (/home/conan/nodejs/nodejs-forever/app.js:41:9) at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
10秒後,因爲內部錯誤, node進程掛掉了。
經過forever命令啓動
~ mkdir logs ~ chmod 777 -R logs ~ forever -p . -l ./logs/access.log -e ./logs/error.log start app.js # 檢查錯誤日誌 ~ cat logs/access.log ls Thu Sep 26 2013 16:15:02 GMT+0800 (CST) Express server listening on port 3000 Thu Sep 26 2013 16:15:12 GMT+0800 (CST) /home/conan/nodejs/nodejs-forever/app.js:41 throw new Error('App is error from inner!'); ^ Error: App is error from inner! at null._onTimeout (/home/conan/nodejs/nodejs-forever/app.js:41:9) at Timer.listOnTimeout [as ontimeout] (timers.js:110:15) error: Forever detected script exited with code: 8 error: Forever restarting script for 1 time Thu Sep 26 2013 16:15:13 GMT+0800 (CST) Express server listening on port 3000 Thu Sep 26 2013 16:15:23 GMT+0800 (CST) /home/conan/nodejs/nodejs-forever/app.js:41 throw new Error('App is error from inner!'); ^ Error: App is error from inner! at null._onTimeout (/home/conan/nodejs/nodejs-forever/app.js:41:9) at Timer.listOnTimeout [as ontimeout] (timers.js:110:15) error: Forever detected script exited with code: 8 error: Forever restarting script for 2 time Thu Sep 26 2013 16:15:23 GMT+0800 (CST) Express server listening on port 3000 Thu Sep 26 2013 16:15:33 GMT+0800 (CST) /home/conan/nodejs/nodejs-forever/app.js:41 throw new Error('App is error from inner!'); ^ Error: App is error from inner! at null._onTimeout (/home/conan/nodejs/nodejs-forever/app.js:41:9) at Timer.listOnTimeout [as ontimeout] (timers.js:110:15) error: Forever detected script exited with code: 8 error: Forever restarting script for 3 time Thu Sep 26 2013 16:15:33 GMT+0800 (CST) Express server listening on port 3000 Thu Sep 26 2013 16:15:43 GMT+0800 (CST) /home/conan/nodejs/nodejs-forever/app.js:41 throw new Error('App is error from inner!'); ^ Error: App is error from inner! at null._onTimeout (/home/conan/nodejs/nodejs-forever/app.js:41:9) at Timer.listOnTimeout [as ontimeout] (timers.js:110:15) error: Forever detected script exited with code: 8 error: Forever restarting script for 4 time
咱們發現每10秒種,node內部掛掉,而後再被forever重啓!!
經過list咱們手動刷新幾回也能夠看到pid是變的。
~ forever list info: Forever processes running data: uid command script forever pid logfile uptime data: [0] SmtT /usr/local/bin/node app.js 18444 18579 logs/access.log 0:0:0:7.211 ~ forever list info: Forever processes running data: uid command script forever pid logfile uptime data: [0] SmtT /usr/local/bin/node app.js 18444 18579 logs/access.log 0:0:0:8.921 ~ forever list info: Forever processes running data: uid command script forever pid logfile uptime data: [0] SmtT /usr/local/bin/node app.js 18444 18604 logs/access.log 0:0:0:0.177 ~ forever list info: Forever processes running data: uid command script forever pid logfile uptime data: [0] SmtT /usr/local/bin/node app.js 18444 18604 logs/access.log 0:0:0:2.206
這樣forever就幫助咱們完成了,幾項比較重要服務器管理功能:「啓動/中止命令簡單」,「支持熱部署」,「宕機重啓」,「監控界面和日誌」。
比起upstart管理,省略了配置腳本的步驟(/etc/init/nodejs-xx.conf)。其餘的功能,還要更近一步的使用才知道。
開發環境
~ cd /home/conan/nodejs/nodejs-forever/ ~ forever -p . -l ./logs/access.log -e ./logs/error.log -a -w start app.js
生產環境
~ export LOG=/var/log/nodejs/project ~ export PID=/var/log/nodejs/project/forever.pid ~ export APP_PATH=/home/conan/nodejs/nodejs-forever ~ export APP=$APP_PATH/app.js ~ forever -p $APP_PATH -l $LOG/access.log -e $LOG/error.log -o $LOG/out.log -a --pidFile $PID start $APP