Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.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
Bash 在expect脚本中输入sudo密码_Bash_Tcl_Expect - Fatal编程技术网

Bash 在expect脚本中输入sudo密码

Bash 在expect脚本中输入sudo密码,bash,tcl,expect,Bash,Tcl,Expect,我在bash脚本中有一个expect代码,类似这样 env input1=${INPUT1} input2=${INPUT2} expect << "EOS" set timeout -1 spawn ./another_script.sh expect { "Input 1" { send -- "$env(input1)\r";exp_continue } "Input 2" { send -- "$env(input2)\

我在bash脚本中有一个expect代码,类似这样

env input1=${INPUT1} input2=${INPUT2} expect << "EOS"
    set timeout -1
    spawn ./another_script.sh
    expect {
        "Input 1" { send -- "$env(input1)\r";exp_continue }
        "Input 2" { send -- "$env(input2)\r";exp_continue }
        eof
    }
EOS

env-input1=${input1}input2=${input2}expect自
man-sudo
:除非在sudoers(5)中被重写,否则sudoers策略会将凭据缓存15分钟


这样,在调用expect之前先调用
sudo-v
。它会检查凭据,如果没有缓存,它会询问根密码。这样,您就可以在
expect
之前输入它们,以后
sudo
命令无需再次询问。

关于您的评论,我认为您在cron中有它。在这种情况下,您需要以sudo的身份运行脚本。你可以在sudo crontab中调用它。您可以通过运行
sudo crontab-e

来访问它。处理此类事件的标准方法是观察sudo密码提示,提供它,然后继续。但是对于长时间运行的脚本,您将希望在expect脚本中缓存密码,这样您就不必在几个小时内多次返回到用户那里。事实上,对于可用性,您可能需要提前询问密码,而不是等到底层系统需要密码

幸运的是,expect包含对stty的支持,因此添加起来很容易

env input1=${INPUT1} input2=${INPUT2} expect << "EOS"
    # Prompt for password, cribbed/converted from example on expect(1) manpage
    stty -echo
    send_tty "sudo password: "
    expect_tty -re "(.*)\n"
    send_tty "\n"
    set password $expect_out(1,string)
    stty echo

    # Rest of the script, with clause for sending the password at the right time
    set timeout -1
    spawn ./another_script.sh
    expect {
        "Input 1" { send -- "$env(input1)\r"; exp_continue }
        "Input 2" { send -- "$env(input2)\r"; exp_continue }
        "assword: " { send -- "$password\r"; exp_continue }
        eof
    }
EOS

env input1=${input1}input2=${input2}expectDonal Fellows的答案是正确的,但为了完整性,这里是您尝试的
interact
解决方案。要使用的命令是

expect {
    "Input 1" { send -- "$env(input1)\r"; exp_continue }
    "Input 2" { send -- "$env(input2)\r"; exp_continue }
    "password for" { stty -echo
                    interact -u tty_spawn_id -o "\r" return
                    stty echo
                    exp_continue }
    eof
}

您遇到的问题是,您正在使用stdin上的脚本运行expect,因此,除非您使用
-u tty\u spawn\u id
使其与
/dev/tty
和用户一起工作,否则interact会出现问题。您需要在这个tty上显式地设置echo on/off,因为sudo只会在生成的命令和expect之间的pty上进行设置。

让用户以交互方式控制expect
interact
功能就是为了这个。我找不到使用
interact
的好例子。我尝试了类似于“{interact-o”\r“return;exp\u continue}
”的密码,但一个问题是我键入的内容是可见的,另一个问题是,在我按下ENTER键后,什么也没有发生,脚本无法继续工作。如果你想让
专家期待
的话,我可能需要一个
tcl
标签。(
expect
是TCL语言的一个扩展,不是bash的一部分;因为您的问题与如何从bash启动expect无关,而与启动后它的行为有关,这不是bash的问题。)
另一个_脚本.sh
将执行几个小时,所以缓存的凭据在此期间超时。@adamm您可以为
NOPASSWD
访问向
/etc/sudoers
添加相关命令吗?我不能这样做。在cron中运行时,您绝对不能与用户交谈,而必须从其他地方获取凭据。在所有选项中,从文件中读取是最好的选择之一。或者您可以简单地将脚本放在root的crontab中,而不需要任何凭据……谢谢您的评论。我尝试了您的建议,但我发现执行“发送用户”\n“
时出现以下错误:sudo password:send:spawn id exp0未打开。
您提到我可以监视提示,提供它,然后继续。我该怎么做?我想这就是原始问题的答案,可能是将expect脚本包装到bash脚本中的方式(我刚刚从您那里复制)。我仍然不知道为什么编写expect脚本的人喜欢这样做。这是因为我不想为expect脚本再增加一个文件。我有一个很大的bash脚本,我希望其中有一些提示(输入1和输入2)
Expect
似乎是解决这个问题的方法,所以我只是将Expect“嵌入”到bash脚本中。@adamm我想我已经通过将
send\u user
Expect\u user
分别更改为
send\u tty
Expect\u tty
解决了这个问题。我认为stty不需要更改。它现在可以工作了。这不是我一直在寻找的问题,但它是非常有用的。