Expect / Bash:在expect中运行bash if语句

时间:2013-04-03 00:23:27

标签: bash scripting tcl expect

我正在尝试ssh到服务器,并检查id_rsa.pub是否存在。如果它不存在,我想运行ssh-keygen,否则我不想做任何事情。

我可以使用Tcl / Expect中的send来运行像“cat”或“rm”这样的命令,但是当我尝试做这样的事情时它不起作用:

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"
...

我收到以下错误消息:     #valid命令名“!”         执行时     “!-f /root/.ssh/id_rsa.pub”         从

中调用

是否可以运行这样的命令?

4 个答案:

答案 0 :(得分:4)

你需要转义方括号,因为它是tcl语法的一部分:

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

在tcl中,[]的工作方式与b ``$()的工作方式相同。所以发生的事情是,在执行send命令之前,解释器首先对字符串进行替换,并且它会看到需要替换的两件事:

  1. $ USER_SSH_PATH将替换为变量USER_SSH_PATH中包含的值

  2. [! ....]被调用!函数/命令的结果替换。您发现的不存在。

  3. 请注意,在tcl(并且通过扩展期望)中,变量和函数名称不限于字母数字。拥有$!等变量和函数名称,甚至是NUL字符(值为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

答案 1 :(得分:1)

正如slebetman已经指出的那样,[]$\中的字符在"中具有特殊含义。

  • []用于命令替换,因此[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作为-nocommands发送到服务器,而不是单个字符。

还有一些其他选项可以创建这样的东西:

  • subst可以对字符串进行替换。也可能只发生某些类型的替换(使用[]开关来阻止-novariables替换,使用$进行-nobackslashes替换,\进行send [subst -nocommands \ {if [ ! -f $USER_SSH_PATH/id_rsa.pub ]; then CREATE_FILE=true; fi\r}] {1}})
    例如:

    send [string map [list {@@r@@} \r {@@USER_SSH_PATH@@} $USER_SSH_PATH] \
       {if [ ! -f @@USER_SSH_PATH@@/id_rsa.pub ]; then CREATE_FILE=true; fi@@r@@}]
    
  • string map替换某些序列 实施例

    {{1}}

有很多方法可以做这些事情。

答案 2 :(得分: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
"

答案 3 :(得分:0)

我刚想到的一个解决方案是在发送中运行“ls /root/.ssh/ | grep id_rsa.pub”并使用expect查看输出。我很好奇我如何在命令中运行bash。

我要么得到“id_rsa.pub”作为回报,要么是空行。但如果我有“id_rsa.pub *”,它就会破裂。

有人有想法改善这个吗?谢谢!