2017-08-02 2 views
0

を私は次のようにはbashから期待スクリプトを呼び出すようにしようとしています:expectScriptを行う必要がある何は期待 - ローカルファイルへのリモートコマンドの直接出力

#!/bin/bash 

mkfifo foobar 
expectScript > foobar & 
# other stuff that does stuff with foobar 

は、リモートホストにssh接続することです。そこから別のリモートホストにsshする必要があります。次に、ユーザーをrootに切り替える必要があります(rootログインは許可されません)。最終的にfoobarに書き込む必要があるコマンド(tail -f/var/log/messagesなど)を発行する必要があります。 foob​​arには他に何も書き込むことができません。パスワードプロンプトまたはコマンドプロンプト。コマンドの出力のみがfoobarに書き込まれます。私は、スクリプトのログイン部分がうまく動作している。私が苦労しているのは、出力がfoobarに書き込まれ、SIGINTがコマンドを強制終了するようにする方法です。ここで

は私が持っているものです。

#!/usr/bin/expect -- 

set HOST1_USER myuser 
set HOST2_USER myotheruser 
set HOST1_PASSWORD mypassword 
set HOST2_PASSWORD myotherpassword 
set ROOT_PASSWORD anotherpassword 
set HOST1 192.168.0.5 
# HOST2 is only reachable from HOST1 
set HOST2 192.168.1.12 

global until_interrupt 
set until_interrupt 0 

set HOST1_PROMPT "CL-\\d.*#" 
set HOST2_PROMPT "\\\$ $" 
set ROOT_PROMPT "# $" 

log_user 0 

spawn ssh [email protected]$HOST1 
# ssh keys are exchanged with HOST1, so there is no need for password here 
    expect -re "$HOST1_PROMPT" { 
      send "ssh [email protected]$HOST2\n" 
      expect { 
        -re ".*ssword.*" { send "$HOST2_PASSWORD\n" } 
        -re ".*Are you sure you want to continue connecting.*" {send "yes\n"; exp_continue} 
      } 
    } 

    expect -re "$HOST2_PROMPT" { send "su\n" } 
    expect -re ".*ssword.*" { send "ROOT_PASSWORD\n" } 

    log_user 1 
    # nothing up to this point should have been sent to stdout 
    # now I want the output of the tail command to be sent to stdout 

    expect -re "$ROOT_PROMPT" { send "tail -f /var/log/messages\n" } 

    # I want to wait here until SIGINT is sent. There may be a better way than the traps below. 
    # Set a trap to watch for SIGINT 
    trap { 
      set until_interrupt sigint_detected 
    } SIGINT 

    while { $until_interrupt == 0 } { 
      #wait until sigint 
    } 

    send "\003" 
    # I think that is SIGINT, and that I'm sending it because I caught the first one in the trap. 

    trap { 
      exit 
    } SIGINT 

    set timeout 30 

    expect -re "$ROOT_PROMPT" { send "exit\n" } 
    expect -re "$HOST2_PROMPT" { send "exit\n" } 
    expect -re "$HOST1_PROMPT" { send "exit\n" } 
    # Fully exited 
+0

この 'expect'スクリプトのほとんどは、公開鍵認証と' ssh'に組み込まれているトンネリングサポートを使用するだけで削除できます。 – chepner

+0

HOST2ではrootとしてコマンドを実行する必要があり(sudoは動作しません)、HOST2はssh経由でrootにログインすることができないため、chepnerに感謝します。 root以外のユーザーとしてログインし、rootにsuを実行する必要があります。私は、公開鍵認証が動作するホスト上でこのソリューションを実装しました。これははるかに簡単です。しかし、この特定のサーバーでは、どのように動作するのかわかりません。 –

+0

もしあなたがrootのパスワードを持っていれば、* sudoが動作するよう*設定することができます。そして、ローカルの 'ssh'設定ファイルに正しいユーザーIDとホスト名を設定できないことは何もありません。 – chepner

答えて

0

あなたがリモート(またはあなたのtail -fコマンドによって生成されていないいくつかの他の文字列)に送信制御文字のエコーをexpectを使用することができるはずです。私はnullにSTDINをリダイレクト、これを実行すると、シェルのバックグラウンドで、私はCtrlキーを押しながらCを入力することができます

#!/usr/bin/expect -d 
log_user 0 
spawn ssh localhost 
expect " $ " 
send "tail -f /var/log/messages\n" 
log_user 1 
trap { send "\003" } SIGINT 
set timeout -1 
expect "\003" 
expect "$ " 
send "date\r" 
expect "$ " 

、それはきれいに終了します。たとえば、この単純なssh例は、(-dはデバッグ用です)私の作品。

./prog </dev/null >/tmp/out & 
関連する問題