リモートシステムでスクリプトを実行するには、見積もりを使用します。

リモートシステムでスクリプトを実行するには、見積もりを使用します。

このプロジェクトを完了するために必要なほとんどの情報を自動化しましたが、唯一の遅れは、リモートシステムでローカルシェルスクリプトを実行することです。

私たちは、「expect」ライブラリを使用するスクリプトがどのLinuxコマンドも認識しないことを知っています。

ここに私が試した2つのユースケースがあります。

  1. Expectスクリプトを使用してリモートサーバーに必要なコマンドのリストを実行すると、スクリプトを実行し、scpを使用して出力をローカルシステムにプッシュします。

    chmod 777 localscript.sh
    cat > script1.sh <<- "ALL"
    #!/usr/bin/expect
    set password [lindex $argv 0];
    set ipaddress [lindex $argv 1];
    set timevalue [lindex $argv 2];
    set timeout $timevalue
    spawn /usr/bin/ssh username@$ipaddress /bin/bash < ./localscript.sh
    expect "assword:"
    send "$password\r"
    set timeout $timevalue
    spawn /usr/bin/scp username@$2:"/path/from/source/*" /path/to/destination/folder/
    expect "assword:"
    send "$password\r"
    interact
    ALL
    chmod 777 script1.sh
    ./script1.sh $password $2 $timevalue
    
  2. 別の Expect スクリプトを使用してリモートサーバーで必要なコマンドのリストを実行し、scp を使用して別のスクリプトのファイルをインポートします。

    cat > script1.sh <<- "ALL"
    #!/usr/bin/expect
    set password [lindex $argv 0];
    set ipaddress [lindex $argv 1];
    set timevalue [lindex $argv 2];
    set timeout $timevalue
    spawn /usr/bin/ssh username@$ipaddress /bin/bash < ./localscript.sh
    expect "assword:"
    send "$password\r"
    interact
    ALL
    cat > script2.sh <<- "ALL2"
    #!/usr/bin/expect
    set password [lindex $argv 0];
    set ipaddress [lindex $argv 1];
    set timevalue [lindex $argv 2];
    set timeout $timevalue
    spawn /usr/bin/scp username@ipaddress:"/path/from/source/*" /path/to/destination/folder/
    expect "assword:"
    send "$password\r"
    interact
    ALL2
    chmod 777 localscript.sh script1.sh script2.sh
    ./script1.sh  $password $2 $timevalue
    sleep 5
    ./script2.sh  $password $2 $timevalue
    

=========================

私は上記のコードがそれ自体ですべて有効でなければならないと思います。しかし、同じ出力は非常に予想外のようです。

  1. パスワードを入力すると、sshコマンドとscpコマンドはほぼ同時に実行されるため、localscriptにジョブを完了するのに十分な時間が与えられません。以下は私が見た出力です。

    spawn /usr/bin/ssh [email protected] /bin/bash < ./localscript.sh
    Warning private system unauthorized users will be prosecuted.
    [email protected]'s password: spawn /usr/bin/scp [email protected]:"/home/some/file/*" /another/file/
    Warning private system unauthorized users will be prosecuted.
    [email protected]'s password:
    scp: /home/some/file/*: No such file or directory
    

注:この機能は「期待」なしでうまく機能します。

  1. ここでは、sshとscpをそれぞれ実行しますが、localscript.shファイルの存在を認識していないようです。

    spawn /usr/bin/ssh [email protected] /bin/bash < ./localscript.sh
    Warning private system unauthorized users will be prosecuted.
    [email protected]'s password:
    bash: localscript.sh: No such file or directory
    Warning private system unauthorized users will be prosecuted.
    [email protected]'s password:
    scp: /home/some/file/*: No such file or directory
    

この問題に関するフィードバックをいただきありがとうございます。最初のアプローチは効果的な解決策かもしれませんが、スポーンが速すぎて「sleep」または「after」コマンドが機能しません。 2番目の方法も通じるようですが、Linuxで「expect」を使用するときに通常使用する方法とは異なり、リモートサーバーでローカルスクリプトを実行する方法があるようです。

ベストアンサー1

いくつかの注意:

  • Expect shebang 行が正しくありません。# #!/usr/bin/expectただそうしなければなりません。#!/usr/bin/expect
  • リモートホストにはsshを使用しますが、ローカルシステムを介してscpを使用します。これはあなたの意図ですか?
    • spawnそれ以外の場合は、2番目の項目に変更する必要がありますsend
    • 私はこれがscp "ファイルが見つかりません"エラーの原因だと思います。
  • $2代わりに使用$ipaddress
  • 生成されたプロセスと実際にやり取りしたくない場合は、プロセスが終了するのを待ちますexpect eofinteract
  • シェルスクリプトは「script1.sh」と「script2.sh」を生成しますが、「localscript.sh」は生成しません。
  • ".sh" は予想コードの説明拡張ではありません。 「.exp」が良いです。
  • すべてのシェル変数を引用します。./script1.sh "$password" "$2" "$timevalue"

私はこのように書きます。明らかにテストされていないようです。

#!/bin/bash
export password=$1
export ipaddress=$2
export timevalue=${3:--1}    # use default -1 if not specified\

[[ -z "$password" ]]  && { echo "Error: missing password";   exit 1; }
[[ -z "$ipaddress" ]] && { echo "Error: missing IP address"; exit 1; }

/usr/bin/expect -d <<END_EXPECT
    set timeout $env(timevalue)

    spawn sh -c "/usr/bin/ssh username@$env(ipaddress) /bin/bash < ./localscript.sh"
    expect "assword:"
    send "$env(password)\r"
    expect eof

    spawn /usr/bin/scp username@$env(ipaddress):"/path/from/source/*" /path/to/destination/folder/
    expect "assword:"
    send "$env(password)\r"
    expect eof
END_EXPECT

-d予想されるデバッグ出力をオンにするオプションを追加しました。もう必要ない場合は削除してください。

問題は、generateコマンドがシェルリダイレクトを実行する方法がわからないことです。 generate は "ssh", "user@host", "/bin/bash", "<" (リテラルより小さい) および " ./localhost.sh" 。ここでは、リダイレクトが正しく実行されるようにsshコマンドを明示的に実行するためにシェルを使用しています。

おすすめ記事