期待してる - `expect` コマンド 再び
今回は shellscript での expcet
コマンドのお話.
以前にも,処理中に対話式でパスワード入力とか求められる操作を自動化したいと,この expect
コマンドについて触れました,この expect
コマンドの spawn
にてパイプ pipe |
を使う場合は,ちょっとしたコツが必要みたい.
と言うのを知りました.
具体的な事例をもって示しますと,こんな感じです.;
expect -c " spawn bash -c \"echo ${path_is} | sudo tee -a /etc/shells\" expect \"Password:\" send \"${PASSWORD}\n\" interact "
話は spawn
のライン.
spawn
へ定義するコマンドの記述に,パイプ |
を使用する場合,bash -c
と《直接 bash を書いて》やる方法を採ると良いらしいです.
ちなみに,bash
の -c
オプションに続く string
,今回の例で言いますと echo ${path_is} | sudo tee -a /etc/shells
の部分,この部分を囲むために使うダブルクォーテーション "
は,きちんとエスケープ \
を挿しておく必要があります.
エスケープなしに spawn bash -c "echo ${path_is} | sudo tee -a /etc/shells"
としてしまいますと,バババババっとエラーを吐いてきます.
つい忘れがち,という事で,これ地味に大事.
《expectスクリプトとしての「"」は\でエスケープする.》ってことなのでしょう.
他にもこちら記載のコード見てもそのようです.メモ.
と,さて閑話休題.
spawn echo ${path_is} | sudo tee -a /etc/shells
と言うの,ダメらしいです
上に示した正解に対して,イケていない方を示すと,こう.;
expect -c " spawn echo ${path_is} | sudo tee -a /etc/shells expect \"Password:\" send \"${PASSWORD}\n\" interact "
自身も,当初,上のような書き方をしてました.
このような書き方をしますと,次のようなエラーを落とします.
send: spawn id exp6 not open while executing
...ちょっと何言ってるかわからない.*1
通常*2ですと,spawn
に記述するコマンド文は "
で囲むことなく,いわゆる “そのまんま” 定義できるものと思っていて,当然その感覚で書いていたのですが,どうもそうではないケースがあるという事のようです.
では,どう言うことなのかと言うと,こう言うことらしいです.
それは,spawn
が,パイプ |
の前だけをコマンドだと思ってしまうから
expectの処理中は、パイプを通した処理の標準入出力の仕様が異なるのでしょうか。
: 略
これは、
spawn が、パイプの前だけをコマンドだと思って先に実行してしまうからです。
ですから、何とか spawn に 1コマンドだと思わせれば良いのです。
だそう.
言われれば,そんなことですか,と言った振る舞い.
思いの外,原始的と言いますか単純な話で,何か,拍子抜けと言うよりは,かえってモヤモヤ感が残ると言うのが正直あったりしますが.
上述の引用元にもありますが,bash
コマンドを直接書く方法だけではなく,別途,スクリプトファイルを用意する方法もあります.
その他に,別途スクリプトファイルを用意することで
このファイルには,本来 spawn
にて指定するはずの処理の部分を記載することになります.
そして用意したそのファイルを,spawn
側にて指定する,と言うやり方です.
今回の話で具体的に言いますと.
イメージとして分かり易いと思うので上手く動作しない方のコードを例にしますが,spawn echo ${path_is} | sudo tee -a /etc/shells
の “echo ${path_is} | sudo tee -a /etc/shells
” の部分を,別途,スクリプトファイルへ切り離す,といった考え方です.*3
上述引用元もありますが,ここにも同じ話がありましたので挙げておきたいと思います.;
If you can’t setup keys, you can put the “tar … | ssh …” line into another script and call it with spawn, just pass the required parameter
.i.e:
sh spawn anotherscript.bash $sdir $port $login $host
「"tar … | ssh …“ の部分を他のスクリプトに置いて,spawn にてそいつ呼びゃ良いんじゃない?」なこと言ってますね.
ついでに,自分の場合は,可能ならファイルを増やたくなかったので,この別ファイルに設ける方法は採りませんでした.
そんなこんなで、まさか Yahooクッソ袋ゥ(伊集院光氏トーンにて)知恵袋にお世話になろう時が来るとは思ってもおりませんでした.*4
はいおしまい。