When testing the host availability check script I mentioned last time, I encountered an interesting Bash feature when performing arithmetic operations💪.
🖐️Hey!
Subscribe to our Telegram channel @r4ven_me📱, so you don’t miss new posts on the website 😉. If you have questions or just want to chat about the topic, feel free to join the Raven chat at @r4ven_me_chat🧐.
👨💻What is the point:
My script uses the check_count variable, which contains the current number of failed checks. This counter is increased with the increment command: ((check_count++)).
The key word here is command. For further understanding, it is worth adding a bit of context😒
🤯Context:
In Bash, the ((expression)) syntax performs two functions:
- Arithmetic evaluation.
- Logical check of the result (return code, also known as return code, rc).
Return code features of arithmetic operations:
- if the expression result is greater than 0, return code 0 is returned (success)
- if the result is equal to 0, return code 1 is returned (error)
And an operation of the form ((expression++)) first returns the current value of the variable, and then increments it🍿
So, if the initial value is check_count=0, then on the first execution of the ((check_count++)) command, Bash first returns code 1, which is interpreted as an error😵💫
By default, Bash ignores any errors and continues execution. Therefore, in my scripts I often use the shell option set -e so that the script exits on any error - this makes its behavior more predictable.
And it seems obvious: got an error - exited, but the script has asynchronous tasks (&) running in subprocesses🤔
Example from the check_hosts.sh script:
for host in "${CHECK_HOSTS[@]}"; do
monitor_host "$host" &
doneThis block launches monitor_host in parallel for each host from the specified list.
If a subprocess entered the else branch and reached ((check_count++)), where check_count was equal to 0, it exited with an error because of set -e. At the same time, the main script and other subprocesses continued working💪
This led to non-obvious behavior: some processes exited, while others continued running. Without detailed checks, you might not notice it. To catch this moment, I had to strain my brain a little🤯
👌Solution:
I added a logical “or” || true so that the command always exits successfully:
((check_count++)) || trueAnother possible (and probably more correct) way is to use the prefix form:
((++check_count))In this case, Bash immediately returns the new value, and if it is greater than 0 (which it will be), the return code is 0.
Or, as I was told, explicitly add one:
check_count=$((check_count+1))I knew about this nuance in Bash arithmetic, but this was the first time I encountered it in the context of asynchronous commands.
👨💻And…
Don’t forget about our Telegram channel 📱 and chat
Or maybe you want to become a co-author? Then click here🔗
💬 All the best ✌️
That should be it. If not, check the logs 🙂


