Course contentsShow
← Linux
Lesson 164 of 1,8192. Deep Dive into Bash ScriptingFree lesson

Non-blocking I/O Patterns

Implement time-out logic for commands that risk hanging indefinitely.

In this lesson, you will learn how to prevent your Bash scripts from hanging indefinitely by implementing time-out logic around slow or unresponsive commands.

The Problem: The Infinite Hang

In Linux, some commands—like network requests, hardware queries, or waiting for user input—don't always finish. If a command freezes, your script stops dead in its tracks. Because Bash is generally synchronous, it will wait forever for a process to return an exit code. To build robust scripts, we need a way to say: "Run this command, but if it takes longer than NN seconds, kill it and move on."

The Solution: Using timeout

The cleanest pattern for non-blocking execution is the timeout command. It wraps your command and manages the process lifecycle, ensuring that if the time limit is reached, it terminates the child process and returns a specific exit code (usually 124).

Consider a script trying to ping a server that might be down:

# Try to reach a server for 3 seconds
if timeout 3s ping -c 1 192.0.2.1 > /dev/null; then
    echo "Server responded!"
else
    # Check if it failed because of the time-out
    if [ $? -eq 124 ]; then
        echo "Command timed out."
    else
        echo "Command failed for other reasons."
    fi
fi

How it works

  1. The Wrapper: timeout acts as a supervisor. It forks your command into a child process and tracks its execution time.
  2. Termination: If the timer expires before the command completes, timeout sends a SIGTERM (and later a SIGKILL if necessary) to the child process.
  3. Exit Code Propagation: By capturing the exit code of the timeout command itself, you can distinguish between a successful run, a standard command failure, and a forced termination.

This pattern is essential when you have multiple tasks. By using timeout in conjunction with your previous knowledge of background processes (Lesson 12), you can launch several non-blocking tasks simultaneously, ensuring that one unresponsive network call doesn't prevent your entire orchestration script from completing its work.

Key Takeaway: Always wrap volatile or network-dependent commands in timeout to ensure your script maintains control over its own execution time.