0x01 示例
正常情况下,如果我们想要在shell脚本中执行一个命令,我们只用将该命令原样写到这个shell脚本中就好了。
但有时候我们会发现,在一些shell脚本中,在某个命令之前,会有一个exec,比如下图所示:
![](/1-1.d53bbf88.png)
上图中,我们要在shell脚本中执行一个sleep命令,但在该命令之前,我们加了个exec,那这个exec有什么作用呢?
0x02 exec的作用
我们先看下exec对应的文档,看看官方是如何解释的。
因为exec是bash的一个内置命令,所以我们可以在bash中,用help命令,查询exec对应的文档。
![](/2-1.0ea8d1d1.png)
上图文档的大致意思为,将shell替换为exec指定的命令,这个解释比较模糊,我们做几个实验具体看下。
0x03 实验
还是使用上面的那个脚本,不过我们先把exec去掉,然后执行。
在该脚本执行后,我们用ps命令查看和该脚本相关的进程树:
![](/3-1.51ad9d85.png)
由上图可见,我们先在bash中执行了a.sh这个测试脚本,然后又在a.sh脚本中,执行了sleep命令。
该执行结果产生了上图中的进程树,即sleep进程的父进程为a.sh进程,a.sh进程的父进程为bash进程。
我们再把exec加回来,然后再执行该脚本,该次执行后,和a.sh脚本相关的进程树为:
![](/3-2.b8d8dcd6.png)
看上图中,这次没有了a.sh进程,为什么呢?因为它被sleep程序替换掉了。
这就是exec的作用,它会告诉linux内核,直接在当前shell脚本进程中,加载并执行目标程序。
这一过程会覆盖掉原shell脚本进程中的各种代码和数据信息,使得原shell脚本进程立即停止运行,并转向执行目标程序代码。
exec命令本质上是执行了execve系统调用,如果想要了解该命令的具体细节,可以查看execve的man文档。
0x04 注意事项
因为exec会立即抹掉当前shell脚本进程中的各种数据,然后加载并执行目标程序代码,所以在exec命令之后,除了错误检查逻辑外,不应该再有其他逻辑,因为这些逻辑永远都不会被执行了。
看个例子:
![](/4-1.10717688.png)
看上图中,只输出了hello,并没有输出world,因为echo world命令写在了exec echo hello命令之后,它是不会被执行的。
0x05 其他
如果有对linux及linux内核感兴趣的,可以扫描右侧二维码添加我的微信。
另外,我开设了一门 linux内核启动流程源码分析 课程,有对内核源码感兴趣的,欢迎报名。