FURYU Tech Blog - フリュー株式会社

フリュー株式会社の開発者が技術情報を発信するブログです。

udo: ruby: コマンドが見つかりません。。。

みなさん、こんにちは。ピクトリンク事業部インフラ課の藤本佳世です。

最近、サーバのリプレース作業の一環として、バッチスクリプトの移行作業を実施しています。この作業中、「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を使うよう習慣付けるのが望ましいです。

そのためにも、今回のようにオプションを調べて対応することが、今後も大切になりそうです。