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[], *old_SHLVL;
intmax_t old_level;
SHELL_VAR *temp_var; old_SHLVL = get_string_value ("SHLVL");
if (old_SHLVL == || *old_SHLVL == '\0' || legal_number (old_SHLVL, &old_level) == )
old_level = ; shell_level = old_level + change;
if (shell_level < )
shell_level = ;
else if (shell_level > )
{
internal_warning (_("shell level (%d) too high, resetting to 1"), shell_level);
shell_level = ;
} /* We don't need the full generality of itos here. */
if (shell_level < )
{
new_level[] = shell_level + '';
new_level[] = '\0';
}
else if (shell_level < )
{
new_level[] = (shell_level / ) + '';
new_level[] = (shell_level % ) + '';
new_level[] = '\0';
}
else if (shell_level < )
{
new_level[] = (shell_level / ) + '';
old_level = shell_level % ;
new_level[] = (old_level / ) + '';
new_level[] = (old_level % ) + '';
new_level[] = '\0';
} temp_var = bind_variable ("SHLVL", new_level, );
set_auto_export (temp_var);
} static void
initialize_shell_level ()
{
adjust_shell_level ();
}

它把数字转字符串的逻辑只写到 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 限制。

Bash 中 SHLVL 变量为 1000 的时候的更多相关文章

  1. bash 中的变量

    bash 中的变量 Linux command line 笔记 变量无需声明,自动创建 var=abc #变量a赋值为字符串abc var="hello world" #字符串里有 ...

  2. Bash中的变量

    Bash中的变量1.用户定义的变量变量的定义  用户定义的变量有字母数字及下划线组成,并且变量名的第一个字符不能为数字.            与其它UNIX名字一样,变量名是大小写敏感的. 对于变量 ...

  3. 在Linux系详解Linux bash中的变量

    (大讲台:国内首个it在线教育混合式自适应学习) 统中进行日常运维或者是编写脚本时,变量是再熟悉不过的了,但这些变量都有哪些类型,具体的用法又有哪些差异呢?本文整理分享给大家: 一.bash变量类型: ...

  4. Linux bash中的变量分类

    1.本地变量 VAR=XYZ 2.局部变量 local VAR=XYZ 3.环境变量 在子shell中可以起作用 export VAR=XYZ 4.位置变量 $0 脚本名本身 $1 第一个参数 $2 ...

  5. bash中声明变量方法

    bash提供了declare命令来声明变量,该命令的基本语法如下: declare attribute variable      其中,attribute表示变量的属性,常用的属性有如下所述.   ...

  6. bash 中的变量可以这么用

    举个例子: t.sh ====================== #!/bin/bash ./a.sh ./b.sh ======================= a.sh =========== ...

  7. 手把手教你 bash中给变量赋值时 ' 和 " 和 ` 和 $() 的使用

    1.赋值指令 var='变量内容' var="变量内容" var=`command` var=$(command) var=变量内容 2.格式要求 =两边不能有空白字符 错误示例 ...

  8. Bash简明教程--变量

    1. 前言 Bash是一门流行在*nix系统下的脚本语言.作为一门脚本语言,变量是一门语言的基本要素,在这篇教程中,我们将学习Bash中的变量是怎么表示的,以及变量相关的一些语法规则. 2. Bash ...

  9. bash中一些基础知识

    bash是linux操作系统的shell.以下是Multi-Perspective Sentence Similarity Modeling论文实现时碰到的一个bash: #!/bin/bash py ...

随机推荐

  1. 自动装配[@Autowired]的歧义性

    在使用@Autowired自动装配时,如果一个接口有多个实现类,那么自动装配就会出现错误,因为Spring无法判断到底要装配哪个实现类实例(bean). 1.可以使用@Qualifier(" ...

  2. 使用using释放资源

    using关键字 using 关键字可以用来导命名空间,与java中的import类似. 我使用using的地方 using(SqlConnection con=new SplConnection(c ...

  3. 关于refs/for/ 和refs/heads/

    1.     这个不是git的规则,而是gerrit的规则, 2.     Branches, remote-tracking branches, and tags等等都是对commite的引用(re ...

  4. C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 访问频率限制功能实现、防止黑客扫描、防止恶意刷屏

    很多软件组件,大家都能想到了,大家也能做出来,但是成熟稳定.可靠.易用.功能全面,可信任,可相信,可开源就不是很容易,需要树立良好的口碑才可以. 1:往往会有黑客,进行撞库挖掘漏洞,很多系统的账户有可 ...

  5. Binder理解

    native takepicture -> camera -> ICamera: class bpbinder: transact -> BpBinder: transact -&g ...

  6. c语言考前最后一天

    明天就是考验这1个多月学习c语言的总结了,所以今天是个重要的日子,明天是个神圣的日子. 但是我还很多地方不明白,特别是函数,循环,这两个都是c语言最重要的,但我却没学好,上课还 时不时走神所以现在学的 ...

  7. Caliburn.Micro学习笔记(一)----引导类和命名匹配规则

    Caliburn.Micro学习笔记目录 用了几天时间看了一下开源框架Caliburn.Micro 这是他源码的地址http://caliburnmicro.codeplex.com/ 文档也写的很详 ...

  8. Prototype原型(创建型模式)

    依赖关系的倒置:抽象不应该依赖于实现的细节,实现细节应该依赖于抽象. 原型模式的定义 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.prototype模式允许一个对象再创建另外一个可 ...

  9. 【JavaScript】Html form 提交表单方式

    源:http://blog.csdn.net/wang02011/article/details/6299517 1.input[type='submit'] 2.input[type='image' ...

  10. Lua和C++交互详细总结

    转自:http://cn.cocos2d-x.org/tutorial/show?id=1474 一.Lua堆栈 要理解Lua和C++交互,首先要理解Lua堆栈. 简单来说,Lua和C/C++语言通信 ...