nodemonを使ってGo製Ginサーバをホットリロードしようとしたらハマった話
はじめに
事前にお伝えすると、Go 言語アプリケーションの開発を効率化するためにホットリロードを導入しようとした場合、最適なのは Air と呼ばれるライブリロードツールを利用するのが良いでしょう。
Air も Go 製ですので、Go の実行環境が整っていれば利用できます。
という前提をおいた上で今回のエントリへ。
ホットリロード ( ライブリロード ) を導入し、コードが変更されたことを自動検知して実行プロセスを再起動させると開発がスムーズに進められます。
今までいくつかのツールを遷移してきましたが、ここ数年は nodemon がお気に入りです。
アプリケーション開発時だけでなく、シェルスクリプト作成時にも利用でき、かつコマンド+オプション指定で利用できるところが気に入っています。過去にも以下のようなエントリを投稿しています。
前置きが長くなりましたが、Go 言語+Gin Web Framework を使った開発中をしていてホットリロードを導入するために nodemon 経由で go run
したところ、うまくリロードされないという事象にあいました。
どのような問題が発生したのかと、どのように解決したかを紹介します。
検証環境
まずは Gin のチュートリアルどおりにかんたんな Web API を作成
このあたりは足早に流していきます。
はじめに Gin のチュートリアルページをもとに、Web API を作成しました。
準備ができたら main.go
を実行します。
起動できたようなので、出力されたメッセージに従って、 8080 ポートにリクエストを投げてみます。
別ターミナルを開き、 curl
でつついてみます。
無事、Gin の Quick Start が終わりました。
一度プロセスを停止するために、 go run main.go
を停止します。
実行中のターミナルで CTRL + C
を押して停止します。
停止できました。
開発効率を上げるために nodemon でホットリロードをさせようとするが...
先程実行した Web サーバ起動用のコマンド go run main.go
を nodemon
コマンドで起動します。
--watch .
: カレントディレクトリ配下の変更をウォッチします--ext go
:.go
という拡張子を持つファイルの変更をウォッチします--exec "go run main.go"
: 変更を検知した際にgo run main.go
を実行します
実行ししばらくすると、以下のようなメッセージが出力されます。
http://localhost:8080/ping
にアクセスすると、先程同様の API 実行結果が取得できます。
それでは、 main.go
を変更してみます。
レスポンス JSON の message
フィールドの値を pong
から hello
に変更してみました。
main.go
nodemon
実行中のターミナルを確認してみると、変更を検知してプロセスを再起動しようとしているようですが、「サブプロセスの終了を待っている」というメッセージが表示され続けます。
http://localhost:8080/ping
にアクセスし、レスポンスが変わったか確認してみても、やはり変更前の情報が返却されます。
対処法 : nodemon
で変更を検知した際に SIGINT/SIGTERM
シグナルが送られるようにする
最初に go run main.go
を実行後に停止させたときに CTRL + C
を押したことと
ターミナルに以下のようなメッセージが表示されていたことを思い出しました。
CTRL + C
でなら問題なくプロセスが停止できるのであれば、 nodemon
で --exec
に指定したコマンドに SIGINT
シグナルを送信するようにすれば、解決するのではないでしょうか。
( 過去にシグナルに関係したエントリを書いたことがありました。シグナルってなんだろうという方は こちらのエントリ もどうぞ。 )
nodemon
には --signal
という隠しオプション(なぜかヘルプを引いても確認できない)があって、これを使って SIGINT
シグナルを送信してみます。
起動後に現在の JSON レスポンスを確認しておきます。
main.go を書き換え、JSON レスポンスの値を変更します。
同時に nodemon
を実行しているターミナルを確認してみました。
今度は無事、変更が検知された後 go run main.go
が再起動されたようです。
再び JSON レスポンスを確認してみます。
変更が反映されています 。
この後、他のシグナルでも試してみたところ、 SIGTERM
シグナルでも問題なく再起動されることがわかりました。
ひとこと
一応解決はしたのですが、 この解決方法で良いのか疑問が残ります。
nodemon
はファイルの変更を検知した際に、実行中プロセスにどんなシグナルを送信しているんでしょうね。
Gthub 上の nodemon のソースコードをチラ見すると、 SIGUSR2
というシグナルを送っているように見えます。
ディスカッション
コメント一覧
まだ、コメントがありません