cron内のsshでsudoするには

結論は一番下に書いてあります。

sshでsudoするとよく見るメッセージ

sudo: sorry, you must have a tty to run sudo

これは、/etc/sudoers で terminal を要求するようになっているためである。なぜデフォルトでそうなっているのかもコメントに書いてある。

#
# Disable "ssh hostname sudo <cmd>", because it will show the password in clear.
#         You have to run "ssh -t hostname sudo <cmd>".
#
Defaults    requiretty

理解した上で設定を変更する場合は、それで解決するので、これ以降は読まなくて良い。 ちなみに、特定のコマンドだけ設定を変更することもできるらしい。

sudo - How to disable requiretty for a single command in sudoers? - Unix & Linux Stack Exchange

ここまではすでにいくつもの記事に書かれている。本題はここから。

コメントに書かれているように ssh -t をすれば、terminalから叩く場合は問題なくなる。

それでは cron から、さらに sshでsudoをするとどうなるのかというと、 -t だけでは足りないので、 -tt とする必要がある。 -tt オプションについてはCentOS 6のman sshで以下のように書かれている。

-t      Force pseudo-tty allocation.  This can be used to execute arbitrary screen-based programs on a remote machine, which
         can be very useful, e.g. when implementing menu services.  Multiple -t options force tty allocation, even if ssh has
         no local tty.

つまり local tty がない場合は、複数回 -t オプションをつけるように、とのこと。

では、実際に試して見る。

まずは、以下のスクリプトを作成。リモートサーバではパスワードなしでsudoできるようにしておく。

#!/bin/bash -x

ssh remote-host sudo id
ssh -t remote-host sudo id
ssh -tt remote-host sudo id

crontabで仕掛ける。

* * * * * path/to/a.sh >> path/to/cron.log 2>&1

しばし待つと、以下のログが出る。

+ ssh remote-host sudo id
sudo: sorry, you must have a tty to run sudo
+ ssh -t remote-host sudo id
Pseudo-terminal will not be allocated because stdin is not a terminal.
sudo: sorry, you must have a tty to run sudo
+ ssh -tt remote-host sudo id
tcgetattr: Invalid argument
uid=0(root) gid=0(root) groups=0(root)
Connection to remote-host closed.

-ttでうまく実行されたが、変なエラーがでる。 tcgetattr: Invalid argument について調べると以下のページがヒットした。

mysql - why is the `tcgetattr` error seen when ssh is used for dumping the backup file on another server? - Stack Overflow

このエラーは terminal の情報を取ろうとして出ているものらしい。それ以上の詳細は書かれていないが、対応策として、おもむろに/dev/nullにリダイレクトしている。他のいくつかのページを見ていても、harmlessなので無視して良いとか言っているが、本当だろうか。

Problem using Net::OpenSSH->capture to su to another user https://groups.google.com/forum/#!topic/comp.security.ssh/ISjpJhTxKVY

結論

調査が十分にできなかったが、ひとまずの結論としては、「cronからの場合、ssh -tt sudo ...とすれば動く。軽く使う用途なら、これで問題なさそう。しかし万全を期すならもう少ししっかり調べたほうが良い」というところ。

sshからのsudoは構成管理ツールやデプロイツールで比較的よく使う組み合わせで、cronで動かすこともあると思うので、その辺のソースを調べれば、もう少し情報が集まるかもしれないが、これは今後の課題。