鍍金池/ 教程/ HTML/ 進程
模塊
斷言測試
Buffer
Smalloc
TTY
概述
REPL
HTTP
DNS
路徑
集群
TLS/SSL
系統(tǒng)
加密
調(diào)試器
進程
Punycode
虛擬機
HTTPS
網(wǎng)絡(luò)
Query String
C/C++ 插件
實用工具
文件系統(tǒng)
Zlib
子進程
UDP/Datagram Sockets
定時器
逐行讀取
字符串解碼器
全局對象
事件
URL
控制臺

進程

process 是全局對象,能夠在任意位置訪問,是 EventEmitter 的實例。

退出狀態(tài)碼

當沒有新的異步的操作等待處理時,Node 正常情況下退出時會返回狀態(tài)碼 0 。下面的狀態(tài)碼表示其他狀態(tài):

  • 1 未捕獲的致命異常-Uncaught Fatal Exception - 有未捕獲異常,并且沒有被域或 uncaughtException 處理函數(shù)處理。
  • 2 - Unused (保留)
  • 3 JavaScript解析錯誤-Internal JavaScript Parse Error - JavaScript的源碼啟動 Node 進程時引起解析錯誤。非常罕見,僅會在開發(fā) Node 時才會有。
  • 4 JavaScript評估失敗-Internal JavaScript Evaluation Failure - JavaScript的源碼啟動 Node 進程,評估時返回函數(shù)失敗。非常罕見,僅會在開發(fā) Node 時才會有。
  • 5 致命錯誤-Fatal Error - V8 里致命的不可恢復(fù)的錯誤。通常會打印到 stderr ,內(nèi)容為: FATAL ERROR
  • 6 Non-function 異常處理-Non-function Internal Exception Handler - 未捕獲異常,內(nèi)部異常處理函數(shù)不知為何設(shè)置為on-function,并且不能被調(diào)用。
  • 7 異常處理函數(shù)運行時失敗-Internal Exception Handler Run-Time Failure - 未捕獲的異常, 并且異常處理函數(shù)處理時自己拋出了異常。例如,如果 process.on('uncaughtException')domain.on('error') 拋出了異常。
  • 8 - Unused保留. 之前版本的 Node, 8 有時表示未捕獲異常。
  • 9 - 參數(shù)非法-Invalid Argument - 可能是給了未知的參數(shù),或者給的參數(shù)沒有值。
  • 10 運行時失敗-Internal JavaScript Run-Time Failure - JavaScript的源碼啟動 Node 進程時拋出錯誤,非常罕見,僅會在開發(fā) Node 時才會有。
  • 12 無效的 Debug 參數(shù)-Invalid Debug Argument - 設(shè)置了參數(shù)--debug 和/或 --debug-brk,但是選擇了錯誤端口。
  • >128 信號退出-Signal Exits - 如果 Node 接收到致命信號,比如SIGKILLSIGHUP,那么退出代碼就是128 加信號代碼。這是標準的 Unix 做法,退出信號代碼放在高位。

事件: 'exit'

當進程準備退出時觸發(fā)。此時已經(jīng)沒有辦法阻止從事件循環(huán)中推出。因此,你必須在處理函數(shù)中執(zhí)行同步操作。這是一個在固定事件檢查模塊狀態(tài)(比如單元測試)的好時機?;卣{(diào)函數(shù)有一個參數(shù),它是進程的退出代碼。

監(jiān)聽 exit 事件的例子:

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 清空事件循環(huán),并且沒有其他安排時觸發(fā)這個事件。通常來說,當沒有進程安排時 node 退出,但是 'beforeExit' 的監(jiān)聽器可以異步調(diào)用,這樣 node 就會繼續(xù)執(zhí)行。

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

事件: 'uncaughtException'

當一個異常冒泡回到事件循環(huán),觸發(fā)這個事件。如果給異常添加了監(jiān)視器,默認的操作(打印堆棧跟蹤信息并退出)就不會發(fā)生。

監(jiān)聽 uncaughtException 的例子:

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 是非常簡略的異常處理機制。

盡量不要使用它,而應(yīng)該用 domains 。如果你用了,每次未處理異常后,重啟你的程序。

不要使用 node.js 里諸如 On Error Resume Next 這樣操作。每個未處理的異常意味著你的程序,和你的 node.js 擴展程序,一個未知狀態(tài)。盲目的恢復(fù)意味著 任何事情 都可能發(fā)生

你在升級的系統(tǒng)時拉掉了電源線,然后恢復(fù)了??赡?0次里有9次沒有問題,但是第10次,你的系統(tǒng)可能就會掛掉。

Signal 事件

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

監(jiān)聽 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.');
});

