9

I have the following simple bash script (called test.sh), that shows disk usage in the root dir. sudo is needed to list all directories (and I'm not asked for sudo password).

#!/bin/bash sudo du -h --max-depth=1 / 2> /dev/null 

The directory is in my path, and then I run the script like this (to get output to a text file):

$ ./test.sh >> ./test.txt 

Now, if I suspend the job with Ctrl+Z, I get this:

^Z [1]+ Stopped ./test.sh >> ./test.txt 

If I then resume in background with bg, I still get:

$ bg [1]+ ./test.sh >> ./test.txt & [1]+ Stopped ./test.sh >> ./test.txt $ jobs [1]+ Stopped ./test.sh >> ./test.txt 

(Additional tries with bg may result in the script actually resuming in background after 2-3 tries, but it seems sporadic...)

However, if I resume with fg, then the script runs in foreground:

$ fg ./test.sh >> ./test.txt 

And the result is written to 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 / 

If I modify the script to not use sudo (and instead run the script with sudo), then I can resume to background normally with bg, and the script is run:

$ 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 & 

The same happens if I run the entire command with sudo, but not as a script:

$ 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 & 

Can anybody explain what's going on here? Why can you resume a command that uses sudo as well as a script in background, but when the script contains the exact same command using sudo, then background resume with bg is apparently not working correctly?

I'm using Ubuntu 22.04.1 with default Bash version 5.1.16.

Edit #1: I can inform that I have setup alias sudo='sudo ' to allow commands using sudo to use other aliases. However, I tested both with and without this alias, and I got the same erratic bg resume behavior in any case.*

Edit #2: jobs -l give the following normal information:

jobs -l [1]+ 1074808 Stopped ./test.sh >> ./test.txt 

Edit #3: I'm normally running in tmux, but I also tested without tmux, and the issue still persists.

Edit #4: Besides my SuperMicro server, I also has a Raspberry Pi, and an Ubuntu VM for testing on my Laptop (Aorus X5). This where it gets really strange:

  • On my Ubuntu VM (on VMWare under Windows 10), this problem does NOT occur at all. It correctly resumes bg the first time in all cases.
  • On my Raspberry Pi, the problem is present as well - it usually takes 2-3 tries with bg until it correctly resumes.

I'm beginning to think I need to test with regards to software that is running on both my main server and my Raspberry Pi, but not on my VM.

Edit #5: Setting stty -tostop before running the script unfortunately does not really help the problem. Most of the time, it still takes 2-3 tries to resume correctly. A few times it succeeds on the first try, but I think this is more chance than anything else.

Edit #6: These are the services running on my 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. 

I believe these are the ones that I installed and activated (and are running on both the SuperMicro and the 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 

Things to test:

  • Check if sudo configuration without NOPASSWD makes a difference.
  • Disable installed services that are common between my SuperMicro server and Raspberry Pi.
13
  • I can confirm that this happens no matter what command is used with sudo in the script (I tested with sudo sleep 30), and it isn't limited to Ubuntu (I tested on Arch). I think this is related to a recent change, I know I've seen questions about the behavior in the past few days. Commented Nov 24, 2022 at 13:53
  • I noticed that if I run bg a few times (it seems to vary between 1 in some cases, 2 in others and 3 in yet others, with the same command in the script) it eventually gets passed to the right process and the sudo command continues. Do you see the same behavior? Commented Nov 24, 2022 at 13:59
  • Thanks for confirming. Yes that is correct - if you try more times, it eventually succeeds - but the written output seems "interrupted" in a way.. Commented Nov 24, 2022 at 14:01
  • 1
    It feels like there is some other process consuming the bg commands. Very strange. Commented Nov 24, 2022 at 14:13
  • I find it even more strange that the two other ways of doing the same thing with sudo succeeds every time. I actually tried a very thorough troubleshooting approach. So it is isolated when sudo is inside the script. 🤔 Commented Nov 24, 2022 at 14:16

3 Answers 3

2

The behaviour seems to be by design, but I'm still trying to identify which parts trigger the issue. You can avoid the suspension in three ways

  1. Ensure that none of stdout, stderr, and stdin is connected to the terminal. For example,

    sudo du -h --max-depth=1 / </dev/null 2>/dev/null >>./test.txt 

    or (my preference) to capture stderr as well:

    sudo du -h --max-depth=1 / </dev/null >>./test.txt 2>&1 
  2. Allow background processes to run uninterrupted. Set stty -tostop before invoking the code (assuming there's a terminal attached):

    tty -s && stty -tostop sudo du -h --max-depth=1 / >>./test.txt 
  3. Enable logging within the sudo configuration. The information is documented in the source code's NEWS file (Debian):

    For sudo version 1.8.22

    • When I/O logging is enabled, sudo will now write to the terminal
      even when it is a background process.

    See the section I/O LOGGING in man sudoers for details on how to configure logging.

4
  • I'd rather have stderr also go to ./test.txt instead of being lost, with : sudo du -h --max-depth=1 / </dev/null >>./test.txt 2>&1 Commented Jan 7 at 17:27
  • @OlivierDulac so would I, but I was copying the structure from the question. Nevertheless I've amended the answer Commented Jan 7 at 18:15
  • 1
    Could you explain the design? I mean, if this is by design, what is the use case? Commented Jan 7 at 19:10
  • @terdon I'd love to, but it seems to be a combination of bash and sudo along with stuff like stty [-]tostop. I'll try to nail it down Commented Jan 7 at 19:24
0

Usually, when a program refuses to background, it is because it wants input.
While df doesn't actually read from stdin, it is still open. Try:

#!/bin/bash sudo du -h --max-depth=1 / 2> /dev/null 0< /dev/null 

Note that this may leave you unable to enter a password.

Alternatively, there could be issues with attempting to send the relevant signals to the process because it isn't . I doubt this is the case, but if it is, I would suggested just running it in the background to begin with. (This isn't an issue for me.)

0

sudo is flakey ;(

Try

sudo -l 

You may find you need to stop sudo from expecting tty or password, e.g. create /etc/sudoers.d/000-defaults containing

Defaults !requiretty, !verifypw, listpw=any 
1
  • "sudo is flakey" - no, it's by design Commented Jan 7 at 11:05

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.