SHLVL 环境变量代表 Shell 嵌套执行的深度。
$ echo $SHLVL 1 $ bash $ echo $SHLVL 2 $ bash $ echo $SHLVL 3 |
在 Bash 里,这个值的范围是 [1, 1000],在 1001 的时候会重置到 1。
$ SHLVL=1000 $ bash bash: warning: shell level (1001) too high, resetting to 1 $ echo $SHLVL 1 |
我也本以为就是这样了,然而却发现个特例:
$ SHLVL=999 $ bash $ echo $SHLVL |
在嵌套 1000 层的时候,SHEVL 会是个空字符串,也就是说 SHEVL 实际的值会在 [1, 999] 以及空这 1000 个值里轮询,不会真正到达 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 的样子,不管是否是作者有意的,这个表现都应该都不会改动了,反正这也算是 edge case 了,顺便说一句,ksh 和 zsh 都没有这个 1000 限制。
时间: 2024-11-05 15:09:07