包含 sudo 的 Bash 脚本 - 不可靠的后台恢复 (bg)

包含 sudo 的 Bash 脚本 - 不可靠的后台恢复 (bg)

我有以下简单的 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

请注意,这可能会让您无法输入密码。

或者,尝试向进程发送相关信号可能会出现问题,因为它不是。我怀疑情况是否如此,但如果是这样,我建议首先在后台运行它。 (这对我来说不是问题。)

相关内容