Bash源码分析

Posted 云开源

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bash源码分析相关的知识,希望对你有一定的参考价值。


点击上方 “公众号” 可以订阅哦!


引言

Bash源码分析(1)


Bash这个程序作为一个linux的用户,用的实在太频繁了,但一般局限于会用就结束了,一直没机会研究bash本身的原理。因工作需要,调试一个bash的cpu冲高问题,趁此机会对bash的源码做了一些研究,希望能对大家有点帮助。


 linux的各种主流shell介绍

Bash源码分析(1)


现在一般使用的shell有sh,bash和csh这几种,我们这里主要说的是bash,其他shell的源代码逻辑也差不多。


bash使用到的主要数据结构介绍

Bash源码分析(1)

1

COMMAND


Bash源码分析(1)


COMMAND是所有数据结构的纲,从这里可以看出一个bash实际能执行的语句有14种,分别位for,case,while,fi,connection,simple_com,function,group,select,arith,cond,arith_for,subshell,coproc,其中select,arith,cond,arith_for这4个命令需要打开对应的编译开关之后才能执行。


除了下面的这个union外,另外几个属性分别对应命令类型,行号和执行环境控制参数。其中控制参数有很多,每个控制参数占用一个bit位,包括是否启动子shell,是否忽略exit值等。


Bash源码分析(1)


这些flag可以在bash启动shell脚本时设置,或者在shell脚本内部调用set指令来设置,一般用户不怎么关注,高阶用户可以看看:


Bash源码分析(1)


2

FOR_COM


Bash源码分析(1)


FOR_COM对应的shell语句是for name in map_list; do action; done


从结构体定义可以看出,除了和COMMAND相同的flags和行号外,for语句是有一个变量名,一个列表和一个递归的COMMAND组成的,实际for循环执行过程中也是将列表中的每个元素拿出来赋值给变量名,并执行action中的脚本段。


从这里的flags,可以看出,每条命令的flags是可以单独设置的,本条命令设置的控制参数可以不影响其他命令的控制参数。


3

CASE_COM


Bash源码分析(1)


对照下面的脚本,可以看出,先判断一个变量,变量判断晚走到复合语句clauses,注意clause最终实现的时候是一个单向链表,链表中每个元素由一个样式的列表和一个执行体action来组成。


Bash源码分析(1)


bash脚本的执行过程分析

Bash源码分析(1)


一个环境上多个sh的cpu占用达到99%,但实际通过ps看,这个sh并没有带任何参数,如果想要知道这个sh在干什么活,为何会一直冲高,还是gdb调试一下比较靠谱(还有一种可选的方法是不断的敲 cat /proc/*/stack 来反复查看堆栈,多敲敲之后总能抓到几次上下文,其中*换成对应进程的pid)。


通过下面的调试,可以看到当前执行是一个简单命令(cm_simple),通过p *command->value->Simple->words->word 看到当前执行的简单命令在字符串是true。


Bash源码分析(1)


重新运行,可以看到又跑到了一个简单命令,其命令是"i=i+1"(汗)。


Bash源码分析(1)


通过shell的进程号,查询进程的上下文,发现是从另外一个虚机链接过来的ssh,咨询环境负责人,该虚机是跑测试用例的,之前跑的测试用例不知道为何没有正常停止,测试用例确实就是简单的一行命令:


Bash源码分析(1)

Bash源码分析(1)


未完待续……

Bash源码分析(1)


以上是关于Bash源码分析的主要内容,如果未能解决你的问题,请参考以下文章

golang源码分析-编译

v73.02 鸿蒙内核源码分析(参考手册) | 阅读内核源码必备工具 | 百篇博客分析OpenHarmony源码

Mesos源码分析

Mybatis源码分析

Spring源码分析专题——目录

ARouter源码分析