Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ssh 在不超时的情况下退出expect{}_Ssh_Scripting_Expect - Fatal编程技术网

Ssh 在不超时的情况下退出expect{}

Ssh 在不超时的情况下退出expect{},ssh,scripting,expect,Ssh,Scripting,Expect,我正在努力解决在ssh中自动键入密码之类的经典问题 其他人我都在黑暗中跌跌撞撞。最后,我拼凑了一个脚本,这是一种工作: #!/usr/bin/expect -f # command line args set user_at_host [lrange $argv 0 0] set password [lrange $argv 1 1] set timeout 1 # ssh command spawn ssh -S ~/.ssh/tmp.$user_at_host -M -N -f $us

我正在努力解决在ssh中自动键入密码之类的经典问题 其他人我都在黑暗中跌跌撞撞。最后,我拼凑了一个脚本,这是一种工作:

#!/usr/bin/expect -f

# command line args
set user_at_host [lrange $argv 0 0]
set password [lrange $argv 1 1]

set timeout 1

# ssh command
spawn ssh -S ~/.ssh/tmp.$user_at_host -M -N -f $user_at_host

# deal with ssh prompts
expect {
    "*yes/no*" { send "yes\r" ; exp_continue }
    "*assword:" { send "$password\r" ; exp_continue }
}
此脚本仅因
超时1
行而终止,如果没有它,它将挂起,并且仅通过用户交互(
^C
)终止

spawn
行是一个直接的ssh命令时,脚本立即终止,但是这是错误的。可能不同的是
-f
选项使其在后台运行(但我尝试了没有脚本的脚本,但没有结果)

我读到,
interactive
expect eof
可能会有帮助,但我无法找到正确的咒语

我的问题(我想)是如何让产生后台进程的expect脚本在没有超时的情况下终止


编辑:我应该预料到(没有双关语)会出现“使用无密码ssh身份验证”的答案。虽然这是一个合理的建议,但在我的场景中它不是合适的解决方案:在受信任的环境中自动测试普通安装的系统,在这种环境中,向映像添加受信任的密钥是不可取/不可能的。

此循环:

expect {
    "*yes/no*" { send "yes\r" ; exp_continue }
    "*assword:" { send "${password}\r" ; exp_continue }
}
除超时或EOF外,不能以任何方式终止;两条匹配的行将
exp\u继续
,因此再次循环

进入背景意味着基本上是分叉;父节点死亡,子节点继续连接

就我个人而言,我会以不同的方式解决交互元素:

  • 主机密钥:手动连接一次,或者直接将密钥插入ssh known_hosts文件
  • 密码:我会使用私钥/公钥身份验证。可以使用代理存储密钥,也可以使用无密码密钥
  • 您可能想要:

    expect {
        "*yes/no*" { send "yes\r" ; exp_continue }
        "*assword:" { send "${password}\r" }
    }
    expect $the_prompt
    send "exit\r"
    expect eof
    
    更新

    我没有注意到您正在通过ssh发送命令。我想你所需要的就是:

    spawn ssh a@b foo bar baz
    expect {
        "*yes/no*" { send "yes\r" ; exp_continue }
        "*assword:" { send "${password}\r" }
        eof
    }
    

    foo
    命令完成时,您会点击
    eof

    好的,所以我找到了一个似乎有效的排列--

    首先,我需要一个
    包装器
    脚本,它将在完成时给出指示:

    #!/bin/bash
    "$@"
    echo "done"
    
    然后expect脚本变为:

    #!/usr/bin/expect -f
    set user_at_host [lrange $argv 0 0]
    set password [lrange $argv 1 1]
    
    # no need for timeout 1
    set timeout 60
    
    # use the wrapper
    spawn wrapper ssh -S ~/.ssh/tmp.$user_at_host -M -N -f $user_at_host
    
    expect {
       "*yes/no*" { send "yes\r" ; exp_continue }
       "*assword:" { send "$password\r" ; exp_continue }
       # use the wrapper
       "done" { exit }
    }
    

    感谢道格拉斯·利德(投赞成票)和格伦·杰克曼(投赞成票)的有益建议。我将很乐意不接受这个答案,并接受任何更优雅的答案,也许是一个废除包装器脚本的答案

    谢谢大家的关注。

    我这样做:

    set user "****"    
    set host "127.0.0.1"    
    spawn shh $user@$host    
    expect "password: "    
    send "**??54"    
    expect "$"    
    interact
    

    (这回答了您如何使用交互方法)

    有没有办法在
    *密码:
    之后立即退出?当我尝试用其他任何东西替换
    exp\u continue
    时,它确实立即退出,但似乎没有
    发送
    ${password}
    。可能是
    睡眠1
    期望eof
    等待
    ?抱歉,我在犹豫,也许你可以帮我减少我必须测试的排列数:
    等待eof
    /
    睡眠1
    是否在
    期望{…}
    循环的内部或外部?我会删除密码exp_continue语句。然后试着在expect小组之后加入sleep或其他小组。谢谢你的帮助。你的建议为我的解决方案提供了一些重要的线索。这并没有解决我的问题,但给了我一个重要的线索:完成后我需要某种提示。看看我自己的答案。谢谢