6

我有一个脚本,必须在多个主机上执行“sudo”操作。我试图让期望工作,所以我只需要输入一次,并且遇到了几个问题。

首先,几个例子建议使用:

/usr/bin/expect <<EOD
spawn ssh -t $host /usr/bin/sudo -v
expect "Password:"
send "$SUDOPASS\n"
EOD

但是,一旦我输入第二个“<”,所有的引用都会被搞砸,我的脚本将以文件意外结束而终止。这真的很奇怪,因为我使用与 cat 相同的机制在其他脚本中写出文件。

其他例子表明:

/usr/bin/expect -c "
spawn ssh -t $host /usr/bin/sudo -v
expect "Password:"
send "$SUDOPASS\n"
"

这样做(并添加 -d 以期望),我得到关于 no tty 的错误和重复我的密码,并在末尾附加一个 'n',所以它没有发送换行符(我试过 '\ r' 也是如此),但似乎正在转义 'n'

由于我找到的大多数示例都来自 Linux,我希望(哈哈,双关语不是故意的!)他们使用的是 GNU 预期,而我使用的是 BSD 预期。我正在阅读手册页,但是“spawn”这个词出现了很多次,我可能需要很长时间才能偶然发现正确的实例。

这是一个似乎最接近工作的结果:

flamingo:~ jnojr$ Scripts/getinfo_expect.sh 
Assuming you have one 'sudo' password for all of your hosts, enter it now: 
expect version 5.45
spawn /usr/bin/ssh -t macbook /usr/bin/sudo -v
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {67358}

expect: does "" (spawn_id exp7) match glob pattern "Password:"? no
Password:
expect: does "Password:" (spawn_id exp7) match glob pattern "Password:"? yes
expect: set expect_out(0,string) "Password:"
expect: set expect_out(spawn_id) "exp7"
expect: set expect_out(buffer) "Password:"
send: sending "password\n" to { exp7 }
argv[0] = /usr/bin/expect  argv[1] = -d  argv[2] = -c  argv[3] = 
    spawn /usr/bin/ssh -t macbook /usr/bin/sudo -v
    expect Password: { send password\n }  
set argc 0
set argv0 "/usr/bin/expect"
set argv ""
sudo: no tty present and no askpass program specified[/CODE]

那就是将 '\n' 留在引号之外,如

send "$SUDOPASS"\n

它似乎大部分都在工作,除了跳过 ssh 的“-t”选项

4

1 回答 1

6

我赞同@BrianCain 的评论,即无密码sshw/sudo将是一个更好的解决方案。也就是说,让我们尝试帮助您的expect脚本,您可以决定它是否仍然令人头疼。

我相信您在expect -f -使用bash“此处字符串”( <<) 将脚本输入到expect. 所以:

/usr/bin/expect -f - <<EOD
spawn ssh -t $host /usr/bin/sudo -v
expect "Password:"
send "$SUDOPASS\n"
EOD
于 2013-02-26T20:12:03.500 回答