在大多數(shù)終端程序里,發(fā)送 SIGINT 信號的簡單方法是按下 信號Control-C

注意:

  • SIGUSR1 node.js 接收這個信號開啟調(diào)試模式。可以安裝一個監(jiān)聽器,但開始時不會中斷調(diào)試。
  • SIGTERMSIGINT 在非 Windows 系統(tǒng)里,有默認的處理函數(shù),退出(伴隨退出代碼 128 + 信號碼)前,重置退出模式。如果這些信號有監(jiān)視器,默認的行為將會被移除。
  • SIGPIPE 默認情況下忽略,可以加監(jiān)聽器。
  • SIGHUP 當 Windowns 控制臺關(guān)閉的時候生成,其他平臺的類似條件,參見signal(7)??梢蕴砑颖O(jiān)聽者,Windows 平臺上 10 秒后會無條件退出。在非 Windows 平臺上,SIGHUP 的默認操作是終止 node,但是一旦添加了監(jiān)聽器,默認動作將會被移除。 SIGHUP is to terminate node, but once a listener has been installed its
  • SIGTERM Windows 不支持, 可以被監(jiān)聽。
  • SIGINT 所有的終端都支持,通常由CTRL+C 生成(可能需要配置)。當終端原始模式啟用后不會再生成。
  • SIGBREAK Windows 里,按下 CTRL+BREAK 會發(fā)送。非 Windows 平臺,可以被監(jiān)聽,但是不能發(fā)送或生成。
  • SIGWINCH - 當控制臺被重設(shè)大小時發(fā)送。Windows 系統(tǒng)里,僅會在控制臺上輸入內(nèi)容時,光標移動,或者可讀的 tty在原始模式上使用。
  • SIGKILL 不能有監(jiān)視器,在所有平臺上無條件關(guān)閉 node。
  • SIGSTOP 不能有監(jiān)視器。

Windows 不支持發(fā)送信號,但是 node 提供了很多process.kill()child_process.kill() 的模擬:

  • 發(fā)送 Sending 信號 0 可以查找運行中得進程
  • 發(fā)送 SIGINT, SIGTERM, 和 SIGKILL 會引起目標進程無條件退出。

process.stdout

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

例如: console.log的定義:

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

process.stderrprocess.stdout 和 node 里的其他流不同,他們不會被關(guān)閉(end() 將會被拋出),它們不會觸發(fā) finish 事件,并且寫是阻塞的。

  • 引用指向常規(guī)文件或 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 里的其他流不同,他們不會被關(guān)閉(end() 將會被拋出),它們不會觸發(fā) finish 事件,并且寫是阻塞的。

  • 引用指向常規(guī)文件或 TTY 文件描述符時,是阻塞的。
  • 引用指向 pipe 管道時:
    • 在 Linux/Unix 里阻塞.
    • 在 Windows 像其他流一樣,不被阻塞

process.stdin

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

