0x01 示例

正常情况下,如果我们想要在shell脚本中执行一个命令,我们只用将该命令原样写到这个shell脚本中就好了。

但有时候我们会发现,在一些shell脚本中,在某个命令之前,会有一个exec,比如下图所示:

上图中,我们要在shell脚本中执行一个sleep命令,但在该命令之前,我们加了个exec,那这个exec有什么作用呢?

0x02 exec的作用

我们先看下exec对应的文档,看看官方是如何解释的。

因为exec是bash的一个内置命令,所以我们可以在bash中,用help命令,查询exec对应的文档。

上图文档的大致意思为,将shell替换为exec指定的命令,这个解释比较模糊,我们做几个实验具体看下。

0x03 实验

还是使用上面的那个脚本,不过我们先把exec去掉,然后执行。

在该脚本执行后,我们用ps命令查看和该脚本相关的进程树:

由上图可见,我们先在bash中执行了a.sh这个测试脚本,然后又在a.sh脚本中,执行了sleep命令。

该执行结果产生了上图中的进程树,即sleep进程的父进程为a.sh进程,a.sh进程的父进程为bash进程。

我们再把exec加回来,然后再执行该脚本,该次执行后,和a.sh脚本相关的进程树为:

看上图中,这次没有了a.sh进程,为什么呢?因为它被sleep程序替换掉了。

这就是exec的作用,它会告诉linux内核,直接在当前shell脚本进程中,加载并执行目标程序。

这一过程会覆盖掉原shell脚本进程中的各种代码和数据信息,使得原shell脚本进程立即停止运行,并转向执行目标程序代码。

exec命令本质上是执行了execve系统调用,如果想要了解该命令的具体细节,可以查看execve的man文档。

0x04 注意事项

因为exec会立即抹掉当前shell脚本进程中的各种数据,然后加载并执行目标程序代码,所以在exec命令之后,除了错误检查逻辑外,不应该再有其他逻辑,因为这些逻辑永远都不会被执行了。

看个例子:

看上图中,只输出了hello,并没有输出world,因为echo world命令写在了exec echo hello命令之后,它是不会被执行的。

0x05 其他

如果有对linux及linux内核感兴趣的,可以扫描右侧二维码添加我的微信。

另外,我开设了一门 linux内核启动流程源码分析 课程,有对内核源码感兴趣的,欢迎报名。