はじめてのNode.js:Node.jsアプリケーションのデバッグ

図1 node-inspectorの画面

 Node.jsアプリケーションのデバッグを行う際に、変数の値や実行中の関数、実行した関数の戻り値といったプログラムの内部的な状態を外部から確認することで、デバッグの効率が大幅に向上する。本記事ではこれらを実現できるNode.js組み込みのデバッグ機能や、GUIで操作できるデバッガ「node-inspector」について紹介する。

【連載】はじめてのNode.js

本記事について

 本記事は、3月13日にソフトバンク クリエイティブより発売された書籍「はじめてのNode.js -サーバーサイドJavaScriptでWebアプリを開発する-」から、「第7章 Node.jsアプリケーションのデバッグ方法」の一部を抜き出し再構成したものです。

 出版社ページ / Amazon.co.jpの商品ページ

 大型本: 384ページ、価格:3,045円(税込)、ISBN: 978-4797370904

Node.js組み込みのデバッガを使う

 nodeコマンドには、CUIで操作できるデバッグ機能が組み込まれている。実行中のコードを表示したり、変数や関数の戻り値を表示する、といったシンプルな機能のみを持つデバッガであるが、別途ツールなどをインストールすることなしに手軽にプログラムの実行状況を確認できる。

 デバッグ機能を使うには、node debugコマンドを使用する。

$ node debug <実行するスクリプト名>

 たとえば、次のようなプログラム(sample7-2.js)をデバッグする例を考えよう。

console.log('hello, world');

function foo() {
  console.log('hello, foo');
  return 100;
}

var bar = 'This is a pen.';
var http = require('http');

var i = foo();
console.log(i);

 このプログラムをデバッグする場合、次のようにする。

