2016-03-04 37 views
1

我想自動從的幫助數據庫備份預計:首先,腳本建立從遠程數據庫端口轉發端口使用SSH 本地機器。然後我使用數據庫實用程序來轉儲所有數據庫。期望具有可選ssh-agent密碼短語提示的腳本?

因此,我有以下期待腳本慶典腳本里面:

#!/bin/sh 

expect <<- DONE 
    set timeout -1 

    # port-forward remote database port 3306 to local port 3307 
    spawn ssh -M -S /var/run/examplecom-mysql-socket -fnNT -L 3307:localhost:3306 [email protected] 

    expect { 
    # conditional prompt appears in case ssh-agent is not active 
    "*.ssh/id_rsa':*" { 
     send -- "$SSH_PASSPHRASE\r" 
    } 
    # ?!?!?!? What to expect here in case ssh-agent is active, therefore no password needed, and therefore no prompt appears? 
    } 

    # dump remote database by connecting to forwarded port 
    spawn mysqldump --all-databases --user=root --password --protocol=TCP --host=localhost --port=3307 --verbose --result-file=${DB_DUMP_FILE} 

    expect { 
    # prompt appears for database password 
    "*?asswor?:*" { 
    send -- "$PASSWORD_MYSQL_ROOT\r"  
    } 
    } 

    expect eof 
DONE 

此腳本可能兩種情況中運行:

  • 要麼的ssh-agent目前不活躍。在這種情況下,產生了SSH過程中會提示Enter passphrase for key '${HOME}/.ssh/id_rsa':,其中第一期望規則愉快地匹配,並且正確地發送SSH密碼。
  • 或者的ssh-agent是當前活動。在這種情況下,產生的ssh進程靜默地建立端口轉發,並且不需要或提示輸入SSH密碼。

我努力讓這兩種情況下,我希望劇本的工作。特別是,我不知道如何修改腳本,以使「silent」active-ssh-agent是「預期的」,因此期望腳本可以繼續啓動數據庫轉儲。

我試過預期多的東西方法(在上面?!?!?!?評論位置)的嘗試:

  • 期待一個換行符,
  • 期待我的shell提示下,
  • 期待eof

但沒有奏效。我發現類似的問題和建議的解決方案圍繞StackExchange: * How to use expect with optional prompts? * https://superuser.com/q/412259/137881 * TCL/Expect Scripting - Using a conditional statement to attempt a secondary login password

但solutinos似乎導致代碼重複:每個條件提示手段複製和粘貼腳本的其餘部分,這使得腳本得到每個ssh語句的嵌套條件提示會迅速進行復雜化。

我怎麼能有期望在正常情況下工作其中SSH不提示,因爲活躍的ssh-agent的口令/密碼?

回答

1

是啊,這是一個有趣的一個。由於您使用的是ssh -N,因此您不需要在遠程主機上啓動任何進程,並且ssh會話就在那裏。你只需要睡幾秒鐘,並希望隧道建立。

set timeout 2 
spawn ssh -M -S /var/run/examplecom-mysql-socket -fnNT -L 3307:localhost:3306 [email protected] 

expect { 
    # conditional prompt appears in case ssh-agent is not active 
    "*.ssh/id_rsa':*" { send -- "$SSH_PASSPHRASE\r" } 
    # wait until the timeout, then carry on with the rest of the script 
    timeout 
} 

set timeout -1 
# ... 

或者,刪除-N,那麼您可以期望看到遠程主機上的提示。

spawn ssh -M -S /var/run/examplecom-mysql-socket -fnT -L 3307:localhost:3306 [email protected] 
# ..........................................^^^^ 

expect { 
    # conditional prompt appears in case ssh-agent is not active 
    "*.ssh/id_rsa':*" { send -- "$SSH_PASSPHRASE\r" } 
    # I assume your prompt ends with a dollar sign and a space 
    -re {\$ $} 
} 

現在可以產卵mysql命令,並與互動。

+0

太棒了!你的'超時'建議訣竅。 2016-03-04的回答版本依賴於端口轉發將在超時之前建立的假設。如果{[file exists/var/run/examplecom-mysql-socket]} { send_user「文件存在...繼續\ r」 } else { send_user「文件不存在,這意味着ssh端口無法建立。退出腳本\ r」 exit 2 }',因此退出以防萬一套接字(文件)'/ var/run/examplecom-mysql-socket'沒有建立。 – Abdull