已复制
全屏展示
复制代码

linux 命令 exec 到底有什么作用

· 2 min read

我们在看别人写的脚步时,你可能会发现别人启动程序时喜欢在命令前面添加一个 exec 命令,它的作用其实是:

将当前的 shell 程序替换为指定的命令或程序,命令或程序不会在新的进程中执行(不会创建新的pid,直接使用当前 shell 的 pid),这意味着原来的 shell 程序将被终止,并且执行的命令将在当前 shell 进程中运行。

这样做的好处在于可以在不创建新的子进程的情况下,直接在当前 shell 进程中执行指定的命令,从而节省了系统资源并且能够更高效地执行命令。另外,在使用 supervise 时通常使用 exec 来保证监控 run 脚本的进程。

注意:在 exec 这一行命令后面的命令将不会执行,因为新的命令已经替换了当前shell进程,也就是新命令复用了当前 shell 的 pid 以及一些环境。

使用示例

  • a.sh 负责打印传给它的第一个参数,同时打印自己的 PID
#!/bin/bash
echo "$1 this is in a.sh my PID:$$"
  • x.sh 首先输出自己的PID,然后分别不使用 exec 和使用 exec 去执行 a.sh 脚本
#!/bin/bash

echo "x.sh PID:$$"
bash ./a.sh " not exec"
exec bash ./a.sh "with exec"
echo "line will never be executed."

执行 x.sh 脚本得到如下输出

$ bash ./x.sh 
x.sh PID:376124
 not exec this is in a.sh my PID:376125
with exec this is in a.sh my PID:376124

PID 376124 是 x.sh 进程的,当没有使用 exec 执行 a.sh 脚本时,创建了一个新的进程 PID 为376125,执行完 a.sh脚本后 376125 进程退出。然后使用 exec 执行 a.sh 脚本,a.sh 会直接在 376124 进程中运行而不会创建新的进程,由于原来的 x.sh进程已经被替换了,所以最后一行 echo 不会被执行。

验证旧的进程被替换

  • test1.sh
#!/bin/bash
exec bash ./test2.sh
  • test2.sh
#!/bin/bash
sleep 999
  • 执行 test1.sh 脚本,然后在另外一个终端使用 ps 查看进程
# 执行 test1.sh
bash test1.sh


# 在另外一个终端查看进程
# 可以看到原来的 test1.sh 已经没有了,只有一个 test2.sh 和 sleep 进程
$ ps aux | grep -E "test|sleep"
yzy       376356  0.0  0.0   7760  3324 pts/0    S+   18:27   0:00 bash ./test2.sh
yzy       376357  0.0  0.0   6188  1056 pts/0    S+   18:27   0:00 sleep 999
yzy       376544  0.0  0.0   7004  2104 pts/1    S+   18:27   0:00 grep --color=auto -E test|sleep
🔗

文章推荐