$ node debug sample7-2.js 
< debugger listening on port 5858
connecting... ok
break in sample7-2.js:3
  1 // This is sample program 7-2
  2 
  3 console.log('hello, world');
  4 
  5 function foo() {
debug> 

 node debugコマンドでは、実行するモジュールの一番最初の命令文を実行する直前でプログラムが一時停止され、画面に「debug>」というプロンプト(デバッグプロンプト)が表示される。この例の場合、「break in sample7-2.js:3」と表示されているが、これは「sample7-2.js」ファイルの3行目の直前でプログラムが停止している、ということを意味している。

 一時停止しているプログラムの実行を開始するには、デバッグプロンプトが表示された状態でcont(「continue」の略)、もしくはcコマンドを実行する。するとプログラムの実行が再開され、その結果がコンソールに表示される。

debug> c
< hello, world
< hello, foo
< 100
program terminated
debug> 

 プログラムの実行が完了すると、コンソールに「program terminated」と表示される。この状態でrunもしくはrコマンドを実行すると、プログラムを最初から再度実行させることができる。

debug> r
< debugger listening on port 5858
connecting... ok
break in sample7-2.js:3
  1 // This is sample program 7-2
  2 
  3 console.log('hello, world');
  4 
  5 function foo() {
debug> 

 contもしくはcコマンドの代わりにnextもしくはnコマンドを実行すると、プログラムを1ステップずつ実行できる。

debug> n
break in sample7-2.js:10
< hello, world
  8 }
  9 
 10 var bar = 'This is a pen.';
 11 var http = require('http');
 12 
debug> 

 この例の場合、プログラムの3行目にある「console.log(‘hello, world’);」が実行されてコンソールに「hello, world」という文字列が表示され、次の命令文である10行目の直前でプログラムが停止している。

 nextコマンドでは、このように命令文単位でプログラムを実行する。そのため、たとえば「var i = foo();」というような関数呼び出しを含む命令文については、その結果のみを表示する。

debug> n
break in sample7-2.js:13
 11 var http = require('http');
 12 
 13 var i = foo();
 14 console.log(i);
 15 
debug> n
< hello, foo
break in sample7-2.js:14
 12 
 13 var i = foo();
 14 console.log(i);
 15 
 16 
debug> 

 命令文内で呼び出されている関数をステップ実行したい場合は、nextコマンドの代わりにstepもしくはsコマンドを利用する。stepもしくはsコマンドを実行すると、呼び出された関数内の最初の命令の直前で実行が停止される。この操作は「ステップイン」と呼ばれている。

debug> n
break in sample7-2.js:13
 11 var http = require('http');
 12 
 13 var i = foo();
 14 console.log(i);
 15 
debug> s
break in sample7-2.js:6
  4 
  5 function foo() {
  6   console.log('hello, foo');
  7   return 100;
  8 }
debug> 

 また、outもしくはoコマンドを実行すると、実行中の関数から抜けるまでプログラムを実行し、次の命令文の直前で停止する。この操作は「ステップアウト」と呼ばれている。

debug> o
< hello, foo
break in sample7-2.js:14
 12 
 13 var i = foo();
 14 console.log(i);
 15 
 16 
debug> 

 なお、Node.jsでは非同期にプログラムが実行されるため、プロンプトが表示されている場合でもバックグラウンドでプログラムが動作していることがある。この状態でpauseコマンドを実行すると、バックグラウンドで実行されているプログラムを一時停止させることができる。

変数の値をウォッチする

 デバッガには実行中プログラムの変数の値を確認する「ウォッチ」機能もある。これは、ステップ実行を行うごとにあらかじめ指定しておいた式を評価しその結果を表示する、というものだ。ウォッチ機能を使うには、デバッグプロンプトが表示された状態でwatchコマンドを実行する。

watch('評価する式')

 watchコマンドの引数には、評価する式を文字列で指定する。たとえば変数iをウォッチするには、次のようにする。

$ node debug sample7-2.js
< debugger listening on port 5858
connecting... ok
break in sample7-2.js:3
  1 // This is sample program 7-2
  2 
  3 console.log('hello, world');
  4 
  5 function foo() {
debug> watch('i')
debug>

 また、ウォッチを解除するには、unwatchコマンドを実行すればよい。

unwatch('<評価する式>')

ブレークポイントを設定する

 プログラムの不具合を見つける際に、疑わしい個所までいちいちステップ実行で進めて行くのは面倒だ。そのため、デバッガには指定した個所でプログラムの実行を一時停止させる機能が用意されている。ここで一時停止させる個所を「ブレークポイント」と呼ぶ。

 ブレークポイントを設定するには、setBreakpointもしくはsbコマンドを実行する。

setBreakpoint(filename, line)
sb(filename, line)

 sbはsetBreakpointのエイリアス(別名)であり、その動作はどちらも同じだ。filename引数にはブレークポイントを設定したいスクリプトファイル名を文字列で指定し、line引数にはブレークポイントを設定したい行番号を数値で指定する。なお、filename引数を省略した場合は現在実行しているファイルが対象となり、またline引数とfilename引数の両方を省略した場合は次に実行される行にブレークポイントが設定される。

 たとえば、現在実行しているファイルの10行目にブレークポイントを設定するには、次のようにする。

debug> setBreakpoint(10)
  1 // This is sample program 7-2
  2 
  3 console.log('hello, world');
  4 
  5 function foo() {
  6   console.log('hello, foo');
  7   return 100;
  8 }

 ブレークポイントを設定した後にcコマンドで実行を開始させると、ブレークポイントを設定した行で動作が一時停止する。このとき、ブレークポイントが設定された行には行番号の前に「*」マークが表示される。

debug> c
< hello, world
break in sample7-2.js:10
  8 }
  9 
*10 var bar = 'This is a pen.';
 11 var http = require('http');
 12 
debug> 

 ブレークポイントを解除するには、clearBreakpointもしくはcbコマンドを使用する。

clearBreakpoint(filename, line)
cb(filename, line)

 そのほか、デバッガで使用できるコマンド一覧は表1のとおりだ。

表1 デバッガのコマンド一覧
コマンド名説明
cont、c実行を再開する
next、n次の命令を実行して一時停止する(ステップ実行)
step、s次の関数の先頭で一時停止する(ステップイン)
out、o実行中関数から抜けるまで実行して一時停止する(ステップアウト)
pauseコードの実行を一時停止する
setBreakpoint()、sb()ブレークポイントを設定する
clearBreakpoint()、cb()ブレークポイントを解除する
backtrace、btバックトレースを表示する
list(number)次に実行する命令の前後のソースコードをnumber引数で指定した行数ずつ表示する
watch(expr)expr引数で指定した式をウォッチする
unwatch(expr)expr引数で指定した式のウォッチを解除する
watcherウォッチしている式とその値を一覧表示する
replreplを開始する
runプログラムの実行を開始する
restartプログラムを先頭から再実行する
killスクリプトの実行を強制終了(KILL)する
scriptsロードされているスクリプトを一覧表示する
versionV8のバージョンを表示する

node-inspectorを使う

 node-inspectorは、Node.jsプログラムをGUIでデバッグするためのWebアプリケーションだ。搭載している機能自体はNode.jsのデバッガと同じだが、ソースコードや変数の値をGUIで確認しながらデバッグを行えるのが特徴だ。

 node-inspectorは、npmコマンドでインストールできる。

$ npm install node-inspector

 node-inspectorでデバッグを行うには、まずデバッグしたいプログラムを–debug-brkオプション付きで実行する。

$ node --debug-brk sample7-2.js 
debugger listening on port 5858

 この状態で、別のコンソールからnode-inspectorを起動する。

$ ./node_modules/.bin/node-inspector
   info  - socket.io started
visit http://0.0.0.0:8080/debug?port=5858 to start debugging

 ここで表示されているURL(この場合0.0.0.0:8080)にWebブラウザでアクセスすると、node-inspectorの画面が表示される(図1)。

図1 node-inspectorの画面
図1 node-inspectorの画面

 node-inspectorでは一般的なGUIの統合開発環境のように実行中のソースコードやコールスタック、変数の値などがGUIで表示される(図2)。右上のツールバーではステップ実行などの操作が可能だ。また、「Console」タブではreplコンソールにアクセスでき、ここで変数の値を確認したり、関数の実行が行える。

図2 node-inspectorのコンソール
図2 node-inspectorのコンソール

【連載】はじめてのNode.js

本記事について

 本記事は、3月13日にソフトバンク クリエイティブより発売された書籍「はじめてのNode.js -サーバーサイドJavaScriptでWebアプリを開発する-」から、「第7章 Node.jsアプリケーションのデバッグ方法」の一部を抜き出し再構成したものです。

 出版社ページ / Amazon.co.jpの商品ページ

 大型本: 384ページ、価格:3,045円(税込)、ISBN: 978-4797370904