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. 一个简单的统计图像主颜色的算法(C#源代码)

    前段日子有朋友咨询了下分析图像主颜色的算法,我对这一块也没有什么深入的研究,参考了一些小代码,然后自己写了一个很简单的小工具,现共享给大家. 界面截图如下: 算法的原理很简单,就是统计出图像中各种颜色 ...

  2. Manacher's algorithm

    Manacher's algorithm 以\(O(n)\)的线性时间求一个字符串的最大回文子串. 1. 预处理 一个最棘手的问题是需要考虑最长回文子串的长度为奇数和偶数的情况.我们通过在任意两个字符 ...

  3. 聊天室(Java实现)

    功能: 登录 若用户账号不存在,弹出错误 若用户密码错误,弹出错误 若用户账号已在线,弹出错误 注册 若用户已注册,弹出错误 聊天室 多人聊天,类似QQ里的群. 点击右侧的在线用户,可进行一对一聊天. ...

  4. 4.bootstrap练习笔记-内容区块

    bootstrap练习笔记-内容区块 1.bootstrap中,采用的全部是div布局,把你的内容首先要包含在一个大的DIV区块当中 2.然后再写一个div.container,这个div里面存放真正 ...

  5. 使用 v-cloak 防止页面加载时出现 vuejs 的变量名

    使用 vuejs 做了一个简单的功能页面,逻辑是,页面加载后获取当前的经纬度,然后通过 ajax 从后台拉取附近的小区列表.但是 bug 出现了,在显示小区列表之前,会闪现小区名对应的 vuejs 变 ...

  6. 物联网平台设计心得:DateTimePicker实现选择联动

    所谓的选择联动,就是指,当我DateTimePicker1选择2月4号的时候,我DateTimePicker2只能选择2月4号和2月5号两天,当然你可以自行规定要选择的日期.这在一些图表查询条件里面是 ...

  7. docfx开源啦

    废话不多说了,直接上地址: 源代码: https://github.com/dotnet/docfx 文档: http://dotnet.github.io/docfx/ clone git clon ...

  8. Android开发自学笔记(Android Studio)—4.2TextView及其子类

    一.引言 TextView是我们最常用的一个控件了,它类似于C# Winform程序中的Lable,Java Swing编程中的JLable,不过相对功能更强大些,但从功能上看,它其实就是个文字编辑器 ...

  9. SQL数据库分配权限

    打开SQL-Server管理工具->安全性->登陆名->右键(新建登陆名) 输入相应的信息(这里要去掉强制实施密码策略,强制密码过期,否则用户在下次登录时必须修改密码) 用户映射-& ...

  10. jQuery之Ajax--底层接口

    1. $.ajax()方法:是jQuery最底层的Ajax实现.它的结构为:$.ajax(options).该方法只有一个参数,但在这个对象里面包含了$.ajax()方法所需要的请求设置以及回调函数等 ...