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
  • ⟹ 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 code 124
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
  • If I use --preserve-status flag, the failed command in my case generates exit code 143
  • Exit code 143 is returned by SIGTERM 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 124143
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

--

--

Infrastructure Support Engineer/Technical Writer (snowplow.io) with a passion for Python/writing documentation. More about me: https://pavol.kutaj.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Pavol Kutaj

Infrastructure Support Engineer/Technical Writer (snowplow.io) with a passion for Python/writing documentation. More about me: https://pavol.kutaj.com