2016-12-15 122 views
2

我意識到類似的問題已經被問過,我看着他們,嘗試運用我所學到的並具有以下腳本:嵌入bash腳本內的期望

#!/bin/bash 

if [ `hostname` = 'EXAMPLE' ] 
then 

/usr/bin/expect << EOD 

spawn scp -rp host:~/outfiles/ /home/USERNAME/outfiles/ 
expect "id_rsa':" 
send "PASSWORD\r" 
interact 

spawn scp -rp host:~/errfiles/ /home/USERNAME/errfiles/ 
expect "id_rsa':" 
send "PASSWORD\r" 
interact 

expect eof 

EOD 

echo 'Successful download' 
fi 

不幸的是,似乎沒有工作和我得到一個錯誤消息:

spawn scp -rp host:~/outfiles/ /home/USERNAME/outfiles/ 
Enter passphrase for key '/home/USERNAME/.ssh/id_rsa': interact: spawn id exp0 not open 
    while executing 
"interact" 

我不知道這是什麼意思,爲什麼它不工作。但是,當我使用非嵌入期望腳本編寫上述代碼時:

#!/usr/bin/expect 

spawn scp -rp host:~/outfiles/ /home/USERNAME/outfiles/ 
expect "id_rsa':" 
send "PASSWORD\r" 
interact 

spawn scp -rp host:~/errfiles/ /home/USERNAME/errfiles/ 
expect "id_rsa':" 
send "PASSWORD\r" 
interact 

它的工作沒有任何問題。那麼我做錯了什麼?

注意:通常當有人發佈關於使用expect來使用scpssh的問題時,給出的答案是使用rsa密鑰。我試過了,不幸的是,在我的一臺電腦上有一些侏儒密鑰環,這意味着我無法從rsa-key中刪除我的密碼,這正是我試圖用if編寫上述腳本的原因聲明。所以請不要告訴我使用rsa密鑰。

+1

如果您希望完全**執行**定界符之間的文本(在解釋之前沒有變量或特殊字符擴展),則必須引用您的here-doc定界符,如下所示: '/ usr/bin/expect <<「EOD」... EOD「。 [這個問題](http://stackoverflow.com/questions/4937792/using-variables-inside-a-bash-heredoc)是相似的,它有相同的問題,但反過來。 – Aserre

+0

我只是試過'/ usr/bin/expect <<「EOD」'但它仍然給出錯誤'spawn scp -rp host:〜/ outfiles // home/USERNAME/outfiles/ 輸入密鑰'/ home /USERNAME/.ssh/id_rsa':interact:spawn id exp0未打開 執行中 「interact」 成功下載 ' –

回答

3

你的bash腳本在標準輸入expect上傳遞expect命令。這就是here-document<<EOD所做的。然而,expect ...希望其命令在文件中提供,或根據man page作爲-c的參數提供。下面有三個選項。買者自負;沒有經過測試。

  1. Process substitution與這裏文檔:

    expect <(cat <<'EOD' 
    spawn ... (your script here) 
    EOD 
    ) 
    

    EOD結束這裏的文檔,然後整個事情被包裹在一個<()進程替換塊。結果是expect將會看到一個臨時文件名,其中包含您的here-document的內容。

    正如@Aserre指出的那樣,<<'EOD'中的引號表示您的here-document中的所有內容都將按照字面意思處理。如果這是你想要的,把它們放在腳本內部展開bash變量等。

  2. 編輯變+ here文檔:

    IFS= read -r -d '' expect_commands <<'EOD' 
    spawn ... (your script here) 
    interact 
    EOD 
    
    expect -c "${expect_commands// 
    /;}" 
    

    是的,這是//後一個真正的換行符 - 這不是明顯,我怎麼逃生呢。這將換行符變成分號,man page說是必需的。

    感謝this answerread + heredoc組合。

  3. 殼牌可變

    expect_commands=' 
    spawn ... (your script here) 
    interact' 
    expect -c "${expect_commands// 
    /;}" 
    

    注意的是,在期望命令任何'(例如,id_rsa之後)將需要與'\''替換離開單引號塊中,添加一個字面撇號,然後重新輸入單引號區塊。 //之後的換行符與之前的選項相同。

+0

感謝您的幫助,我使用了示例1並且它工作正常。我很感激。 –