SHLVL 環境變數代表 Shell 巢狀執行的深度。
$ echo $SHLVL 1 $ bash $ echo $SHLVL 2 $ bash $ echo $SHLVL 3 |
在 Bash 裡,這個值的範圍是 [0, 1000],0 是怎麼來的呢?是在上次的 SHLVL 值為負數的時候:
$ SHLVL=-1 $ bash $ echo $SHLVL 0 |
當 SHLVL 的值超過 1000 時,會自動重置到 1。
$ SHLVL=1000 $ bash bash: warning: shell level (1001) too high, resetting to 1 $ echo $SHLVL 1 |
我也本以為就是這樣了,然而卻發現個特例:
$ SHLVL=999 $ bash $ echo $SHLVL
|
在巢狀 1000 層的時候,SHEVL 看起來是個空字串,但在 Shell 裡很多東西眼見都不為實,所以我們用 16 進位制看看:
$ SHLVL=999 bash -c 'echo -n "$SHLVL" | hexdump' 0b 01 $ SHLVL=999 bash -c 'echo -n "$SHLVL" | hexdump' 0f 01 $ SHLVL=999 bash -c 'echo -n "$SHLVL" | hexdump' 04 01 |
這個值原來是個隨機字串,在我的 Mac 上是兩個控制字元(不可見字元),所以看起來像是空字串。而在另外一臺 Red Hat 上執行了下是一些肉眼可見的亂碼:
$ SHLVL=999 bash -c 'echo "$SHLVL"' �[g� |
總之,也就是說 SHEVL 實際的值會在 [0, 999] 以及這個不確定的值這 1001 個值裡輪詢,不會真正到達 1000。
看了下 Bash 原始碼:
void adjust_shell_level (change) int change; { char new_level[5], *old_SHLVL; intmax_t old_level; SHELL_VAR *temp_var; old_SHLVL = get_string_value ("SHLVL"); if (old_SHLVL == 0 || *old_SHLVL == '\0' || legal_number (old_SHLVL, &old_level) == 0) old_level = 0; shell_level = old_level + change; if (shell_level < 0) shell_level = 0; else if (shell_level > 1000) { internal_warning (_("shell level (%d) too high, resetting to 1"), shell_level); shell_level = 1; } /* We don't need the full generality of itos here. */ if (shell_level < 10) { new_level[0] = shell_level + '0'; new_level[1] = '\0'; } else if (shell_level < 100) { new_level[0] = (shell_level / 10) + '0'; new_level[1] = (shell_level % 10) + '0'; new_level[2] = '\0'; } else if (shell_level < 1000) { new_level[0] = (shell_level / 100) + '0'; old_level = shell_level % 100; new_level[1] = (old_level / 10) + '0'; new_level[2] = (old_level % 10) + '0'; new_level[3] = '\0'; } temp_var = bind_variable ("SHLVL", new_level, 0); set_auto_export (temp_var); } static void initialize_shell_level () { adjust_shell_level (1); }
它把數字轉字串的邏輯只寫到 shell_level < 1000 的地方,漏掉了最後一個 else 的樣子,導致 SHLVL 的值成為了一個未初始化的字串。我在 bug-bash 上發了郵件,這個 bug 會在 Bash 4.4 中修復 http://lists.gnu.org/archive/html/bug-bash/2015-09/msg00057.html。順便說一句,ksh 和 zsh 都沒有這個 1000 限制。