Capistranoでバックグラウンド処理を発火する

Capistranoでバックグラウンドジョブを実行させたいときがある.
監視スクリプトなんかがいい例だ.


そんな時,2タイプの記事を見つけた.

  • sleepすればいいよ

d.hatena.ne.jp


  • $ /dev/nullリダイレクト

qiita.com




どちらも正しいのだけれど,おそらく両方が成功するわけではない.


というのも,これは別の設定に依存している.

ptyという設定

Capistranoのはptyというオプションがある.

set :pty, true

このオプション,デフォルトではfalseになっているが,結構trueにする記事も見かける.


quanon.hateblo.jp



qiita.com



そう,ptyとは仮想端末の割り当てフラグなのだ.

sudoなどはわかりやすい例で,やってみればわかるとは思うが,sshでコマンド引数からsudoを実行する際などに必要になる.

仮想端末があるかないかによって変わる

例えば,& /dev/nullという設定はコマンドラインでよく見かけるバックグラウンドジョブの起動方法だ.
これがきっちりバックグラウンドに移るのかどうかについては,以下の記事が非常に詳しい.

技術/UNIX/なぜnohupをバックグランドジョブとして起動するのが定番なのか?(擬似端末, Pseudo Terminal, SIGHUP他) - Glamenv-Septzen.net

おそらくこの場合,ptyで割り当てられた仮想端末が終了するときに,同時にプロセスを殺してしまっている.これは,プロセスが「STOP状態 + J_NOHUP有」になるからだ.そのために仮想端末がSIGCONTを送信してしまっている.



では,sleepは仮想端末が死んだ時,どうなるのか.
これは,sleepが付くことにより,プロセスがrunning状態になる.
これにより,上記記事の「RUNNING状態 + J_NOHUP無 」に該当し,SIGCONTとSIGTERMが送信されなくなる.そのため,プロセスは生き残る.

しかし,仮想端末がない状態でsleepしても,単にCapistranoの実行が待たされるだけで,別にバックグラウンドに移るわけではないので,次の瞬間にはプロセスが殺されてしまう.

どうすればいいの?

ptyがtrueのときはsleep

仮想端末がある場合は,上記の通り,sleepで対応する.

set :pty, true

namespace :deploy do
  task :hoge do
    run "(cd $DIR && (nohup sh ./background_script.sh &)) && sleep 1"
  end
end

ptyがfalseのときは& /dev/null


仮想端末がない場合は,通常のコマンドライン上でのバックグラウンド処理と同様になる.

set :pty, false

namespace :deploy do
  task :hoge do
    run "sh -c 'cd $DIR && nohup sh ./background_script.sh &' >& /dev/null"
  end
end