How to Run Sequential Commands with nohup in Linux: Background Execution of Dependent Tasks


2 views

When working on Linux systems, we often need to execute long-running commands in the background while maintaining execution order between dependent operations. The naive approach of simply chaining commands with semicolons doesn't work as expected with nohup:

nohup command1; command2 &   # Doesn't work as intended

The issue occurs because the shell interprets the entire command sequence before applying the background operator (&). When you use:

nohup tar -zcf archive.tar.gz.tmp mydir ; mv archive.tar.gz.tmp archive.tar.gz > /dev/null 2>&1 &

The shell sees this as two separate commands: one nohup command followed by a mv command in the foreground, with only the last part implicitly backgrounded.

The most elegant solution is to group the commands in a subshell and background the entire sequence:

nohup sh -c 'tar -zcf archive.tar.gz.tmp mydir && mv archive.tar.gz.tmp archive.tar.gz' > /dev/null 2>&1 &

Key points:

  • The commands are wrapped in single quotes
  • && ensures the second command only runs if the first succeeds
  • Entire sequence is properly backgrounded

For more complex sequences, consider creating a temporary script:

cat << 'EOF' > /tmp/archive_script.sh
#!/bin/bash
tar -zcf archive.tar.gz.tmp mydir
mv archive.tar.gz.tmp archive.tar.gz
EOF

chmod +x /tmp/archive_script.sh
nohup /tmp/archive_script.sh > /dev/null 2>&1 &

For production use, you should add error handling:

nohup sh -c '
tar -zcf archive.tar.gz.tmp mydir || exit 1
[ -f archive.tar.gz.tmp ] || exit 1
mv archive.tar.gz.tmp archive.tar.gz
' > /dev/null 2>&1 &

For repeated tasks, creating a simple Makefile can be cleaner:

archive:
    tar -zcf archive.tar.gz.tmp mydir
    mv archive.tar.gz.tmp archive.tar.gz

# Then run:
nohup make archive > /dev/null 2>&1 &

After launching your background process, you can monitor it with:

jobs -l       # For current shell's background jobs
ps aux | grep tar  # System-wide process search
tail -f nohup.out  # If not redirecting output

When working with long-running processes in Linux, we often face a common scenario: executing multiple commands sequentially in the background where each subsequent command depends on the successful completion of the previous one. The standard nohup approach works perfectly for single commands, but becomes tricky when dealing with command chains.

The initial attempts reveal some important shell behavior nuances:

nohup command1 ; command2 &  # Doesn't background properly
nohup command1 & ; command2 &  # Syntax error

The issue stems from how shell interprets the semicolon and ampersand operators in combination with nohup.

Here are three robust approaches to solve this problem:

1. Using Command Grouping

nohup { tar -zcf archive.tar.gz.tmp mydir && mv archive.tar.gz.tmp archive.tar.gz; } > /dev/null 2>&1 &

Note: The curly braces require spaces around them and a terminating semicolon.

2. Creating a Temporary Shell Script

Even without write permissions, you can create an ephemeral script:

nohup bash -c 'tar -zcf archive.tar.gz.tmp mydir && mv archive.tar.gz.tmp archive.tar.gz' > /dev/null 2>&1 &

3. Using Subshell Execution

nohup (tar -zcf archive.tar.gz.tmp mydir && mv archive.tar.gz.tmp archive.tar.gz) > /dev/null 2>&1 &

For more complex workflows, consider:

  • Adding error handling with exit codes
  • Implementing logging for debugging
  • Using process substitution for output handling

Example with enhanced error handling:

nohup (
  if tar -zcf archive.tar.gz.tmp mydir; then
    mv archive.tar.gz.tmp archive.tar.gz || echo "Move failed" >&2
  else
    echo "Compression failed" >&2
    exit 1
  fi
) > /dev/null 2>&1 &

This technique is particularly useful for:

  • Database backup and rotation
  • CI/CD pipeline steps
  • Data processing workflows
  • Automated deployment sequences