在 expect 脚本中输入 sudo 密码
Enter sudo password while in expect script
我在 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
在执行 another_script.sh
期间,系统提示我输入 sudo 密码,但我无法输入,因为我还在等待。
我该怎么做才能让我能够输入 sudo 密码并让脚本在之后继续 运行?
我不想在脚本中保存密码然后传递给expect,但我希望能够输入它。
来自 man sudo
:sudoers 策略缓存凭据 15 分钟,除非在 sudoers(5) 中被覆盖。
这样,在调用 expect 之前调用 sudo -v
。它检查凭据,如果没有缓存,它会要求输入 root 密码。这样你就可以在 expect
之前输入它们,之后 sudo
命令不需要再次询问。
对于你的评论,我认为你在 cron 中有它。在这种情况下,您需要 运行 脚本作为 sudo。你可以在 sudo crontab 中调用它。您可以通过 运行ning sudo crontab -e
访问它
处理此类事件的标准方法是观察输入 sudo 密码的提示,提供它,然后继续。但是对于长 运行 脚本,您需要将密码 缓存在期望脚本 中,这样您就不必多次返回给用户几个小时的时间。事实上,为了可用性,您可能需要预先询问密码,而不是等到底层系统需要它。
幸运的是,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
Donal 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 上使用脚本,因此交互有问题,除非您使用 -u tty_spawn_id
使其与 /dev/tty
一起工作,并且用户。您需要在此 tty 上显式设置 echo on/off,因为 sudo 只会在生成的命令和 expect 之间的 pty 上完成它。
我在 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
在执行 another_script.sh
期间,系统提示我输入 sudo 密码,但我无法输入,因为我还在等待。
我该怎么做才能让我能够输入 sudo 密码并让脚本在之后继续 运行?
我不想在脚本中保存密码然后传递给expect,但我希望能够输入它。
来自 man sudo
:sudoers 策略缓存凭据 15 分钟,除非在 sudoers(5) 中被覆盖。
这样,在调用 expect 之前调用 sudo -v
。它检查凭据,如果没有缓存,它会要求输入 root 密码。这样你就可以在 expect
之前输入它们,之后 sudo
命令不需要再次询问。
对于你的评论,我认为你在 cron 中有它。在这种情况下,您需要 运行 脚本作为 sudo。你可以在 sudo crontab 中调用它。您可以通过 运行ning sudo crontab -e
处理此类事件的标准方法是观察输入 sudo 密码的提示,提供它,然后继续。但是对于长 运行 脚本,您需要将密码 缓存在期望脚本 中,这样您就不必多次返回给用户几个小时的时间。事实上,为了可用性,您可能需要预先询问密码,而不是等到底层系统需要它。
幸运的是,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
Donal 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 上使用脚本,因此交互有问题,除非您使用 -u tty_spawn_id
使其与 /dev/tty
一起工作,并且用户。您需要在此 tty 上显式设置 echo on/off,因为 sudo 只会在生成的命令和 expect 之间的 pty 上完成它。