以下例子:打開標準輸入流,并監(jiān)聽兩個事件:

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流默認暫停,必須調(diào)用 process.stdin.resume() 讀取??梢哉{(diào)用 process.stdin.resume() 切換到老的模式。

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

process.argv

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

// 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

開啟當前進程的執(zhí)行文件的絕對路徑。

例子:

/usr/local/bin/node

process.execArgv

啟動進程所需的 node 命令行參數(shù)。這些參數(shù)不會在 process.argv 里出現(xiàn),并且不包含 node 執(zhí)行文件的名字,或者任何在名字之后的參數(shù)。這些用來生成子進程,使之擁有和父進程有相同的參數(shù)。

例子:

$ node --harmony script.js --version

process.execArgv 的參數(shù):

['--harmony']

process.argv 的參數(shù):

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

process.abort()

這將導(dǎo)致 node 觸發(fā) 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

包含用戶環(huán)境的對象,參見 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 結(jié)束進程。如果忽略,將會使用 code 0

使用失敗的代碼退出:

process.exit(1);

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

process.exitCode

進程退出時的代碼,如果進程優(yōu)雅的退出,或者通過 process.exit() 退出,不需要指定退出碼。

設(shè)定 process.exit(code) 將會重寫之前設(shè)置的 process.exitCode。

process.getgid()

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

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

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

process.setgid(id)

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

設(shè)置進程的群組標識(參見 setgid(2))。可以接收數(shù)字 ID 或者群組名。如果指定了群組名,會阻塞等待解析為數(shù)字 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()

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

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

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

process.setuid(id)

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

設(shè)置進程的用戶標識(參見setuid(2))。接收數(shù)字 ID或字符串名字。果指定了群組名,會阻塞等待解析為數(shù)字 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()

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

返回進程的群組 iD 數(shù)組。POSIX 系統(tǒng)沒有保證一定有,但是 node.js 保證有。

process.setgroups(groups)

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

設(shè)置進程的群組 ID。這是授權(quán)操作,所有你需要有 root 權(quán)限,或者有 CAP_SETGID 能力。

列表可以包含群組 IDs,群組名,或者兩者都有。

process.initgroups(user, extra_group)

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

讀取 /etc/group ,并初始化群組訪問列表,使用成員所在的所有群組。這是授權(quán)操作,所有你需要有 root 權(quán)限,或者有 CAP_SETGID 能力。

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

當你在注銷權(quán)限 (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 執(zhí)行文件的 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])

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

如果進程沒有退出,會拋出錯誤。信號 0 可以用來測試進程是否存在。

注意,雖然這個這個函數(shù)名叫process.kill,它真的僅是信號發(fā)射器,就像kill 系統(tǒng)調(diào)用。信號發(fā)射可以做其他事情,不僅是殺死目標進程。

例子, 給自己發(fā)信號:

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 調(diào)試模式, 參見 Signal Events.

process.pid

當前進程的 PID

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

process.title

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

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

在 Linux 和 OS X 上,它受限于名稱的長度加上命令行參數(shù)的長度,因為它會覆蓋參數(shù)內(nèi)存(argv memory)。

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

process.arch

當前 CPU 的架構(gòu):'arm'、'ia32' 或者 'x64'.

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

process.platform

運行程序所在的平臺系統(tǒng) 'darwin', 'freebsd', 'linux', 'sunos' or 'win32'

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

process.memoryUsage()

返回一個對象,描述了 Node 進程所用的內(nèi)存狀況,單位為字節(jié)。

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}

一旦當前事件循環(huán)結(jié)束,調(diào)用回到函數(shù)。

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

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

在對象構(gòu)造后,在 I/O 事件發(fā)生前,你又想改變附加事件處理函數(shù)時,這個非常有用。

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.

要保證你的函數(shù)一定是 100% 同步執(zhí)行,或者 100% 異步執(zhí)行。例子:

// 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() 哪個先執(zhí)行。

更好的方法:

function definitelyAsync(arg, cb) {
  if (arg) {
    process.nextTick(cb);
    return;
  }

  fs.stat('file', cb);
}

注意:nextTick 隊列會在完全執(zhí)行完畢之后才調(diào)用 I/O 操作。因此,遞歸設(shè)置 nextTick 的回調(diào)就像一個 while(true); 循環(huán)一樣,將會阻止任何 I/O 操作的發(fā)生。

process.umask([mask])

設(shè)置或讀取進程文件的掩碼。子進程從父進程繼承掩碼。如果mask 參數(shù)有效,返回舊的掩碼。否則,返回當前掩碼。

var oldmask, newmask = 0022;

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

process.uptime()

返回 Node 已經(jīng)運行的秒數(shù)。

process.hrtime()

返回當前進程的高分辨時間,形式為 [seconds, nanoseconds]數(shù)組。它是相對于過去的任意事件。該值與日期無關(guān),因此不受時鐘漂移的影響。主要用途是可以通過精確的時間間隔,來衡量程序的性能。

你可以將之前的結(jié)果傳遞給當前的 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可能會繼續(xù)返回老的模塊??梢哉J為,這兩者引用了同一個模塊。

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

require.main 一樣, 如果沒有入口腳本,將會返回undefined 。

上一篇:加密下一篇:控制臺