2015-12-21 70 views
1

为什么这个期望的脚本不断产生ssh命令,从不打印“进入睡眠”或者“离开睡眠”,并且从不睡觉?为什么不这样期待句柄超时或者eof

我的意图是尝试ssh'ing,如果它看到“password:”以退出while循环(更多代码在这里看不到会包含交互)。如果3秒钟过去,或ssh在此之前死亡,它会应该放3秒睡,再放,然后再试ssh。

主机名“doesntexist”用于强制失败,例如名称或服务未知。

#!/usr/bin/expect -f 

set readyForPassword 0 
while { $readyForPassword == 0 } { 
    spawn ssh [email protected] 
    expect -timeout 3 { 
     "password: " { 
     set readyForPassword 1 
     } timeout { 
     puts "going to sleep" 
     sleep 3 
     puts "out of sleep" 
     } eof { 
     puts "going to sleep" 
     sleep 3 
     puts "out of sleep" 
     } 
    } 
} 
+0

呵呵。如果我删除了{在期望行结束时(及其底部附近的大括号)并使期望行为'expect -timeout 3“密码:”{“然后它按预期工作。探索Expect说,你可以按照我原来的方式来支撑它,至少在p76我想。期望改变吗?我误解别的东西了吗? – user1902689

回答

3

当使用-timeout标志,应当先于Expect的图案,不执行的操作。

通过调试,我们可以发现,该模式所采取Expect与您现有的代码,

expect: does "" (spawn_id exp6) match glob pattern "\n  "password: " {\n   set readyForPassword 1\n  } timeout {\n   puts "going to sleep"\n   sleep 3\n   puts "out of sleep"\n  } eof {\n   puts "going to sleep"\n   sleep 3\n   puts "out of sleep"\n  }\n "? no 

Exploring Expect书的第76页,我们可以看到下面的语句,

初始打开大括号会导致Tcl继续扫描其他 行以完成该命令。一旦匹配的括号中发现,外括号之间的模式和操作的所有 传递给 期待作为参数

出了什么问题呢?

-timeout不是一个动作,而只是一个标志。预期假设如下的模式

"password: " { 
     set readyForPassword 1 
     } timeout { 
     puts "going to sleep" 
     sleep 3 
     puts "out of sleep" 
     } eof { 
     puts "going to sleep" 
     sleep 3 
     puts "out of sleep" 
     } 

记住,Expect不强制行动,只有模式,即好像我们只喜欢图案被赋予它会采取行动,但没有应采取的行动。

简单地说,你的代码是等同

expect "Hello"; # Either 'timeout' or pattern can be matched. But, no action at all 

您的代码应该被重新安排为,

#!/usr/bin/expect -d 
set readyForPassword 0 
while { $readyForPassword == 0 } { 
    spawn ssh [email protected] 
    expect { 
     -timeout 3 "password: " {set readyForPassword 1} 
     timeout { 
       puts "going to sleep in timeout" 
       sleep 3 
       puts "out of sleep in timeout" 
     } eof { 
       puts "going to sleep in eof" 
       sleep 3 
       puts "out of sleep in eof" 
     } 
    } 
}