SSH 接続先でサーバを立ち上げっぱなしにしてログアウトするための Bash の書き方
自端末から、SSH で Linux (CentOS) サーバに接続し、その Linux サーバ上で Express サーバを立ち上げ、SSH 接続を切断したかった。
Express サーバは、$ npm install
後、$ node main.js
と叩くと起動するようになっているのだが、ターミナルを閉じたり、ログアウトしたりした時に、このプロセスを生かし続ける方法が分からず調べた。
結論からいうと、Linux の nohup
というコマンドを使うと実現できた。
HUP シグナルを無視しつつバックグラウンドプロセスで起動する
nohup
を使って、SSH 切断後もプロセスを動かし続けるには、nohup 【コマンド】 &
というイディオムを使う。
nohup
コマンド自体は、SSH ログアウトなどを行った時に送信される HUP (ハングアップ) シグナルを無視するだけ。そのコマンドをバックグラウンドで動かすには、末尾に &
を与える。
というワケで、以下のように叩けば良い。
# Linux サーバに SSH 接続する
$ ssh -p 22 hogeuser@linux-host
# Linux サーバにて以下のように実行する
$$ nohup node main.js > /dev/null 2>&1 </dev/null &
# プロンプトが戻るので、このまま exit したりして良い
$$ exit
標準出力、エラー出力などを無視するため、リダイレクトと /dev/null
の記述を追加してはいるが、nohup node main.js &
ということだ。
バックグラウンドで起動しているプロセスを停止させるには
最初の目的はこれで果たせたが、今度はこの Express サーバを止めたくなった時にどうするか、ということである。普通プロンプトを奪われたままだったら、Ctrl + C
で終了できたのに…というところ。
具体的な手法がいくつかあるのでこれから紹介するが、やろうとしていることは プロセスを特定して終了させる、ということだ。
方法1 : ps
でプロセス ID を調べて kill
する
最も原始的なやり方は、ps
コマンドで node main.js
が動作している PID (プロセス ID) を取得して、コレを指定して kill
コマンドを叩く、というモノ。
$ ps aux | grep [n]ode
Neo 4954 0.0 0.5 5226356 39428 s000 S 1:32PM 0:00.72 node main.js
# コレでプロセス ID が「4954」と分かったので、以下のように叩く
$ kill -9 4954
$ ps aux | grep [n]ode
# 何も出なくなる = プロセスが終了できた
grep
コマンドの検索文字列に [n]ode
と書いているが、先頭の文字列を []
で囲むと、grep
コマンド自身のプロセスを除外できるという小技だ。
# 「[n]」と書かないと、以下のように grep コマンド自身も表示されてしまう
$ ps aux | grep node
Neo 4980 0.0 0.0 4267768 896 s000 S+ 1:32PM 0:00.00 grep --color node
Neo 4954 0.0 0.5 5226356 39428 s000 S 1:32PM 0:00.72 node main.js
方法2 : pgrep
でプロセス ID を取得して kill
する
pgrep
という便利なコマンドがある。ps | grep
を一気にやってくれるようなコマンドだ。このコマンドはプロセス ID だけを返すので、コレを直接 kill
コマンドに渡してしまえば終了できる。
# 比較のため、「方法1」のやり方でプロセスを確認しておく
$ ps aux | grep [n]ode
Neo 5046 0.0 0.5 5226868 39796 s000 S 1:36PM 0:00.62 node main.js
# pgrep を使うと、検索対象のコマンドを指定して、PID のみ取得できる
$ pgrep -f 'node main.js'
5046
# 「$()」構文を利用して、kill コマンドに PID を渡して終了させる
$ kill -9 $(pgrep -f 'node main.js')
# 以下いずれのコマンドも結果が表示されなく鳴った = 停止できた
$ ps aux | grep [n]ode
$ pgrep -f 'node main.js'
方法3 : pkill
で対象のコマンドを指定して直接 Kill してもらう
「方法2」のようなことをしなくとも、同等のことをやってくれるコマンドとして、pkill
というコマンドが用意されている。最初からコレでよかった…。
# コレだけでプロセスを終了できる
$ pkill -f 'node main.js'
以上。コレで Express サーバを立ち上げっぱなしにできるぞ〜