exec 跟 source 差在哪?-- Shell十三问<第六问>

这次先让我们从 CU Shell 版的一个实例贴子来谈起吧:

例中的提问是:

cd /etc/aa/bb/cc 可以执行

但是把这条命令写入 shell 时 shell 不执行!这是什么原因呀!

我当时如何回答暂时别去深究,先让我们了解一下进程(process)的观念好了。首先,我们所执行的任何程序,都是由父进程(parent process)所产生出来的一个子进程(child process),子进程在结束后,将返回到父进程去。此一现像在 Linux 系统中被称为 fork 。

当子进程被产生的时候,将会从父进程那里获得一定的资源分配、及(更重要的是)继承父进程的环境!

让我们回到上一章所谈到的"环境变量"吧:

  • 所谓环境变量其实就是那些会传给子进程的变量。简单而言,"遗传性"就是区分本地变量与环境变量的决定性指标。

然而,从遗传的角度来看,我们也不难发现环境变量的另一个重要特征:

  • 环境变量只能从父进程到子进程单向继承。换句话说:在子进程中的环境如何变更,均不会影响父进程的环境。

命令脚本(shell script)

接下来,再让我们了解一下命令脚本(shell script)的概念。

所谓的 shell script 讲起来很简单,就是将你平时在 shell prompt 后所输入的多行command line 依序写入一个文件去而已。

其中再加上一些条件判断、互动界面、参数运用、函数调用、等等技巧,得以让 script 更加"聪明"的执行,但若撇开这些技巧不谈,我们真的可以简单的看成 script 只不过依次执行预先写好的命令行而已。

再结合以上两个概念(process + script),那应该就不难理解如下这句话的意思了:

  • 正常来说,当我们执行一个 shell script 时,其实是先产生一个 sub-shell 的子进程,

    然后 sub-shell 再去产生命令行的子进程。

    然则,那让我们回到本章开始时所提到的例子再从新思考:
cd /etc/aa/bb/cc 可以执行

但是把这条命令写入 shell 时 shell 不执行!这是什么原因呀!

我当时的答案是这样的:

因为,一般我们跑的 shell script 是用 sub shell 去执行的。从 process 的观念来看,是 parent process 产生一个child process 去执行,当 child 结束后,会返回 parent ,但 parent 的环境是不会因 child 的改变而改变的。

所谓的环境元数很多,凡举 effective id, variable, workding dir 等等...

其中的 workding dir ($PWD) 正是楼主的疑问所在:

当用 sub shell 来跑 script 的话,sub shell 的 \(PWD 会因为 cd 而变更,但当返回 primary shell 时,\)PWD 是不会变更的。

能够了解问题的原因及其原理是很好的,但是?如何解决问题恐怕是我们更感兴趣的!是吧?那好,接下来,再让我们了解一下 source 命令好了。

source 概念

  • 所谓 source 就是让 script 在当前 shell 内执行、而不是产生一个 sub-shell 来执行。

由于所有执行结果均于当前 shell 内完成,若 script 的环境有所改变,当然也会改变当前环境了!

因此,只要我们要将原本单独输入的 script 命令行变成 source 命令的参数,就可轻易解决前例提到的问题了。

比方说,原本我们是如此执行 script 的:

./my.script
现在改成这样即可:
source ./my.script
或:
. ./my.script

说到这里,我想,各位有兴趣看看 /etc 底下的众多设定文件,应该不难理解它们被定议后,如何让其它 script 读取并继承了吧?

若然,日后你有机会写自己的 script ,应也不难专门指定一个设定文件以供不同的 script。

到这里,若你搞得懂 fork 与 source 的不同,那接下来再接受一个挑战:

那 exec 又与 source/fork 有何不同呢?

哦... 要了解 exec 或许较为复杂,尤其扯上 File Descriptor 的话...

不过,简单来说:

  • exec 也是让 script 在同一个进程上执行,但是原有进程则被结束了。也就是简而言之:原有进程会否终止,就是 exec 与 source/fork 的最大差异了。

光是从理论去理解,或许没那么好消化,不如动手"实作+思考"来的印像深刻哦。

下面让我们写两个简单的 script ,分别命令为 1.sh 及 2.sh :

1.sh
#!/bin/bash
A=B
echo "PID for 1.sh before exec/source/fork:$$"
export A
echo "1.sh: \$A is $A"
case $1 in
exec)
echo "using exec..."
exec ./2.sh ;;
source)
echo "using source..."
. ./2.sh ;;
*)
echo "using fork by default..."
./2.sh ;;
esac
echo "PID for 1.sh after exec/source/fork:$$"
echo "1.sh: \$A is $A" 2.sh
#!/bin/bash
echo "PID for 2.sh: $$"
echo "2.sh get \$A=$A from 1.sh"
A=C
export A
echo "2.sh: \$A is $A"
然后,分别跑如下参数来观察结果: $ ./1.sh fork
$ ./1.sh source
$ ./1.sh exec

好了,别忘了仔细比较输出结果的不同及背后的原因哦...

