![包含 sudo 的 Bash 脚本 - 不可靠的后台恢复 (bg)](https://linux22.com/image/213811/%E5%8C%85%E5%90%AB%20sudo%20%E7%9A%84%20Bash%20%E8%84%9A%E6%9C%AC%20-%20%E4%B8%8D%E5%8F%AF%E9%9D%A0%E7%9A%84%E5%90%8E%E5%8F%B0%E6%81%A2%E5%A4%8D%20(bg).png)
我有以下简单的 bash 脚本(称为test.sh
),它显示根目录中的磁盘使用情况。sudo
需要列出所有目录(并且不需要我输入sudo
密码)。
#!/bin/bash
sudo du -h --max-depth=1 / 2> /dev/null
该目录位于我的路径中,然后我像这样运行脚本(以将输出输出到文本文件):
$ ./test.sh >> ./test.txt
Ctrl现在,如果我用+暂停工作Z,我会得到:
^Z
[1]+ Stopped ./test.sh >> ./test.txt
如果我然后在后台恢复bg
,我仍然得到:
$ bg
[1]+ ./test.sh >> ./test.txt &
[1]+ Stopped ./test.sh >> ./test.txt
$ jobs
[1]+ Stopped ./test.sh >> ./test.txt
(额外的尝试bg
可能会导致脚本在 2-3 次尝试后实际上在后台恢复,但似乎是零星的......)
但是,如果我使用 继续fg
,则脚本将在前台运行:
$ fg
./test.sh >> ./test.txt
结果写入test.txt
:
3.8M /root
4.0K /authentic-theme
4.0K /srv
72K /tmp
3.2G /snap
4.0K /media
8.4M /etc
0 /proc
0 /sys
4.0K /cdrom
16K /opt
16K /lost+found
24K /dev
4.3M /run
263G /mnt
14M /home
19G /var
245M /boot
3.8G /usr
297G /
如果我将脚本修改为不是使用sudo
(并改为使用 运行脚本sudo
),然后我可以使用 正常恢复到后台bg
,并且运行脚本:
$ sudo ./test.sh >> ./test.txt
^Z
[1]+ Stopped sudo ./test.sh >> ./test.txt
$ bg
[1]+ sudo ./test.sh >> ./test.txt &
$ jobs
[1]+ Running sudo ./test.sh >> ./test.txt &
如果我使用 运行整个命令sudo
,但不是作为脚本运行,也会发生同样的情况:
$ sudo du -h --max-depth=1 / 2> /dev/null >> ./test.txt
^Z
[1]+ Stopped sudo du -h --max-depth=1 / 2> /dev/null >> ./test.txt
$ bg
[1]+ sudo du -h --max-depth=1 / 2> /dev/null >> ./test.txt &
$ jobs
[1]+ Running sudo du -h --max-depth=1 / 2> /dev/null >> ./test.txt &
有人能解释一下这是怎么回事吗?为什么您可以sudo
在后台恢复使用以及脚本的命令,但是当脚本包含使用完全相同的命令时sudo
,后台恢复bg
显然无法正常工作?
我使用的是 Ubuntu 22.04.1,默认 Bash 版本为 5.1.16。
编辑#1:我可以通知我已设置alias sudo='sudo '
允许命令使用sudo
其他别名。但是,我测试了使用和不使用此别名的情况,并且bg
在任何情况下都得到了相同的不稳定恢复行为。*
编辑#2: jobs -l
给出以下正常信息:
jobs -l
[1]+ 1074808 Stopped ./test.sh >> ./test.txt
编辑#3:我通常在 中运行tmux
,但我也在没有 的情况下进行了测试tmux
,问题仍然存在。
编辑#4:除了我的 SuperMicro 服务器之外,我还有一个 Raspberry Pi 和一个用于在我的笔记本电脑 (Aorus X5) 上进行测试的 Ubuntu VM。这真的很奇怪:
- 在我的 Ubuntu VM 上(在 Windows 10 下的 VMWare 上),出现此问题才不是发生在所有。在所有情况下,它都会
bg
第一次正确恢复。 - 在我的 Raspberry Pi 上,问题也存在 - 通常需要 2-3 次尝试
bg
才能正确恢复。
我开始认为我需要测试在我的主服务器和 Raspberry Pi 上运行的软件,但不在我的虚拟机上运行。
编辑#5:stty -tostop
不幸的是,在运行脚本之前进行设置并不能真正解决问题。大多数时候,仍需要 2-3 次尝试才能正确恢复。有几次第一次尝试就成功了,但我认为这比其他任何事情都更有机会。
编辑#6:这些是我的 Raspberry Pi 上运行的服务:
$ systemctl --type=service --state=running
UNIT LOAD ACTIVE SUB DESCRIPTION
atd.service loaded active running Deferred execution scheduler
containerd.service loaded active running containerd container runtime
cron.service loaded active running Regular background program processing daemon
dbus.service loaded active running D-Bus System Message Bus
docker.service loaded active running Docker Application Container Engine
[email protected] loaded active running Getty on tty1
irqbalance.service loaded active running irqbalance daemon
ModemManager.service loaded active running Modem Manager
networkd-dispatcher.service loaded active running Dispatcher daemon for systemd-networkd
packagekit.service loaded active running PackageKit Daemon
polkit.service loaded active running Authorization Manager
prometheus-node-exporter.service loaded active running Prometheus exporter for machine metrics
rsyslog.service loaded active running System Logging Service
[email protected] loaded active running Serial Getty on ttyS0
smartmontools.service loaded active running Self Monitoring and Reporting Technology (SMART) Daemon
snapd.service loaded active running Snap Daemon
ssh.service loaded active running OpenBSD Secure Shell server
systemd-journald.service loaded active running Journal Service
systemd-logind.service loaded active running User Login Management
systemd-networkd.service loaded active running Network Configuration
systemd-timesyncd.service loaded active running Network Time Synchronization
systemd-udevd.service loaded active running Rule-based Manager for Device Events and Files
udisks2.service loaded active running Disk Manager
unattended-upgrades.service loaded active running Unattended Upgrades Shutdown
unbound.service loaded active running Unbound DNS server
[email protected] loaded active running User Manager for UID 1000
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
26 loaded units listed.
我相信这些是我安装和激活的(并且在 SuperMicro 和 Raspberry Pi 上运行):
containerd.service loaded active running containerd container runtime
docker.service loaded active running Docker Application Container Engine
prometheus-node-exporter.service loaded active running Prometheus exporter for machine metrics
smartmontools.service loaded active running Self Monitoring and Reporting Technology (SMART) Daemon
unbound.service loaded active running Unbound DNS server
要测试的东西:
检查sudo
配置是否NOPASSWD
有影响。- 禁用我的 SuperMicro 服务器和 Raspberry Pi 之间常见的已安装服务。
答案1
通常,当程序拒绝后台运行时,这是因为它需要输入。
虽然df
实际上没有从标准输入读取,但它仍然是打开的。尝试:
#!/bin/bash
sudo du -h --max-depth=1 / 2> /dev/null 0< /dev/null
请注意,这可能会让您无法输入密码。
或者,尝试向进程发送相关信号可能会出现问题,因为它不是。我怀疑情况是否如此,但如果是这样,我建议首先在后台运行它。 (这对我来说不是问题。)