nodejs 的調(diào)試 debug


簡(jiǎn)介
對(duì)于開(kāi)發(fā)者來(lái)說(shuō),在開(kāi)發(fā)應(yīng)用程序的過(guò)程中,往往為了開(kāi)發(fā)方便和解決 bug 需要借助于編程語(yǔ)言的調(diào)試功能。一般來(lái)說(shuō)我們需要借助于強(qiáng)大 IDE 的調(diào)試功能來(lái)完成這項(xiàng)工作。nodejs 也不例外。
今天我們來(lái)詳細(xì)介紹一下如何調(diào)試 nodejs 程序。
開(kāi)啟 nodejs 的調(diào)試
還記得之前我們講到的 koa 程序嗎?本文將會(huì)以一個(gè)簡(jiǎn)單的 koa 服務(wù)端程序?yàn)槔瑏?lái)展開(kāi) nodejs 的調(diào)試。
先看下一個(gè)簡(jiǎn)單的 koa 服務(wù) app.js:
上面的程序開(kāi)啟了 3000 端口,建立了一個(gè) http 服務(wù)。每次請(qǐng)求的時(shí)候,都會(huì)返回 hello World,非常的簡(jiǎn)單。
要想運(yùn)行上面的程序,我們需要執(zhí)行 node app.js。 這會(huì)執(zhí)行 app.js 但是并不會(huì)開(kāi)啟調(diào)試功能。
怎么進(jìn)行調(diào)試呢?
我們需要加上 –inspect 參數(shù):
上面的代碼將會(huì)開(kāi)啟 nodejs 的調(diào)試功能。
我們看下輸出結(jié)果:
結(jié)果告訴了我們兩件事情,第一件事情就是 debugger 監(jiān)聽(tīng)的端口。默認(rèn)情況下將會(huì)開(kāi)啟 127.0.0.1 的 9229 端口。并且分配了一個(gè)唯一的 UUID 以供區(qū)分。
第二件事情就是告訴我們 nodejs 使用的調(diào)試器是 Inspector。
Inspector 是 nodejs 8 之后引入的,如果是在 nodejs 7 之前,那么使用的是 legacy debugger。
調(diào)試的安全性
如果 debugger 連接到了 nodejs 運(yùn)行環(huán)境中,如果有惡意攻擊者的話,這個(gè)惡意攻擊者可以在 nodejs 環(huán)境中運(yùn)行任意代碼。這會(huì)給我們的程序帶來(lái)很大的安全隱患。
所以我們一定要注意調(diào)試的安全性。一般來(lái)說(shuō),我們不建議進(jìn)行遠(yuǎn)程調(diào)試。
默認(rèn)情況下 –inspect 綁定的是 127.0.0.1,這樣就只允許本地程序訪問(wèn)。并且任何本地運(yùn)行的程序都有權(quán)限進(jìn)行該程序的調(diào)試。
如果我們真的想將 debug 程序暴露給外部程序的話,那么可以指明本機(jī)的外網(wǎng) IP 地址或者 0.0.0.0(表示任何地址,無(wú)限制),這樣遠(yuǎn)程機(jī)子就可以進(jìn)行遠(yuǎn)程調(diào)試了。
如果我們想進(jìn)行安全的 remote debug 該怎么處理呢?
首先,我們要開(kāi)啟本地的 debug:
然后我們可以搭建一個(gè) ssh 隧道,將本地的 9221 端口映射到遠(yuǎn)程服務(wù)器的 9229 端口:
這樣我們就可以通過(guò)連接本地的 9221 端口,進(jìn)行遠(yuǎn)程調(diào)試了。
使用 WebStorm 進(jìn)行 nodejs 調(diào)試
JetBrains 出品的 WebStorm 可謂是開(kāi)發(fā) nodejs 的利器,WebStorm 自帶有 debug 選項(xiàng),如果開(kāi)啟該選項(xiàng),則會(huì)在后臺(tái)開(kāi)啟 –inspect:

使用 WebStorm 來(lái)進(jìn)行調(diào)試和使用 IDEA 來(lái)進(jìn)行 java 程序調(diào)試類似,這里就不多介紹了。
使用 Chrome devTools 進(jìn)行調(diào)試
使用 Chrome devTools 進(jìn)行調(diào)試的前提是我們已經(jīng)開(kāi)啟了 –inspect 模式。
在 chrome 中輸入 chrome://inspect:

我們可看到 chrome inspect 的界面,如果你本地已經(jīng)有開(kāi)啟 inspect 的 nodejs 程序的話,在 Remote Target 中就可以直接看到。
選中你要調(diào)試的 target,點(diǎn)擊 inspect,即可開(kāi)啟 Chrome devTools 調(diào)試工具:

你可以對(duì)程序進(jìn)行 profile,也可以進(jìn)行調(diào)試。
這里我們關(guān)注的是調(diào)試,所以轉(zhuǎn)到 source 一欄,添加你要調(diào)試的程序的源代碼:

加入斷點(diǎn)即可開(kāi)始調(diào)試了。和在 chrome 中調(diào)試 web 端的 js 是一樣的。
使用 node-inspect 來(lái)進(jìn)行調(diào)試
其實(shí) nodejs 有一個(gè)自帶的調(diào)試工具,叫做 node-inspect,這是一個(gè) cli 的調(diào)試工具。我們看一下怎么使用。
我們直接使用:
node inspect 做了兩件事情,第一件事情就是生成子程序去運(yùn)行 node –inspect app.js,第二件事情就是在主程序中運(yùn)行 CLI 調(diào)試窗口。
這個(gè) CLI 調(diào)試程序?yàn)槲覀兲峁┝艘恍┓浅S杏玫拿睿?/p>
Stepping
cont, c: 繼續(xù)執(zhí)行
next, n: Step 到下一步
step, s: Step in
out, o: Step out
pause: 暫停運(yùn)行的代碼
Breakpoints
setBreakpoint(), sb(): 在當(dāng)前行設(shè)置斷點(diǎn)
setBreakpoint(line), sb(line): 在指定的行設(shè)置斷點(diǎn)
setBreakpoint(‘fn()’), sb(…): 在指定的 function 中設(shè)置斷點(diǎn)
setBreakpoint(‘script.js’, 1), sb(…): 在指定的腳本文件中設(shè)置斷點(diǎn)
clearBreakpoint(‘script.js’, 1), cb(…): 從文件中清除斷點(diǎn)
Information
backtrace, bt: 打印當(dāng)前 execution frame 的 backtrace 信息
list(5): 列出源代碼前后的 5 行
watch(expr): 添加監(jiān)聽(tīng)表達(dá)式
unwatch(expr): 刪除監(jiān)聽(tīng)表達(dá)式
watchers: 列出所有的 watchers
repl: 打開(kāi) repl 表達(dá)式
exec expr: 執(zhí)行表達(dá)式
通過(guò)上面的命令,我們可以在 CLI 中進(jìn)行比較復(fù)雜的調(diào)試活動(dòng)。
其他的 debug 客戶端
除了上面我們講到的幾個(gè)之外,我們還可以使用 vscode,Visual Studio ,Eclipse IDE 等來(lái)進(jìn)行 nodejs 的調(diào)試,這里就不一一詳細(xì)介紹了。
感興趣的朋友可以自行探索。