説明
概要
ChefのService Resourceでは、冪等性を担保するために/sbin/service <service-name> status
みたいなコマンドを使って現在のServiceの状態を取得する場合があります。1
具体的には、コマンドの終了コードが0
だと起動、それ以外だと未起動と判定されます。
となると、ここでそのstatus
コマンドが終了コードを返さなかったり、おかしなコードを返すことがうまく動かないということになるのですが、そういったケースはたまにあります。特にRHELファミリー。。。2
具体的にどういった時に起きうるのか
デフォルトでは、起動中のプロセスの中から指定されたサービス名を探して判定されますが、以下の様な記述をしているとstatus
コマンドが使用されます。
service "hoge" do
supports :status => true
end
Webのサンプルコードなんかでも指定しているものが散見されるので、特に意識せず指定しちゃっている場合もあるかもしれません。
ただし、RHELファミリーに限ってはデフォルトで:status => true
になっています(なんでや!)3
対処法
終了コードはちゃんと返すよう起動スクリプトを修正する
一番真っ当な対処法ですね。
ですが、パッケージインストールしたものだったりすると、パッチや修正依頼を送って待つにも時間かかるし
面倒だしで現実的ではないこともあります。
status
コマンドを使わせない
以下のように書きましょう。
service "hoge" do
supports :status => false
end
起動確認用のコマンドを置き換える
例えば、デフォルトの挙動だとサービス名が含まれるプロセスが別にあったりする4とうまく動かないことが予想されます。そういった場合に、起動確認用のコマンドを置き換えることができます。
service "hoge" do
status_command 'hoge piyo'
end
最後に
この件に関しては、対処法もそうなんですが、そもそもとして以下を気をつけたほうが良いと思います。
-
suports
を指定する場合、本当にそれが使えるコマンドか確認する - RHELファミリーに限ってはデフォルトで
:status => true
ということで、久々にけっこうハマったので書き留めておきました。
-
https://github.com/chef/chef/blob/master/lib/chef/provider/service/simple.rb の
determine_current_status
メソッド参照 ↩ -
RedHatとかCentOSとかAmazon Linuxとか ↩
-
https://docs.chef.io/resource_service.html (Attribute -> supportsの最後の方に「Default value: { :restart => false, :reload => false, :status => false } for all platforms (except for the Red Hat platform family, which defaults to { :restart => false, :reload => false, :status => true }.)」って書いてる・・・) ↩
-
マッチに使用するservice_nameを厳密に指定するという方法もあります ↩