The timeout command in Linux runs a command with a time limit and terminates it when the limit is reached. It is part of GNU coreutils, available on virtually every Linux distribution.
It is most useful for commands with no built-in timeout option, such as ping, curl, tcpdump, or a custom script that might hang indefinitely.
The syntax is:
bashtimeout [OPTIONS] DURATION COMMAND [ARG]...
Duration is a number followed by an optional unit: s (seconds, default when omitted), m (minutes), h (hours), or d (days). Floating-point values are supported:
bashtimeout 5 ping 8.8.8.8 # 5 secondstimeout 5m ping 8.8.8.8 # 5 minutestimeout 1.5m ping 8.8.8.8 # 90 seconds
Setting the duration to 0 disables the timeout. This is useful in scripts where the timeout value comes from a variable and you want a way to skip the limit without extra conditional logic.
For commands that require elevated privileges:
bashsudo timeout 300 tcpdump -n -w data.pcap
When the time limit is reached, timeout sends SIGTERM (signal 15) by default. SIGTERM is a graceful termination request. The process receives it and can clean up open files and flush buffers before exiting. Some processes are written to catch and ignore SIGTERM, so they keep running after the signal is sent.
To send a different signal, use the -s option with the signal name or number:
bashtimeout -s SIGKILL 1m ping 8.8.8.8timeout -s 9 1m ping 8.8.8.8 # equivalent
SIGKILL (signal 9) forces the process to stop at the kernel level. The process cannot catch it, block it, or clean up before terminating.
The recommended pattern for processes that ignore SIGTERM is the -k (kill-after) option. It sends SIGTERM at the timeout and escalates to SIGKILL only if the process is still running after the grace period:
bashtimeout -k 10 1m ping 8.8.8.8
This gives the process 10 seconds to shut down cleanly before force-killing it. Jumping straight to SIGKILL risks data loss if the process was writing to a file.
To list all signal names and their numbers:
bashkill -l
Exit codes. When the time limit is reached, timeout returns exit code 124. When the command finishes before the timeout, it returns the command’s own exit code. Use --preserve-status to return the command’s actual exit code even when a timeout fires — useful when a calling script needs to distinguish a timeout from a genuine command failure.
Check for exit code 124 in scripts:
bashtimeout 30 curl -s -o /tmp/data.json https://api.example.com/data[ $? -eq 124 ] && echo "Timed out after 30 seconds." || echo "Completed or failed."
Pipelines. timeout applies only to the command directly after it. In a pipeline, downstream commands keep running after the first is killed. Wrap the full pipeline in bash -c to apply the limit to all stages:
bashtimeout 30 bash -c 'curl -s https://example.com | grep "pattern"'
Without the bash -c wrapper, grep keeps waiting for input after curl is terminated. The pipeline never closes.
sudo placement. Always put sudo before timeout, not after it. If the child process runs as root and timeout runs as a regular user, signal delivery fails with a permission error:
bashsudo timeout 60 tcpdump -n -w capture.pcap # correct
Interactive commands and shell built-ins. Use --foreground for commands that read from the terminal. By default, timeout places the managed command in a separate process group, which can break terminal input. Shell built-ins like read and cd cannot be timed directly because they are not external commands — wrap them with bash -c:
bashtimeout --foreground 5m ./interactive-script.shtimeout 5 bash -c 'read -p "Input: " val'
Use timeout -k 10 as your default pattern for processes that might ignore SIGTERM. Check exit code 124 in scripts to detect timeouts cleanly, and wrap pipelines in bash -c so the limit applies to every stage. Leave a comment below if you run into any issues.