2017-08-02 227 views
0

我想打電話從慶典的期待腳本方式如下:期待 - 遠程命令的直接輸出到本地文件

#!/bin/bash 

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

什麼expectScript需要做的是ssh到遠程主機。從那裏它需要ssh到另一個遠程主機。然後它需要將用戶切換到根(不允許root登錄)。然後它需要發出一個最終需要寫入foobar的命令(例如tail -f/var/log/messages)。沒有其他信息可以寫入foobar,例如密碼提示或命令提示符。只有命令的輸出可以寫入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

謝謝chepner,但沒有太多可以消除,因爲在HOST2上我需要以root用戶身份運行命令(sudo無法運行),並且HOST2不允許root通過ssh登錄。所以有必要首先以非root用戶身份登錄,然後su登錄到root用戶。我已經在公鑰認證工作的主機上實現了該解決方案,並且更容易。但對於這個特定的服務器,我不明白它是如何工作的。 –

+0

如果你有root密碼,你可以*配置*'sudo'工作。而且沒有什麼能夠阻止你在你本地的'ssh'配置文件中設置正確的用戶ID和主機名。 – chepner

回答

0

您應該能夠使用的控制字符發送到遠程回聲的expect(或不被你的tail -f命令產生了一些其他的字符串) 。比如這個簡單的ssh例子對我的作品(該-d是調試):

#!/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 "$ " 

如果我運行此,重定向標準輸入爲空,在shell我可以按下Ctrl-C的背景和它結束乾淨。

./prog </dev/null >/tmp/out &