Node.js 進程

process 是全局對象,可以在任意位置訪問,是 EventEmitter 的實例。javascript

退出狀態碼

當沒有新的異步的操做等待處理時,Node 正常狀況下退出時會返回狀態碼 0 。下面的狀態碼錶示其餘狀態:css

  • 1 未捕獲的致命異常-Uncaught Fatal Exception - 有未捕獲異常,而且沒有被域或 uncaughtException 處理函數處理。
  • 2 - Unused (保留)
  • 3 JavaScript解析錯誤-Internal JavaScript Parse Error - JavaScript的源碼啓動 Node 進程時引發解析錯誤。很是罕見,僅會在開發 Node 時纔會有。
  • 4 JavaScript評估失敗-Internal JavaScript Evaluation Failure - JavaScript的源碼啓動 Node 進程,評估時返回函數失敗。很是罕見,僅會在開發 Node 時纔會有。
  • 5 致命錯誤-Fatal Error - V8 裏致命的不可恢復的錯誤。一般會打印到 stderr ,內容爲: FATAL ERROR
  • 6 Non-function 異常處理-Non-function Internal Exception Handler - 未捕獲異常,內部異常處理函數不知爲什麼設置爲on-function,而且不能被調用。
  • 7 異常處理函數運行時失敗-Internal Exception Handler Run-Time Failure - 未捕獲的異常, 而且異常處理函數處理時本身拋出了異常。例如,若是 process.on('uncaughtException')domain.on('error') 拋出了異常。
  • 8 - Unused保留. 以前版本的 Node, 8 有時表示未捕獲異常。
  • 9 - 參數非法-Invalid Argument - 多是給了未知的參數,或者給的參數沒有值。
  • 10 運行時失敗-Internal JavaScript Run-Time Failure - JavaScript的源碼啓動 Node 進程時拋出錯誤,很是罕見,僅會在開發 Node 時纔會有。
  • 12 無效的 Debug 參數-Invalid Debug Argument - 設置了參數--debug 和/或 --debug-brk,可是選擇了錯誤端口。
  • >128 信號退出-Signal Exits - 若是 Node 接收到致命信號,好比SIGKILLSIGHUP,那麼退出代碼就是128 加信號代碼。這是標準的 Unix 作法,退出信號代碼放在高位。

事件: 'exit'

當進程準備退出時觸發。此時已經沒有辦法阻止從事件循環中推出。所以,你必須在處理函數中執行同步操做。這是一個在固定事件檢查模塊狀態(好比單元測試)的好時機。回調函數有一個參數,它是進程的退出代碼。html

監聽 exit 事件的例子:java

