bashshellsudoufw

How to handle "sudo ufw" failing in a subshell when the parent shell is closed?


I'm writing a shell script which will run in the background to control Syncthing and manage a UFW firewall in relation to Syncthing.

Here it is in simplified form:

#!/bin/bash

sync () {
    # Open the ports which Syncthing communicates on.
    sudo ufw allow syncthing &> /dev/null
    # Start Syncthing, and block script execution here until Syncthing is closed.
    syncthing &> /dev/null
    # Close the ports which Syncthing communicates on once it is closed.
    sudo ufw delete allow syncthing &> /dev/null
}

# Get sudo before the sync function is backgrounded.
sudo -v
# Run the sync function in the background.
sync &

This script works as intended when the terminal it is run from remains open.

If the terminal it is run from is closed while Syncthing is running though, then ports in the firewall are not closed when Syncthing is closed.

Is there a way to get this script to run properly -- closing the ports in the firewall after Syncthing is closed -- when the terminal it is started from is closed before Syncthing is closed?

Here is a script which you can use to experiment with this behaviour. It doesn't require Syncthing to be installed, and it outputs to syslog:

#!/bin/bash

test_function () {
    echo '-- Opening port' | logger -t TEST
    sudo ufw allow 80 | logger -t TEST
    echo '-- Close the terminal you started this script from in the next 10 seconds' | logger -t TEST
    sleep 10
    echo '-- Closing port' | logger -t TEST
    sudo ufw delete allow 80 | logger -t TEST
}

sudo -v
test_function &

Solution

  • I used one of triplee's suggestions to handle this problem by enabling passwordless sudo for the ufw commands I wanted to run.

    To do that I created a file called ufw in /etc/sudoers.d/ with this content:

    %sudo ALL=(root) NOPASSWD:/usr/sbin/ufw allow syncthing
    %sudo ALL=(root) NOPASSWD:/usr/sbin/ufw delete allow syncthing
    

    Then with passwordless sudo in place, my script became:

    #!/bin/bash
    
    sync () {
        sudo ufw allow syncthing
        syncthing
        sudo ufw delete allow syncthing
    }
    
    sync &> /dev/null &
    

    Now even when the terminal that it is run from is closed while syncthing is running, the ufw delete command still fires when syncthing is closed.