在 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 上完成它。