process.on('exit', function(code) { // do *NOT* do this setTimeout(function() { console.log('This will not run'); }, 0); console.log('About to exit with code:', code); });

事件: 'beforeExit'

當 node 清空事件循環,而且沒有其餘安排時觸發這個事件。一般來講,當沒有進程安排時 node 退出,可是 'beforeExit' 的監聽器能夠異步調用,這樣 node 就會繼續執行。node

'beforeExit' 並非明確退出的條件,process.exit() 或異常捕獲纔是,因此不要把它當作'exit' 事件。除非你想安排更多的工做。linux

事件: 'uncaughtException'

當一個異常冒泡回到事件循環,觸發這個事件。若是給異常添加了監視器,默認的操做(打印堆棧跟蹤信息並退出)就不會發生。npm

監聽 uncaughtException 的例子:json

process.on('uncaughtException', function(err) { console.log('Caught exception: ' + err); }); setTimeout(function() { console.log('This will still run.'); }, 500); // Intentionally cause an exception, but don't catch it. nonexistentFunc(); console.log('This will not run.');

注意,uncaughtException 是很是簡略的異常處理機制。vim

儘可能不要使用它,而應該用 domains 。若是你用了,每次未處理異常後,重啓你的程序。數組

不要使用 node.js 裏諸如 On Error Resume Next 這樣操做。每一個未處理的異常意味着你的程序,和你的 node.js 擴展程序,一個未知狀態。盲目的恢復意味着 任何事情 均可能發生

你在升級的系統時拉掉了電源線,而後恢復了。可能10次裏有9次沒有問題,可是第10次,你的系統可能就會掛掉。

Signal 事件

當進程接收到信號時就觸發。信號列表詳見標準的 POSIX 信號名,如 SIGINT、SIGUSR1 等

監聽 SIGINT 的例子:

// Start reading from stdin so we don't exit. process.stdin.resume(); process.on('SIGINT', function() { console.log('Got SIGINT. Press Control-D to exit.'); });

在大多數終端程序裏,發送 SIGINT 信號的簡單方法是按下 信號Control-C

注意:

  • SIGUSR1 node.js 接收這個信號開啓調試模式。能夠安裝一個監聽器,但開始時不會中斷調試。
  • SIGTERMSIGINT 在非 Windows 系統裏,有默認的處理函數,退出(伴隨退出代碼 128 + 信號碼)前,重置退出模式。若是這些信號有監視器,默認的行爲將會被移除。
  • SIGPIPE 默認狀況下忽略,能夠加監聽器。
  • SIGHUP 當 Windowns 控制檯關閉的時候生成,其餘平臺的相似條件,參見signal(7)。能夠添加監聽者,Windows 平臺上 10 秒後會無條件退出。在非 Windows 平臺上,SIGHUP 的默認操做是終止 node,可是一旦添加了監聽器,默認動做將會被移除。 SIGHUP is to terminate node, but once a listener has been installed its
  • SIGTERM Windows 不支持, 能夠被監聽。
  • SIGINT 全部的終端都支持,一般由CTRL+C 生成(可能須要配置)。當終端原始模式啓用後不會再生成。
  • SIGBREAK Windows 裏,按下 CTRL+BREAK 會發送。非 Windows 平臺,能夠被監聽,可是不能發送或生成。
  • SIGWINCH - 當控制檯被重設大小時發送。Windows 系統裏,僅會在控制檯上輸入內容時,光標移動,或者可讀的 tty在原始模式上使用。
  • SIGKILL 不能有監視器,在全部平臺上無條件關閉 node。
  • SIGSTOP 不能有監視器。

Windows 不支持發送信號,可是 node 提供了不少process.kill()child_process.kill() 的模擬:

  • 發送 Sending 信號 0 能夠查找運行中得進程
  • 發送 SIGINT, SIGTERM, 和 SIGKILL 會引發目標進程無條件退出。

process.stdout

一個 Writable Stream 執向 stdout (on fd 1).

例如: console.log的定義:

console.log = function(d) { process.stdout.write(d + '\n'); };

process.stderrprocess.stdout 和 node 裏的其餘流不一樣,他們不會被關閉(end() 將會被拋出),它們不會觸發 finish 事件,而且寫是阻塞的。

  • 引用指向常規文件或 TTY 文件描述符時,是阻塞的。
  • 引用指向 pipe 管道時:
    • 在 Linux/Unix 裏阻塞.
    • 在 Windows 像其餘流同樣,不被阻塞

檢查 Node 是否運行在 TTY 上下文中,從process.stderr, process.stdout, 或 process.stdin裏讀取 isTTY 屬性。

$ node -p "Boolean(process.stdin.isTTY)" true $ echo "foo" | node -p "Boolean(process.stdin.isTTY)" false $ node -p "Boolean(process.stdout.isTTY)" true $ node -p "Boolean(process.stdout.isTTY)" | cat false

更多信息參見 the tty docs

process.stderr

一個指向 stderr (on fd 2)的可寫流。

process.stderrprocess.stdout 和 node 裏的其餘流不一樣,他們不會被關閉(end() 將會被拋出),它們不會觸發 finish 事件,而且寫是阻塞的。

  • 引用指向常規文件或 TTY 文件描述符時,是阻塞的。
  • 引用指向 pipe 管道時:
    • 在 Linux/Unix 裏阻塞.
    • 在 Windows 像其餘流同樣,不被阻塞

process.stdin

一個指向 stdin (on fd 0)的可讀流。

如下例子:打開標準輸入流,並監聽兩個事件:

process.stdin.setEncoding('utf8'); process.stdin.on('readable', function() { var chunk = process.stdin.read(); if (chunk !== null) { process.stdout.write('data: ' + chunk); } }); process.stdin.on('end', function() { process.stdout.write('end'); });

process.stdin 能夠工做在老模式裏,和 v0.10 以前版本的 node 代碼兼容。

更多信息參見Stream compatibility.

在老的流模式裏,stdin流默認暫停,必須調用 process.stdin.resume() 讀取。能夠調用 process.stdin.resume() 切換到老的模式。

若是開始一個新的工程,最好選擇新的流,而不是用老的流。

process.argv

包含命令行參數的數組。第一個元素是'node',第二個參數是 JavaScript 文件的名字,第三個參數是任意的命令行參數。

// print process.argv process.argv.forEach(function(val, index, array) { console.log(index + ': ' + val); });

將會生成:

$ node process-2.js one two=three four 0: node 1: /Users/mjr/work/node/process-2.js 2: one 3: two=three 4: four

process.execPath

開啓當前進程的執行文件的絕對路徑。

例子:

/usr/local/bin/node

process.execArgv

啓動進程所需的 node 命令行參數。這些參數不會在 process.argv 裏出現,而且不包含 node 執行文件的名字,或者任何在名字以後的參數。這些用來生成子進程,使之擁有和父進程有相同的參數。

例子:

$ node --harmony script.js --version

process.execArgv 的參數:

['--harmony']

process.argv 的參數:

['/usr/local/bin/node', 'script.js', '--version']

process.abort()

這將致使 node 觸發 abort 事件。會讓 node 退出並生成一個核心文件。

process.chdir(directory)

改變當前工做進程的目錄,若是操做失敗拋出異常。

console.log('Starting directory: ' + process.cwd()); try { process.chdir('/tmp'); console.log('New directory: ' + process.cwd()); } catch (err) { console.log('chdir: ' + err); }

process.cwd()

返回當前進程的工做目錄

console.log('Current directory: ' + process.cwd());

process.env

包含用戶環境的對象,參見 environ(7).

這個對象的例子:

{ TERM: 'xterm-256color', SHELL: '/usr/local/bin/bash', USER: 'maciej', PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin', PWD: '/Users/maciej', EDITOR: 'vim', SHLVL: '1', HOME: '/Users/maciej', LOGNAME: 'maciej', _: '/usr/local/bin/node' }

你能夠寫入這個對象,可是不會改變當前運行的進程。如下的命令不會成功:

node -e 'process.env.foo = "bar"' && echo $foo

這個會成功:

process.env.foo = 'bar'; console.log(process.env.foo);

process.exit([code])

使用指定的 code 結束進程。若是忽略,將會使用 code 0

使用失敗的代碼退出:

process.exit(1);

Shell 將會看到退出代碼爲1.

process.exitCode

進程退出時的代碼,若是進程優雅的退出,或者經過 process.exit() 退出,不須要指定退出碼。

設定 process.exit(code) 將會重寫以前設置的 process.exitCode

process.getgid()

注意:這個函數僅在 POSIX 平臺上可用(例如,非Windows 和 Android)。

獲取進程的羣組標識(參見 getgid(2))。獲取到得時羣組的數字 id,而不是名字。

if (process.getgid) { console.log('Current gid: ' + process.getgid()); }

process.setgid(id)

注意:這個函數僅在 POSIX 平臺上可用(例如,非Windows 和 Android)。

設置進程的羣組標識(參見 setgid(2))。能夠接收數字 ID 或者羣組名。若是指定了羣組名,會阻塞等待解析爲數字 ID 。

if (process.getgid && process.setgid) { console.log('Current gid: ' + process.getgid()); try { process.setgid(501); console.log('New gid: ' + process.getgid()); } catch (err) { console.log('Failed to set gid: ' + err); } }

process.getuid()

注意:這個函數僅在 POSIX 平臺上可用(例如,非Windows 和 Android)。

獲取進程的用戶標識(參見 getuid(2))。這是數字的用戶 id,不是用戶名

if (process.getuid) { console.log('Current uid: ' + process.getuid()); }

process.setuid(id)

注意:這個函數僅在 POSIX 平臺上可用(例如,非Windows 和 Android)。

設置進程的用戶標識(參見setuid(2))。接收數字 ID或字符串名字。果指定了羣組名,會阻塞等待解析爲數字 ID 。

if (process.getuid && process.setuid) { console.log('Current uid: ' + process.getuid()); try { process.setuid(501); console.log('New uid: ' + process.getuid()); } catch (err) { console.log('Failed to set uid: ' + err); } }

process.getgroups()

注意:這個函數僅在 POSIX 平臺上可用(例如,非Windows 和 Android)。

返回進程的羣組 iD 數組。POSIX 系統沒有保證必定有,可是 node.js 保證有。

process.setgroups(groups)

注意:這個函數僅在 POSIX 平臺上可用(例如,非Windows 和 Android)。

設置進程的羣組 ID。這是受權操做,全部你須要有 root 權限,或者有 CAP_SETGID 能力。

列表能夠包含羣組 IDs,羣組名,或者二者都有。

process.initgroups(user, extra_group)

注意:這個函數僅在 POSIX 平臺上可用(例如,非Windows 和 Android)。

讀取 /etc/group ,並初始化羣組訪問列表,使用成員所在的全部羣組。這是受權操做,全部你須要有 root 權限,或者有 CAP_SETGID 能力。

user 是用戶名或者用戶 ID, extra_group 是羣組名或羣組 ID。

當你在註銷權限 (dropping privileges) 的時候須要注意. 例子:

console.log(process.getgroups()); // [ 0 ] process.initgroups('bnoordhuis', 1000); // switch user console.log(process.getgroups()); // [ 27, 30, 46, 1000, 0 ] process.setgid(1000); // drop root gid console.log(process.getgroups()); // [ 27, 30, 46, 1000 ]

process.version

一個編譯屬性,包含 NODE_VERSION.

console.log('Version: ' + process.version);

process.versions

一個屬性,包含了 node 的版本和依賴.

console.log(process.versions);

打印出來:

{ http_parser: '1.0', node: '0.10.4', v8: '3.14.5.8', ares: '1.9.0-DEV', uv: '0.10.3', zlib: '1.2.3', modules: '11', openssl: '1.0.1e' }

process.config

一個包含用來編譯當前 node 執行文件的 javascript 配置選項的對象。它與運行 ./configure 腳本生成的 "config.gypi" 文件相同。

一個可能的輸出:

{ target_defaults: { cflags: [], default_configuration: 'Release', defines: [], include_dirs: [], libraries: [] }, variables: { host_arch: 'x64', node_install_npm: 'true', node_prefix: '', node_shared_cares: 'false', node_shared_http_parser: 'false', node_shared_libuv: 'false', node_shared_v8: 'false', node_shared_zlib: 'false', node_use_dtrace: 'false', node_use_openssl: 'true', node_shared_openssl: 'false', strict_aliasing: 'true', target_arch: 'x64', v8_use_snapshot: 'true' } }

process.kill(pid[, signal])

發送信號給進程. pid 是進程id,而且 signal 是發送的信號的字符串描述。信號名是字符串,好比'SIGINT' 或 'SIGHUP'。若是忽略,信號會是 'SIGTERM'.更多信息參見 Signal 事件 和 kill(2) .

若是進程沒有退出,會拋出錯誤。信號 0 能夠用來測試進程是否存在。

注意,雖然這個這個函數名叫process.kill,它真的僅是信號發射器,就像kill 系統調用。信號發射能夠作其餘事情,不只是殺死目標進程。

例子, 給本身發信號:

process.on('SIGHUP', function() { console.log('Got SIGHUP signal.'); }); setTimeout(function() { console.log('Exiting.'); process.exit(0); }, 100); process.kill(process.pid, 'SIGHUP');

注意: 當 Node.js 接收到 SIGUSR1 信號,它會開啓 debugger 調試模式, 參見Signal Events.

process.pid

當前進程的 PID

console.log('This process is pid ' + process.pid);

process.title

獲取/設置(Getter/setter) 'ps' 中顯示的進程名。

使用 setter 時,字符串的長度由系統指定,可能會很短。

在 Linux 和 OS X 上,它受限於名稱的長度加上命令行參數的長度,由於它會覆蓋參數內存(argv memory)。

v0.8 版本容許更長的進程標題字符串,也支持覆蓋環境內存,可是存在潛在的不安全和混亂(很難說清楚)。

process.arch

當前 CPU 的架構:'arm'、'ia32' 或者 'x64'.

console.log('This processor architecture is ' + process.arch);

process.platform

運行程序所在的平臺系統 'darwin', 'freebsd', 'linux', 'sunos' or 'win32'

console.log('This platform is ' + process.platform);

process.memoryUsage()

返回一個對象,描述了 Node 進程所用的內存情況,單位爲字節。

var util = require('util'); console.log(util.inspect(process.memoryUsage()));

將會生成:

{ rss: 4935680, heapTotal: 1826816, heapUsed: 650472 }

heapTotal and heapUsed refer to V8's memory usage.

process.nextTick(callback)

  • callback {Function}

一旦當前事件循環結束,調用回到函數。

這不是 setTimeout(fn, 0) 的簡單別名,這個效率更高。在任何附加 I/O 事件在子隊列事件循環中觸發前,它就會運行。

console.log('start'); process.nextTick(function() { console.log('nextTick callback'); }); console.log('scheduled'); // Output: // start // scheduled // nextTick callback

在對象構造後,在 I/O 事件發生前,你又想改變附加事件處理函數時,這個很是有用。

function MyThing(options) { this.setupOptions(options); process.nextTick(function() { this.startDoingStuff(); }.bind(this)); } var thing = new MyThing(); thing.getReadyForStuff(); // thing.startDoingStuff() gets called now, not before.

要保證你的函數必定是 100% 同步執行,或者 100% 異步執行。例子:

// WARNING! DO NOT USE! BAD UNSAFE HAZARD! function maybeSync(arg, cb) { if (arg) { cb(); return; } fs.stat('file', cb); }

這個 API 很是危險. 若是你這麼作:

maybeSync(true, function() { foo(); }); bar();

不清楚foo()bar() 哪一個先執行。

更好的方法:

function definitelyAsync(arg, cb) { if (arg) { process.nextTick(cb); return; } fs.stat('file', cb); }

注意:nextTick 隊列會在徹底執行完畢以後才調用 I/O 操做。所以,遞歸設置 nextTick 的回調就像一個 while(true); 循環同樣,將會阻止任何 I/O 操做的發生。

process.umask([mask])

設置或讀取進程文件的掩碼。子進程從父進程繼承掩碼。若是mask 參數有效,返回舊的掩碼。不然,返回當前掩碼。

var oldmask, newmask = 0022; oldmask = process.umask(newmask); console.log('Changed umask from: ' + oldmask.toString(8) + ' to ' + newmask.toString(8));

process.uptime()

返回 Node 已經運行的秒數。

process.hrtime()

返回當前進程的高分辨時間,形式爲 [seconds, nanoseconds]數組。它是相對於過去的任意事件。該值與日期無關,所以不受時鐘漂移的影響。主要用途是能夠經過精確的時間間隔,來衡量程序的性能。

你能夠將以前的結果傳遞給當前的 process.hrtime() ,會返回二者間的時間差,用來基準和測量時間間隔。

var time = process.hrtime(); // [ 1800216, 25 ] setTimeout(function() { var diff = process.hrtime(time); // [ 1, 552 ] console.log('benchmark took %d nanoseconds', diff[0] * 1e9 + diff[1]); // benchmark took 1000000527 nanoseconds }, 1000);

process.mainModule

require.main 的備選方法。不一樣點,若是主模塊在運行時改變,require.main可能會繼續返回老的模塊。能夠認爲,這二者引用了同一個模塊。

Alternate way to retrieverequire.main.The difference is that if the main module changes at runtime, require.mainmight still refer to the original main module in modules that were requiredbefore the change occurred. Generally it's safe to assume that the two referto the same module.

require.main 同樣, 若是沒有入口腳本,將會返回undefined

相關文章
相關標籤/搜索