exec 跟 source 差在哪?-- Shell十三问<第六问>的更多相关文章

  1. ( ) 与 { } 差在哪?-- Shell十三问<第七问>

    ( ) 与 { } 差在哪?-- Shell十三问<第七问> 先说一下,为何要用 ( ) 或 { } 好了. 许多时候,我们在 shell 操作上,需要在一定条件下一次执行多个命令,也就是 ...

  2. > 与 < 差在哪?-- Shell十三问<第十一问>

    > 与 < 差在哪?-- Shell十三问<第十一问> 谈到 I/O redirection ,不妨先让我们认识一下 File Descriptor (FD) .程序的运算,在 ...

  3. && 与 || 差在哪?-- Shell十三问<第十问>

    && 与 || 差在哪?-- Shell十三问<第十问> 好不容易,进入两位数的章节了... 一路走来,很辛苦吧?也很快乐吧? 在解答本章题目之前,先让我们了解一个概念:r ...

  4. $(( )) 与 $( ) 还有${ } 差在哪?-- Shell十三问<第八问>

    $(( )) 与 \(( ) 还有\){ } 差在哪?-- Shell十三问<第八问> 我们上一章介绍了 ( ) 与 { } 的不同,这次让我们扩展一下,看看更多的变化:$( ) 与 \( ...

  5. var=value?export前后差在哪?-- Shell十三问<第五问>

    var=value?export前后差在哪?-- Shell十三问<第五问> 这次让我们暂时丢开 command line ,先来了解一下 bash 变量(variable)吧.所谓的 变 ...

  6. " "( 双引号) 与 ' '( 单引号) 差在哪?-- Shell十三问<第四问>

    " "( 双引号) 与 ' '( 单引号) 差在哪?-- Shell十三问<第四问> 经过前面两章的学习,应该很清楚当你在 shell prompt 后面敲打键盘.直到 ...

  7. 别人 echo 、你也 echo ,是问 echo 知多少?-- Shell十三问<第三问>

    别人 echo .你也 echo ,是问 echo 知多少?-- Shell十三问<第三问> 承接上一章所介绍的 command line ,这里我们用 echo 这个命令加以进一步说明. ...

  8. [^ ] 跟 [! ] 差在哪?-- Shell十三问<第十四问>

    [^ ] 跟 [! ] 差在哪?-- Shell十三问<第十四问> 这道题目说穿了, 就是要探讨 Wildcard(通配符)与 Regular Expression(正则表达式)的差别的. ...

  9. shell十三问

    1) 为何叫做 shell ?在介绍 shell 是甚幺东西之前,不妨让我们重新检视使用者与计算机系统的关系:图(FIXME)我们知道计算机的运作不能离开硬件,但使用者却无法直接对硬件作驱动,硬件的驱 ...

随机推荐

  1. Masterboxan INC是你靠近财富的最佳选择

    Masterboxan INC万事达资产管理有限公司(公司编号:20151264097)是一家国际性资产管理公司,主要提供外汇.证券.投资管理和财富管理等金融服务,其在投资方面一直倡导组合型投资构建稳 ...

  2. 「NGK每日快讯」12.15日NGK公链第42期官方快讯!

  3. redis环境配置

    1.解压redis压缩包 tar -zxvf redis-5.0.7 2. 基本环境安装 进入解压后的目录 安装yum(cents需要 其它版本Linux可能不适用yum用其它工具)ubuntu:ap ...

  4. 谈一下HashMap的底层原理是什么?

    底层原理:Map + 无序 + 键唯一 + 哈希表 (数组+Entry)+ 存取值 1.HashMap是Map接口的实现类.实现HashMap对数据的操作,允许有一个null键,多个null值. Co ...

  5. SpringBoot读取资源目录下的文件

    需要读取resources目录下的文件,那么方法如下: 假设在资源目录下的template目录下有一个文件a.txt,获取到文件流的方式 InputStream stream = this.getCl ...

  6. Virtual DOM 简直就是挥霍

    彻底澄清"Virtual DOM 飞快"的神话. 注意:原文发表于2018-12-27,随着框架不断演进,部分内容可能已不适用. 近年来,如果你有使用过 JavaScript 框架 ...

  7. wxWidgets源码分析(5) - 窗口管理

    窗口管理 所有的窗口均继承自wxTopLevelWindows: WXDLLIMPEXP_DATA_CORE(wxWindowList) wxTopLevelWindows; wxTopLevelWi ...

  8. Linux下制作Windows启动U盘的工具

    Linux下制作Windows启动U盘的工具 很多人说Linux下制作Windwos启动盘要用GRUB4DOS建立引导,其实不用,有专门的工具的,就像Windows下有Rufus制作Linux启动U盘 ...

  9. STM32 ADC详细篇(基于HAL库)

    一.基础认识 ADC就是模数转换,即将模拟量转换为数字量 l  分辨率,读出的数据的长度,如8位就是最大值为255的意思,即范围[0,255],12位就是最大值为4096,即范围[0,4096] l  ...

  10. @WebFilter("")配置servlet访问出现404的原因

    配置 servlet 一共有两种方式 直接在web.xml中配置name 和 url-parttern 使用注解配置servlet 使用注解的方式配置servlet是在servlet3.0之后新增的特 ...