2013-04-03 48 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