はじめに
Ruby製のデプロイツールであるCapistranoを使ってみました。いろいろなレシピを眺めていると、sudoの書き方が次のようにいろいろあって違いがわからなかったので、調べてみました。
sudo "hoge" # (1) sudoアクション run "sudo hoge" # (2) 文字列 "sudo" run "#{sudo} hoge" # (3) 文字列 "#{sudo}" run "#{try_sudo} huge" # (4) 文字列 "#{try_sudo}"
なお、対象のバージョンは、執筆時点で最新の2.14.2です。
(1) sudoアクション
この書き方は、deprecatedなので今は使いません。
2.x DSL Action Invocation Sudo · capistrano/capistrano Wiki
(2) 文字列 "sudo"
書いてある通りにsudoコマンドが実行されます。sudoにパスワードが必要な場合をうまくハンドルできないことがあるので、次の"#{sudo}"を使うべきです。
(3) 文字列 "#{sudo}"
これは変数sudoが展開されるようにも見えますが、実際はsudoメソッドの呼び出し結果が展開されます。使ってみるとわかりますが、"#{sudo}"は、"sudo -p 'sudo password: '"と展開されます。
-pオプションでプロンプトを明示的に指定することで、パスワードが要求されていることをCapistranoが確実に検知できる仕組みです。sudoしたいときは、この書き方を使いましょう。
#{sudo :as => 'bob' }"のようにして、ユーザーを指定することもできます。
2.x DSL Action Invocation Sudo · capistrano/capistrano Wiki
(4) 文字列 "#{try_sudo}"
設定:use_sudoがtrueの場合(デフォルト)はsudoを使い、falseの場合はsudoを使いません。Capistranoがデフォルトで定義しているデプロイプロセスで使われるものなので、ユーザーがdeploy.rbに書くべきものではないと思われます。
:use_sudoの解説 には、次のように書いてあります。
Defines for the default Rails deployment recipes whether we want to use
sudoor not.sudois a unix tool for executing commands as the root user. To use it, your user must have password-lesssudoaccess enabled. If you’re using shared hosting wheresudoaccess may not be enabled for your user, you should set:use_sudo to false. In general, if you can get away without usingsudo, you should avoid it. For example, 37signals now uses a system where they have a special deployment user, and always deploy as that user.
sudoを使わずに済むなら:use_sudoをfalseにしてsudoを使わないようにしましょうと書いてあります。37signalsでは、デプロイ専用のユーザーを用意して、デプロイは常にそのユーザーで行っているそうです。
なお、歴史的経緯はよくわかりませんが、:use_sudoをtrueにしている(デフォルト)場合、cap deploy:setupでroot権限でユーザーが作られてしまうため、そのままではcap deployでgit cloneできないという問題があります。
このことからも、:use_sudoはfalseにすべきでしょう。
まとめ
sudoしたいときは、run "#{sudo} huge"と書きましょう。set :use_sudo, falseとして、デプロイ専用のユーザーでデプロイしましょう。