ansibleでmysqlにinsertしたらData too long for columnだけど手動だと成功する
結論: 環境変数 LANG (LC_ALL) を UTF-8 対応のにする
やりたかったこと:
mysql -uuser -ppassword < insert_data.sql
のansible化
ansibleではこのようなタスクを定義:
- name: insert data shell: mysql -uuser -ppassword < insert_data.sql
実行するとエラー
mysql: [Warning] Using a password on the command line interface can be insecure. ERROR 1406 (22001) at line 6: Data too long for column 'hoge' at row 1 mysql: [Warning] Using a password on the command line interface can be insecure. ERROR 1452 (23000) at line 3: Cannot add or update a child row: a foreign key constraint fails (`huga`.`piyo`, CONSTRAINT `piyo_1` FOREIGN KEY (`puyo`) REFERENCES `puyo` (`poyo`))
(パスワード直書きはこの際置いておく)
ググると、 Data too long エラーの解決策は、sql_mode を strict じゃないのにするといいらしい。
しかし、同じデータを使っている他のサーバの sql_mode は全く同じ内容で、しかも strict も存在する。
謎すぎるためとりあえずシェルに入って手動で実行してみる。
$ mysql -uuser -ppassword < insert_data.sql
…できた。??
手動ではできたということは、コマンドの実行環境が違う疑いが持てる。
# ログインシェルのbashで試行 - name: shell with login shell shell: bash -lc "mysql -uuser -ppassword < insert_data.sql" # become (sudo) なしで試行 - name: shell without become shell: mysql -uuser -ppassword < insert_data.sql become: no
どちらもだめ。
仕方ないので現在の変数定義をみてみる。
- name: show login shell environments shell: bash -lc declare become: no
手動でシェルに入って見てみた分と比較。(どちらも一部抜粋)
--- 手動でシェルに入った分 +++ ansibleでの分 -BASH=/bin/bash -BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:globasciiranges:histappend:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath +BASH=/usr/bin/bash +BASHOPTS=checkwinsize:cmdhist:complete_fullquote:extquote:force_fignore:globasciiranges:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath IFS=$' \t\n' -LANG=C.UTF-8 +LANG=C +LC_ALL=C +LC_CTYPE=C.UTF-8 +LC_MESSAGES=C
BASHOPTSが微妙に違うな〜などと見ていると、あれ、LANG系が全然違うぞと。
そういえばinsertするデータは日本語が入ってたなと。
試しにLANGをCにして実行してみる
LANG=C mysql -uuser -ppassword < insert_data.sql
無事に失敗!
ということで犯人はansibleが勝手に環境変数を変えた結果のLANGでした。
なのでansibleではこのようなタスクを定義して対処:
- name: insert data shell: LC_ALL=C.UTF-8 mysql -uuser -ppassword < insert_data.sql
うー、それにしてもなんで変数が変わってるのか…。
こんな記事
もあることからansible側を掘らないとわからないかも。
とりあえず対処できたのでヨシ!