How to use timeout command to terminate a command and proceed accordingly
The aim of this page📝 is to share my solution to the problem that I want to allow users into a Docker box only if the attempt to authenticate against Hashicorp Vault succeeds.
In other words, only if they are in VPN. It’s a bit of a leap of faith, I know. To diagnose if I am in VPN, I just use a blunt mechanism of timeout — if the program runs for > 5s, it follows that you are not in the VPN, which is another leap, I know. But hey, this is an internal and team-specific box, so it should be a good-enough measure. The abstract (therefore interesting:) question remains: how to timeout a program in bash and make a case analysis based on that, i.e. if timed out do something (exit early) and if not timed out, just run along the happy path.
Use timeout command and exit quickly if timed out, which is confirmed by exit code 124
- Use
timeout
command - ⟹ time runs out and the command that follows is terminated; from
timeout --help
Usage: timeout [OPTION] DURATION COMMAND [ARG]...
Start COMMAND, and kill it if still running after DURATION.
<!-- EXAMPLE -->
timeout 2s ping google.com
- If any command times out, the
timeout
returns error code124
EXIT status:
124
if COMMAND times out, and −−preserve−status is not specified
— timeout(1) — Linux manual pages
- If that happens, so I just explain myself and terminate
timeout 5s vault login -method=github token="${GITHUB_TOKEN}"
if [[ $? == 124 ]]; then
echo "ERROR: Authentication timed out after 5s!"
echo "~~> VPN is a prerequisite — please connect and try again"
exit
fi
- If no, and command returned
0
(all good, it did not time out) ⟹ just go on
Just for fun, it is possible to use --preserve-status
and then go with error_code 143
- If I use
--preserve-status
flag, the failed command in my case generates exit code143
- Exit code
143
is returned bySIGTERM
signal, which is basically a signal for grafeful termination
is a generic signal used to cause program termination. Unlike SIGKILL, this signal can be blocked, handled, and ignored. It is the normal way to politely ask a program to terminate. The shell command kill generates SIGTERM by default.
— Termination Signals (The GNU C Library)
- Say you want to do this with a
ping
command (echo $?
checks for the last exit code)
~$ timeout --preserve-status 2 ping google.com
PING google.com(prg03s13-in-x0e.1e100.net (2a00:1450:4014:80f::200e)) 56 data bytes
64 bytes from prg03s13-in-x0e.1e100.net (2a00:1450:4014:80f::200e): icmp_seq=1 ttl=116 time=18.4 ms
64 bytes from prg03s13-in-x0e.1e100.net (2a00:1450:4014:80f::200e): icmp_seq=2 ttl=116 time=16.0 ms
~$ echo $?
143
- In my case, I’d just add the flag and replace
124
⟹143
timeout --preserve-status 5 vault login -method=github token="${GITHUB_TOKEN}"
if [[ $? == 143 ]]; then
echo "ERROR: Authentication timed out after 5s!"
echo "~~> VPN is a prerequisite — please connect and try again"
exit
fi