経緯
ansibleを書いている時に実行ユーザーに依存したフォルダ構造がある場合にansibleの実行ユーザーを明示的に指定したい時が稀にある。
例えば以下のようなtempalte moduleの対象ファイルが templates
フォルダ以下にない場合。(ちゃんと各roles配下に置けよ、って話は置いておいて)
- name: get the username running the deploy
local_action: command whoami
register: username_on_the_host
- name: Set zabbix proxy on elasticsearch.userparam.j2 to elasticsearch.userparam
template:
src: "/home/{{ username_on_the_host.stdout }}/hoge.sh.j2"
dest: /dest/forlder/hoge.sh
問題
sudo su -l user -c 'ansible-playbbok entry.yml'
のようにコマンド実行したところ、以下のエラーで怒られる
Host key verification failed
公開キーの配置、秘密鍵の配置、秘密鍵のファイル権限も問題なさそうなことは確認。
もう少し詳しくデバッグするために直接sshコマンドを打ってデバッグする
sudo su -l user -c 'ssh -vvvvv -i key.prm user@ip'
するとpassphraseの処理で落ちていることが分かる
debug1: read_passphrase: can't open /dev/tty: No such device or address
Host key verification failed.
/dev/ttyって?
tty
自体は標準入出力を制御する端末デバイスを表示するコマンド。
このエラーから分かることは鍵の検証処理中に標準入出力が存在しなくて落ちている、とうい状態。
が、このansible自体はインタラクティブに標準入出力を制御する想定でないので何かがおかしい。
普通にsshしてみる
普通にユーザーを変更してsshしてみる
sudo su user
ssh -i key.prm user@ip
するとはじめてのログイン時に求められる(known_hostsに登録されていない)おなじみの警告が出て、標準入力を求められていることが判明。
Are you sure you want to continue connecting (yes/no)?
結論
どうやら su -l user -c
でユーザーを指定した時に標準入力の処理に入った時点で実行ユーザーの仮想ターミナルが存在しなくて、処理が落ちるらしい。
なのでsshの場合は ssh -o StrictHostKeyChecking=no -i key.prm user@ip
のようにオプションを付与する。
ansibleの場合は ~/.ansible.cfgに以下の設定を付けることで回避可能です
[defaults]
host_key_checking = False