ちくわ

ちくわにきゅうりを入れるとうまい

expcet + scp + cron で、日本語を判定するときに失敗して困った件

先日 「expect + scp でメタ文字(* : アスタリスク)を使用した際に失敗した時のメモ」 という記事を投稿しましたが、その続きの話です。

以下の様な expect を使用したスクリプトを用意しました。

接続先が Solaris で、SSH/SCP 接続時のプロンプトが「パスワード:」と日本語になっていましたので、

expect にもそのように設定しています。

$ cat test.sh

#!/bin/bash

# expect の function

func_expect (){

expect -c "

spawn $1

expect {

\"Are you sure you want to continue connecting (yes/no)?\" {

send \"yes\r\"

expect \"パスワード:\"

send \"hogehoge\r\"

} \"パスワード:\" {

send \"hogehoge\r\"

}

}

interact

"

}

# ファイルを SCP で送信

func_expect "sh -c \"scp /var/tmp/test_from/*.txt root@192.168.1.1:/var/tmp/test_to\""

そして、このスクリプトを crontab に登録し、定期的に実行しようと考えていました。

が、、、ターミナル上では成功するのに cron だと失敗するという切ない結果に。。

結論から言うと、上記は以下 2 つの理由で失敗します。

  • interact は cron ではアカン
  • cron だと LANG の設定が消える(cron 実行ユーザの LANG 設定にはならない)

一つ目、interact ですが、man を読むとこう書いてありました。

       interact [string1 body1] ... [stringn [bodyn]]

は 、現プロセスの制御をユーザーに渡す。結果、現プロセスに送られたキーストロークと現プ

ロセスの標準出力と標準エラー出力が復帰する。

おおぅ、cron では使えなさそう... ネットでぱっと見つけた情報をコピペするのは危険ですね。

この情報はぐぐってもたくさん出て来ました。

参考例:えくすぺくと | novaの日記 | スラッシュドット・ジャパン

ということで、以下のように編集!

戻りの文字列を echo で出すようにして、その文字列を見て exit させるようにしました。

終る時間も scp が長引く事も考え、「set timeout」を追加。

最後の echo $? が 3 であれば、ちゃんと終了文字を拾ってくれるかどうか分かります(確認用)。

$ cat test.sh

#!/bin/bash

# expect の function

func_expect (){

expect -c "

set timeout 60

spawn $1

expect {

\"Are you sure you want to continue connecting (yes/no)?\" {

send \"yes\r\"

expect \"パスワード:\"

send \"hogehoge\r\"

} \"パスワード:\" {

send \"hogehoge\r\"

}

}

expect {

\"== expect END ==\" { exit 3 }

}

"

}

# ファイルを SCP で送信

func_expect "sh -c \"scp /var/tmp/test_from/*.txt root@192.168.1.1:/var/tmp/test_to ; echo '== expect END Flag ==' \""

echo $?

が、これもダメ、どうやら「パスワード」のところで止まっている模様...

その後試行錯誤して、cron で実行した際に LANG の設定が消える(C になる?)事が分かりました。

てっきり実行ユーザの LANG 設定が適用されると思っていました。

実際にスクリプトの途中に「set | grep LANG」を追加して、ターミナル上で手動実行した時は

LANG=ja_JP.UTF-8

と出ますが、cron で実行した時は何も出力されませんでした。

うまく日本語の処理ができず、expcet も失敗したと思われます。

最終的にはこうなりました。

export LANG="ja_JP.UTF-8" を追加しています。

$ cat test.sh

#!/bin/bash

# expect の function

func_expect (){

expect -c "

set timeout 60

spawn $1

expect {

\"Are you sure you want to continue connecting (yes/no)?\" {

send \"yes\r\"

expect \"パスワード:\"

send \"hogehoge\r\"

} \"パスワード:\" {

send \"hogehoge\r\"

}

}

expect {

\"== expect END ==\" { exit 3 }

}

"

}

export LANG="ja_JP.UTF-8"

set | grep LANG

# ファイルを SCP で送信

func_expect "sh -c \"scp /var/tmp/test_from/*.txt root@192.168.1.1:/var/tmp/test_to ; echo '== expect END Flag ==' \""

echo $?

以下 cron で実行した結果(出力結果をファイルにリダイレクトしたもの)。

LANG で UTF-8 の設定にもなってるし、最後のリターンコードが 3 になった事を確認。

これでようやくうまく言った。。。

$ ./test.sh

LANG=ja_JP.UTF-8

_=LANG

spawn sh -c scp /var/tmp/test_from/*.txt root@192.168.1.1:/var/tmp/test_to ; echo '== expect END Flag =='

root@192.168.1.1's password:

M1.txt 100% 0 0.0KB/s 00:00

M2.txt 100% 0 0.0KB/s 00:00

M3.txt 100% 0 0.0KB/s 00:00

== expect END Flag ==

3

※「set | grep LANG」 や最後の $? は確認用ですので、本番用では削除しました。

ちなみに、solaris のパスワードプロンプトが日本語なのは困ってる人他にもいるみたい

Solaris resource Adapter 〜パスワードプロンプトにご用心