2013-04-03 81 views
0

我試圖SSH入服務器,並檢查是否存在id_rsa.pub。如果它不存在,我想運行ssh-keygen,否則我不想做任何事情。期望/ Bash:運行一個bash if語句預期

我可以運行簡單的命令,如「貓」或「RM」使用的Tcl /預計發送,但是當我嘗試做這樣的事情它不工作:

send "if [ ! -f $USER_SSH_PATH/id_rsa.pub ]; then CREATE_FILE=true; fi\r" 
expect "# " { } 

send "if $CREATE_FILE; then; ssh-keygen -t rsa -C $USER -f $USER_SSH_PATH/id_rsa\r" 
... 

我得到以下錯誤消息: #無效的命令名稱「!」 在執行 「!-f /root/.ssh/id_rsa.pub」 從內

是否可以調用運行這樣的命令嗎?

回答

4

你需要躲避方括號,因爲它是TCL語法的一部分:

send "if \[ ! -f $USER_SSH_PATH/id_rsa.pub \]; then CREATE_FILE=true; fi\r" 

在TCL,[]以同樣的方式在bash ``$()作品。所以,發生了什麼是執行send命令之前解釋第一個做的字符串替換,它認爲它需要兩樣東西來代替:

  1. $ USER_SSH_PATH被包含在該變量USER_SSH_PATH值替換

  2. [! ....]被調用!函數/命令的結果替換。正如你發現的那樣不存在。

請注意,在tcl中(並通過擴展expect)變量和函數名稱不限於字母數字。它是有效的有變量和函數的名稱,如$!甚至NULL字符(爲0的值的字節):

proc ! {} {puts "!"} 
proc "$" {} {puts "\$"} 
proc \0 {} {puts "NUL character"} 

! ;# this prints ! 
\$ ;# this prints $ 
\0 ;# this prints "NUL character" 

對TCL語法的詳細信息,請參閱http://www.tcl.tk/man/tcl/TclCmd/Tcl.htm

+0

這是實際處理問題的唯一答案。 –

+0

謝謝!這實際上是我需要的,你解決了我的問題!非常感謝! – user1777907

0

什麼在你的$USER_SSH_PATH?在本地和遠程機器上是否一樣,這意味着您擁有正確的權限......以下內容可幫助您進行調試。我只是想過

echo ${USER_SSH_PATH} 
ssh <hostname> " 
if [ ! -f ${USER_SSH_PATH}/id_rsa.pub ]; then 
    echo ${USER_SSH_PATH}; 
    echo \"File Not Found, Creating....\"; 
    ssh-key-gen -t rsa -C ${USER} -f ${USER_SSH_PATH}/id_rsa; 
else 
    echo \"File Found\"; 
    exit 1; 
fi 
" 
+0

$ USER_SSH_PATH實際上只是/root/.ssh,謝謝!我首先在服務器上以root身份登錄。儘管如此,我必須使用期望登錄,ssh-keygen不是第一次設置。 – user1777907

+0

我不知道你的評論是如何幫助的,我只是想要得到一個if語句與預期發送。 – user1777907

+0

我在這裏寫的行會在遠程服務器的'ssh'上執行'if語句',檢查'id_rsa.pub'。如果該文件不存在,它將執行你的'ssh-keygen'命令。我不明白你想用'send'實現什麼額外的功能? – iamauser

0

一種解決方案是運行|在發送「LS /root/.ssh/ grep的id_rsa.pub」,並期待在與期望的輸出。我很好奇,如果我可以運行bash命令但是。

要麼我會得到「id_rsa.pub」或空行。但是如果我有「id_rsa.pub *」,它會中斷。

任何人有一個想法,以改善這個請好嗎?謝謝!

1

正如slebetman已經指出的那樣,人物[]$\有內部"特殊的意義。

  • []用於命令subsitution,所以[expr {2+3}]將由5(結果)所取代。
  • $用於變量替換。
  • \用於特殊字符

您可以逃脫內"這些字符與\(與代碼點13字符像\r):我認爲$USER_SSH_PATH是本地(TCL)變量

send "if \[ ! -f $USER_SSH_PATH/id_rsa.pub \]; then CREATE_FILE=true; fi\r" 

或使用{}包圍你的字符串。
如果您使用{},則不會進行替換。這還包括\r將作爲\r發送到服務器,而不是作爲單個字符。

還有其他幾個選項來創建這樣的事情:

  • subst可以做到替換上的字符串。另外,也可以只有某些種取代的發生(使用-nocommands開關,以防止[]取代,-novariables$替代和-nobackslashes\
    實施例:

    send [subst -nocommands \ 
        {if [ ! -f $USER_SSH_PATH/id_rsa.pub ]; then CREATE_FILE=true; fi\r}] 
    
  • string map更換某些序列。

    send [string map [list {@@[email protected]@} \r {@@[email protected]@} $USER_SSH_PATH] \ 
        {if [ ! -f @@[email protected]@/id_rsa.pub ]; then CREATE_FILE=true; [email protected]@[email protected]@}] 
    

有很多方法可以做這樣的事情。

+0

謝謝!這有助於很多!謝謝。 – user1777907