Bash中source/fork/exec的相关知识


我记得在我第一次翻看《Unix环境高级编程》的时候,里面有讲过fork和exec的知识(APUE这本身书很多知识应该都讲了,但是以我现在的水平还理解/体会不到罢了),但那时候啥也不懂,看了也就看了,只有个大概的印象,现在在实际工作编码过程中碰到问题了才后悔当时为什么不学扎实一点?

这篇文章标题起的比较含糊,因为我现在的知识水平无法完全解释、说明 source/fork/exec 中包含的知识点,只能一点一点来吧,逐步加深理解。

=Start=

=source/fork/exec三者之间有什么区别=

# source
所谓source,就是让 script 在当前 shell 内执行、 而不是产生一个 sub-shell 来执行。 由于所有执行结果均在当前 shell 内执行,所以在当前 script 中的其它地方可以用到执行结果中的变量和值。举例如下:

[root@sec-tools script_s]# pwd
/root/script_s
[root@sec-tools script_s]# cat cd_2_tmp.sh
#!/bin/bash
cd /tmp
[root@sec-tools script_s]# source cd_2_tmp.sh
[root@sec-tools tmp]# pwd
/tmp

# fork
正常来说,当我们执行一个 shell script 时(比如在shell命令行中执行”./a.sh”),其实是先产生一个 sub-shell 的子进程, 然后由 sub-shell 再去执行命令行的子进程。因为环境变量只能从父进程到子进程单向传递(换句话说:在子进程中环境如何变更,均不会影响父进程的环境),所以,会有下面的现象:

[root@sec-tools script_s]# pwd
/root/script_s
[root@sec-tools script_s]# cat cd_2_tmp.sh
#!/bin/bash
cd /tmp
[root@sec-tools script_s]# ./cd_2_tmp.sh
[root@sec-tools script_s]# pwd
/root/script_s

# exec
exec 和 source 一样,也是让 script 在同一个进程上执行,但是原有进程在 script 执行结束之后自己也被结束了。举例如下:

[root@sec-tools script_s]# pwd
/root/script_s
[root@sec-tools script_s]# cat cd_2_tmp.sh
#!/bin/bash
cd /tmp
[root@sec-tools script_s]# exec cd_2_tmp.sh
-bash: exec: cd_2_tmp.sh: not found
[root@sec-tools script_s]#
[root@sec-tools script_s]# exec ./cd_2_tmp.sh
Connection to x.y.z.x closed.

综上,原有进程是否会被终止,是exec与source/fork的最大差异。

参考内容:

=subshell的一些知识点=

=EOF=

, ,

《 “Bash中source/fork/exec的相关知识” 》 有 3 条评论

  1. 我们可以使用env命令来查看当前bash已经定义的环境变量。set命令不加任何参数可以查看当前bash环境中的所有变量,包括环境变量和私有的一般变量。一般变量的定义方法:
    `
    $ aaa=1000
    $ echo $aaa
    1000
    $ env | grep aaa
    $ set | grep aaa
    aaa=1000
    `
    上面我们定义了一个变量名字叫做aaa,我们能看到在set命令中可以显示出这个变量,但是env不显示。export命令可以将一个一般变量变成环境变量。
    `
    $ export aaa
    $ env | grep aaa
    aaa=1000
    $ set | grep aaa
    aaa=1000
    `
    export之后,env和set都能看到这个变量了。一般变量和环境变量的区别是:一般变量不能被子进程继承,而环境变量会被子进程继承。

  2. bash会在以下情况下打开一个subshell执行命令:

    • 使用&作为命令结束提交了作业控制任务时。
    • 使用|连接的命令会在subshell中打开。
    • 使用()封装的命令。
    • 使用coproc(bash 4.0版本之后支持)作为前缀执行的命令。
    • 要执行的文件不存在或者文件存在但不具备可执行权限的时候,这个执行过程会打开一个subshell执行。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注