在 script.sh 中使用 sudo 调用 init.d 中的 init 文件时出现错误 sudo:没有 tty present 并且没有指定 askpass 程序

在 script.sh 中使用 sudo 调用 init.d 中的 init 文件时出现错误 sudo:没有 tty present 并且没有指定 askpass 程序

我正在尝试编写一个在启动时启动的脚本来连接到我的个人 VPN。

我有一个初始化文件:/etc/init.d/vpnstartup

它在启动时使用以下命令调用我的 vpnon.sh 脚本:

case "$1" in
    start)
        su username -c $VPN_DIR/vpnon.sh
        ;;

在我的脚本 vpnon.sh 中有一些需要 root 权限才能执行的命令:

sudo iptables -A INPUT -i pptp -j ACCEPT
sudo iptables -A OUTPUT -o pptp -j ACCEPT

当我使用 ./vpnstartup start 调用我的 init 文件时,我使用 chmod 775 授予 vpnstartup init 文件和 vpnon.sh 脚本的权限

调用 sudo iptables 命令时出现以下错误

sudo: no tty present and no askpass program specified
sudo: no tty present and no askpass program specified

我认为发生的情况是 sudo 命令需要输入密码但无法获取密码。

我发现的唯一解决方案是将其添加NOPASSWD :ALL option 到我的用户名下的 sudoers 文件中。

如果有更好的解决方案,出于安全原因我不想使用此方法。

如果您能帮助我解决这个问题,请告诉我;我在这个问题上花了很多时间。

答案1

我认为这里的关键因素是,由于脚本是用 sudo 运行的,因此它可以执行 root 可以执行的所有操作。问题是该脚本中的其他 sudo 命令不一定继承 root 权限,而是以控制用户的身份执行。这通常会导致您在 sudo 中看到的错误,即使父脚本本身可以通过 sudo 允许,但子命令不允许。

发生的情况是,该脚本中的嵌套 sudo 调用失败,因为 sudo 通常会提示输入密码,但没有控制 shell,所以无法输入。这会产生sudo: no tty present and no askpass program specified您看到的略显模糊的错误。

一个简单的说明方法是,如果像您的示例一样,init 脚本包含使用 sudo 的内部调用。运行:

sudo /etc/init.d/startvpn

如果您自己的用户没有对所有 sudo 调用的 sudo 权限,则可能会失败,并可能会给您 sudo tty 错误。但是,像这样运行它:

sudo sh /etc/init.d/startvpn

可能会有效。在后一种情况下,sudo sh以 root 身份创建一个命令 shell,因此在该 shell 中运行的任何东西实际上都是以 root 身份执行的。Root 通常具有不受限制的 sudo 权限,因此命令是否使用 sudo 运行不再重要。

值得一提的是:

  • 正如其他人指出的那样,大多数此类混乱情况都可以通过不在脚本中使用 sudo 来避免。通常,使用 sudo 运行时失败的子命令可以在没有 sudo 的情况下正常运行(当父脚本使用 sudo 运行时)。
  • 虽然使用运行脚本sudo sh可能会解决问题,但这样做同样存在安全隐患。考虑到 sudo 的行为方式是健全性检查,以确保脚本的内容不会执行不该执行的操作,即使脚本本身是允许的。
  • 如果您以 sudo 身份运行的用户也拥有足够的综合权限,您可能不会看到任何这些问题。但这些问题可能会在以后出现,例如,如果您使用自己的特权帐户开发脚本,并且在生产中以非特权服务帐户运行它。
  • 一般来说,你应该避免向用户账户授予广泛的 sudo 权限来解决此类问题。如果确实需要,请将账户访问规则限制为该用户和该特定命令。

答案2

我找到了解决问题的方法。

我删除了 vpnon.sh 脚本中的所有单独的 sudo 命令,并从脚本外部传入了 sudo。

在我的 /etc/init.d/vpnstartup 文件中,我将其更改su username -csudo $VPN_DIR/vpnon.sh 现在的样子:

case "$1" in
    start)
        sudo $VPN_DIR/vpnon.sh
        ;;

然后呼叫sudo update-rc.d vpnstartup defaults ,现在 VPN 在启动时连接!:)

相关内容