bash / expectスクリプトでは、「相互作用」が期待どおりに機能しません。

bash / expectスクリプトでは、「相互作用」が期待どおりに機能しません。

内蔵デバイスを設定するには(フラッシュメモリに画像を書き込むなど)、起動フェーズでよく知られている一連のコマンドを入力する必要があります。アルゴリズムは次のようになります。

  • 起動中に任意のキーを入力してブートローダシェルをキャプチャします。
  • フラッシュイメージA
  • フラッシュイメージB
  • ...
  • 継続ブート(新しいイメージを使用)

ブート中のある時点で最初にブートローダシェルをキャプチャする必要があるため、expectスクリプトを適用するとこの問題はうまく解決されると思います。私返品接続するデバイスノードなどのロジックを実装するために、他のbashコマンドを混在させたいと思います。私が思いついたのは(予想される部分のみ)次のとおりです。

#!/bin/bash
DEVICE=...
FLASH_CMD_A=...
#Other bash stuff

expect <<SCRIPT
    set timeout 5
    spawn plink -serial -sercfg 115200,8,n,1 $DEVICE 

    expect "Hit any key to stop autoboot"
        sleep 1
        send "\r"

    expect "=>"
        sleep 1
        send "$FLASH_CMD_A\n"

    interact   
SCRIPT

echo "Done!"

私が観察したのは、最初の予想行が正しくキャプチャされ、スリープモードが機能し、改行が送信されるようです。次の期待(ヒントをつかむ)とそれに対応する睡眠も機能しているようです。 sendコマンド($ FLASH_CMD_A)は、単語の間に多くのスペースが含まれており、端末に印刷されますが、機能しているようです。

最大の問題は、彼らがinteract何もしないようです。 2番目の期待/転送が実行されると、bashシェルに戻り、「Done!」がstdoutに印刷されるのをまったく見ることはできません。また、インタラクティブな構文を使ってみました。

interact {
    "=>"{
        send "\r"
        exp_continue
    }
}

しかし役に立たない別の言葉。プロンプトはキャプチャされず、そのinteract文が存在しないかのようにスクリプトはすぐに終了します。何が間違っているのかというアイデアはありますか?私は持っています:

expect -v
expect version 5.45

注文は〜らしいデバイスに渡されるかどうかは不明です。 bashシェルに戻ると、このコマンドに従うデバイスのすべての出力が失われます。ただし、スクリプトを2番目に実行すると、予想されるテキストバッファ(expect_out?)がダンプされ、すぐに終了するようです。興味深いことに、以前に送信されたコマンドの出力がこのバッファダンプに含まれると予想しました。

注:仮想マシン環境で同じスクリプトを試しましたが、「予想される」ステートメントのどれもキャプチャされませんでした。すべての入力がstdoutとして印刷され、渡されました。

答え1

この問題を解決するには、標準入力の代わりにファイルからExpectスクリプトを実行してください。

#!/bin/sh

BLAH='echo hi'

ESCRIPT=`mktemp runner.XXXXXXXXXX` || exit 1

# nope
#expect -d - <<SCRIPT
cat >$ESCRIPT <<SCRIPT
  set timeout 5
  spawn $SHELL
  # FIXME whatever your prompt looks like
  expect -ex "% "
  send -raw "\r"
  expect -ex "% "
  send -- "$BLAH\n"
  expect -ex "% "
  interact
SCRIPT

expect -d $ESCRIPT

echo alas poor $SHELL I knew him well a man of infinit

# and probably also `trap` in the event this code gets whapped with an INT
# or something...
rm $ESCRIPT

関連情報