---
# System prepended metadata

title: 'Bug: Bash Arithmetic Evaluation Exit Status Pitfall'
tags: [shell script, linux, bug]

---

---
title: 'Bug: Bash Arithmetic Evaluation Exit Status Pitfall'
disqus: hackmd
---

Bug: Bash Arithmetic Evaluation Exit Status Pitfall
===

某天寫了支Daemon（使用`shell script`），上線後出現bug：
```
Dec 09 08:40:11 tw-logs run_syncLog_bin[171034]: -----------------------------------------------------
Dec 09 08:40:11 tw-logs systemd[1]: syncLog.service: Main process exited, code=exited, status=1/FAILURE
Dec 09 08:40:11 tw-logs systemd[1]: syncLog.service: Failed with result 'exit-code'.
Dec 09 08:40:11 tw-logs systemd[1]: Failed to start syncLog.service - syncLogFiles.
```
log message印出分隔線之後，立刻因為return code崩潰


## Guide

[TOC]


## How it works

把code拉出來看，乍看之下沒問題：
```bash=
count=0
...
...
while read -r list || [ -n "list" ]; do
    echo "-----------------------------------------------------" 
    (   
        mkdir -p "${path}/${list}"
        ...
        ...
    ) &
    ((count++))
    ...
    ...
done
```

然而，前面加入這個參數：
```bash
set -euo pipefail
```
意思是，遇到錯誤，也就是`exit-code=1`時，直接讓script崩潰

於是問題就產生了：
> [!Warning]
> ((count++))是**後置運算**，先**回傳目前的值，再進行運算**

所以，while-loop第一次運作時，count會先`return 0`，再開始+1
數學運算邏輯中，數值0代表`False`；在shell得到這個"狀態"後，會將這個狀態識別（FAILURE）並反應，
回傳`FAILURE`（status=1，error）
這時就會撞到前面的：
```bash
set -euo pipefail
```
然後，script崩潰了(Failed with result: exit-code)，如同設計好的一般
計畫失敗的相當成功
![image](https://hackmd.io/_uploads/B17x9GrM-x.png)


## What should we do
事情出在哪，解法就用在哪
改成**後置運算**即可：
```bash
((++count))
```

## Ref.
[BashPitfalls](https://gist.github.com/dsoares/7608d68538be606f3b6a6f0c557bfc8c)
[How to do calculation in Bash](https://www.shell-tips.com/bash/math-arithmetic-calculation/#gsc.tab=0)
[something interesting in StackOverFlow](https://stackoverflow.com/questions/69950459/bash-weirdness-exit-codes-of-arithmetic-expressions-in-relation-to-conditionals)
    
###### tags: `linux` `shell script` `bug`