みなさん、こんにちは。ピクトリンク事業部インフラ課の藤本佳世です。
最近、サーバのリプレース作業の一環として、バッチスクリプトの移行作業を実施しています。この作業中、「sudo: ruby: コマンドが見つかりません」問題に出くわしたので、対処方法をシェアしたいと思います。
問題
フリューでは、rundeckを使って日次・月次のバッチを実行しています。
新しく構築した環境(以下、新サーバとします)に、従来通りの手順でスクリプトを実行しようとしたところ、エラーが出てしまいました。
$ sudo /usr/local/rundeck_scripts/test/example.sh
/usr/local/rundeck_scripts/test/example.sh: 行 52: ruby: コマンドが見つかりません
今までは問題なく実行できていたのに、なぜ……?
対応策
sudoにオプションiをつけて解決しました。
$ sudo -i /usr/local/rundeck_scripts/test/example.sh
詳細
エラーになっているexample.shの52行目を確認すると、rubyスクリプトを実行する記述がありました。
エラーの原因は、このrubyコマンドを実行した際、rubyコマンドが見つかりませんというエラーのようです。
ruby ./example.rb
実際に新サーバにsshログインし、rubyコマンドがないのかバージョン確認で検証してみました。
やはり、「ruby:コマンドが見つかりません」が出力されました。
$ sudo ruby -v sudo: ruby: コマンドが見つかりません
旧サーバで実施すると問題ありませんでした。
$ sudo ruby -v ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-linux]
rootで実施すると問題ありませんでした。
# ruby -v ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]
# ruby -v ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-linux]
原因は、sudo経由で実行した場合、環境変数が引き継がれない...という問題でした。
もう少し詳しく説明すると
sudo はrootや他のユーザの権限でコマンドを実行することができますが、sudoの設定(/etc/sudoers)によっては、環境変数が引き継がれなかったり、上書きされる設定になっている事があります。
こちらは/etc/sudoersファイルの一部を切り取ったものです。
Defaults env_reset Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS" Defaults env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE" Defaults env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES" Defaults env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE" Defaults env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY" # # Adding HOME to env_keep may enable a user to run unrestricted # commands via sudo. # # Defaults env_keep += "HOME" Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
env_resetが設定されていてますが、これはsudoが実行された際、環境変数がsecure_pathの設定値に上書きされてしまいます。
またenv_keepにPATHがないためにPATHが引き継がれません。
Defaults env_keep += "PATH"
上記のように、/etc/sudoersに追加することで、PATHを引き継ぐことができますが、
今回、私はsudoにオプション-iをつけて対応しました。オプション-iとは、何でしょうか?
こういう時は、–helpコマンドで調べると便利です。
$ sudo --help
-i, --login 変更先のユーザーとしてログインシェルを実行する; コマンドを指定することもできます
では、 -i
オプションの効果を踏まえて、ruby の設定が環境変数のPATHに設定されているかを見てみましょう。
$ sudo printenv PATH /sbin:/bin:/usr/sbin:/usr/bin
sudoだと環境変数のPATHが通っていません。
オプション-iを付けることにより、この問題を解消することができます。
$ sudo -i printenv PATH /usr/local/rvm/gems/ruby-2.4.1/bin:/usr/local/rvm/gems/ruby-2.4.1@global/bin:/usr/local/rvm/rubies/ruby-2.4.1/bin:/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/rvm/bin:/opt/dell/srvadmin/bin:/opt/dell/srvadmin/sbin:/root/bin
補足
sudo のオプションに-Eがあります。
$ sudo --help
-E, --preserve-env コマンドを実行する時にユーザーの環境変数を維持する
これも環境変数を維持してくれるものになりますが、これでは問題を解決することができませんでした。
原因は不明なので、こちらに関してはもう少し調査する予定です。
$ sudo -E printenv PATH /sbin:/bin:/usr/sbin:/usr/bin
最後に
フリューでは、全ユーザにsudo実行できる権限を付与するかわりにrootでのシェル操作を禁止しています。
【理由】
- セキュリティ向上のため
- rootコンソールでシェル操作をすると、「誰」が「何」を操作したのか解りにくくなるため
- sudoを使用してのroot権限での操作はログに残るので追跡調査が可能になるため
今回のように、sudoを使っているといくつかの問題に出くわすことがあります。
しかし、セキュリティを担保するためには、rootで直接実行するよりもsudoを使うよう習慣付けるのが望ましいです。
そのためにも、今回のようにオプションを調べて対応することが、今後も大切になりそうです。