我有一个长时间运行的 Bash 脚本,我不想以 root 身份运行它,但它需要定期进行 root 访问。我通过询问用户 root 密码来解决这个问题
sudo -v
然后我在后台运行一个进程,该进程将循环并使用以下命令重置 sudo 计时器
sudo -n true
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"
除了 之外,我无法使用任何其他命令复制此行为sudo
。如何sudo -n true
在不干扰的情况下在后台运行read
?
编辑:
我只在 Ubuntu 上遇到这个问题,在 macOS 上没有。
答案1
我得到同样的行为:
sleep 1 && true < /dev/tty &
read var
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/663ubuntu 至少向后移植到其 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 发布。
或者,您可以使用zsh
它内置支持更改 uid(通过 EUID/UID/USERNAME 特殊变量),前提是您启动脚本,这样root
您就不需要sudo
在脚本内运行(延长脚本的寿命也有潜在的危险) sudo 令牌比用户预期的要长)。