Bash:如何在不干扰“读取”的情况下在后台运行“sudo -n true”?

Ros*_*hur 7 bash sudo read

我有一个长时间运行的 Bash 脚本,我不想以 root 身份运行,但它需要在整个过程中定期进行 root 访问。我通过要求用户输入 root 密码解决了这个问题

sudo -v
Run Code Online (Sandbox Code Playgroud)

然后我背景了一个进程,该进程将使用循环并重置 sudo 计时器

sudo -n true
Run Code Online (Sandbox Code Playgroud)

然后我read在主进程中使用时开始遇到奇怪的问题。这是一个展示此问题的最小脚本。如果您运行它并且在sudo -n true运行之前不输入任何内容,则读取将获得read error: 0: Resource temporarily unavailable

#!/usr/bin/env bash

sudo -v  # ask user for password

sleep 1 && sudo -n true &  # background a process to reset sudo

printf "Reading text: "
read -n 1 TEXT
echo "Read text: $TEXT"
Run Code Online (Sandbox Code Playgroud)

除了sudo. 如何sudo -n true在不干扰的情况下在后台运行read

编辑:

我只在 Ubuntu 上遇到这个问题,而不是 macOS。

Sté*_*las 10

我得到相同的行为:

sleep 1 && true < /dev/tty &
read var
Run Code Online (Sandbox Code Playgroud)

sudo打开/dev/tty以查询当前的前台进程组,这会导致read()bash 进行的系统调用read以 EAGAIN 返回,Ubuntu 18.04 的 Linux 内核 4.15.0-45-generic 和 4.18.0-14-generic 至少导致read实用程序返回有那个错误。

这似乎是由Linux 内核的 Ubuntu 变体的最新版本中的错误引起的。我无法在 Solaris 或 FreeBSD 上重现它,也无法在 Debian 上的任何 Linux 版本中重现它(尽管如果我在 Ubuntu 的 4.18 内核上启动 Debian,我可以重现它)。

https://bugs.launchpad.net/ubuntu/+source/linux-signed-hwe/+bug/1815021似乎是该错误的另一种表现形式。

这是由https://lkml.org/lkml/2018/11/1/663引入的,ubuntu 至少向后移植到其 4.15 和 4.18 内核。但是 Ubuntu直到2 小时前才向后移植了另一个更改来修复该补丁引入的回归

4.18.0-15-generic 现在已经登陆 Ubuntu 存储库并修复了这个问题。我想 4.15 的版本很快就会发布。

ksh93没有问题,因为它的read内置代码select()首先使用它来等待输入,并且select()在其他进程打开时不返回/dev/tty

所以在这里你可以使用ksh93代替bash或等待修复的内核,或者回到 4.15.0-43 直到 4.15.0-46 发布。

或者,您可以使用zshwhich 具有更改 uids 的内置支持(通过 EUID/UID/USERNAME 特殊变量),前提是您启动脚本,root这样您就不需要sudo在脚本中运行(延长使用寿命也有潜在危险) sudo 令牌比用户预期的要长)。