hello.sh
#!/bin/sh
while :
do
date
sleep 1
done
ローカルホストにおけるバックグラウンド処理はコマンドの後に '&' を付与することで実現できます。リダイレクションについてはこちらをご参照ください。
$ ./hello.sh > out.txt 2>&1 &
$ tailf out.txt
2015年 6月 15日 月曜日 20:07:37 UTC
2015年 6月 15日 月曜日 20:07:38 UTC
$ jobs
[1]+ 実行中 ./hello.sh > out.txt &
$ fg
./hello.sh > out.txt
Ctrl-C
リモートホストにおけるフォアグラウンド処理は ssh コマンドの後に所望の処理を記述することで実現できます。
$ ssh REMOTEHOST "./hello.sh"
2015年 6月 15日 月曜日 20:09:58 UTC
2015年 6月 15日 月曜日 20:09:59 UTC
リモートホストにおけるバックグラウンド処理を実現するためにはどうしたらよいでしょうか。
ローカルホストにおけるバックグラウンド処理と同様に '&' を付与することで実現できます。
$ ssh REMOTEHOST "./hello.sh > out.txt 2>&1 &"
$ ssh REMOTEHOST "tailf out.txt"
2015年 6月 15日 月曜日 20:16:20 UTC
2015年 6月 15日 月曜日 20:16:21 UTC
しかしながらプロセスによってはターミナル終了時に送信される可能性のある SIGHUP で処理が停止してしまいます。その場合は次の方法を検討します。
シグナルは UNIX 系 OS においてプロセス間の非同期通信などで使用されます。様々な種類のシグナルがあります。
$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
kill コマンドの -s オプションによって任意のシグナルをプロセス ID 指定で送信できます。
$ kill -s 15 PID
代表的なものをいくつか抜粋します。
プロセスによっては SIGHUP を無視して処理を継続します。特に一部のデーモンプロセスは SIGHUP を終了ではなく再起動のために利用します。シグナルのキャッチについてはこちらをご参照ください。
nohup コマンドを利用することで SIGHUP を無視するプロセスを生成できます。/dev/null で標準入力を閉じています。
$ ssh REMOTEHOST "nohup ./hello.sh > out.txt 2>&1 < /dev/null &"
$ ssh REMOTEHOST "tailf out.txt"
2015年 6月 15日 月曜日 21:14:00 UTC
2015年 6月 15日 月曜日 21:14:01 UTC
kill コマンドで SIGHUP を送信してもプロセスが停止されないことが分かります。
$ pgrep -l hello.sh
10084 hello.sh
$ kill -s 1 10084
$ pgrep -l hello.sh
10084 hello.sh
しかしながら SIGHUP 以外のシグナルは無視できません。何らかの原因によって処理が停止してしまう場合は次の方法を検討します。
screen はこちらで紹介した tmux と同様に仮想端末を提供するコマンドです。手動でログインする場合に screen または tmux を利用してリモート処理をターミナルを閉じても継続して実行できることはよく知られています。あまり知られていないですが、それに加えて、実は screen または tmux コマンドは nohup と同様に ssh の引数内でも利用できます。自動化時に重宝します。ファイルへのリダイレクトは bash のサブコマンドであれば実現できます。標準でインストールされていることの多い screen の例を示します。
$ ssh REMOTEHOST "screen -dm -S qoosky bash -c './hello.sh > out.txt'"
検証してみます。
$ ssh REMOTEHOST "screen -ls"
There is a screen on:
10602.qoosky (Detached)
1 Socket in /var/run/screen/S-ec2-user.
$ ssh REMOTEHOST "tailf out.txt"
2015年 6月 15日 月曜日 21:53:07 UTC
2015年 6月 15日 月曜日 21:53:08 UTC
プロセスの処理が完了すれば仮想端末は自動で消滅します。
$ ssh REMOTEHOST "screen -ls"
No Sockets found in /var/run/screen/S-ec2-user.
処理の完了を待たずに終了したい場合は以下のようにします。
$ ssh REMOTEHOST "screen -S qoosky -X quit"
nohup コマンドの場合と比較してプロセスが fork されている場合におけるシグナル耐性が高いように思われます。nohup でうまくいかない場合には利用を検討してみてください。