脚本执行指令辨析(source , . , sh , bash , ./)

本文最后更新于:2024年12月20日 下午

大体上来说,脚本执行指令可以分为两类:子程序内执行父程序内执行。如果再分得细些的话,那么子程序内执行又可以分为直接指令下达以bash程序执行这两种。

父程序与子程序

当你登陆 Linux 并取得一个 bash 之后,你的 bash 就是一个独立的程序,被称为 PID 的就是。 接下来你在这个 bash 底下所下达的任何命令都是由这个 bash 所衍生出来的,那些被下达的命令就被称为子程序了[1]。父程序与子程序之间的关系可以用以下的图示来表明:

图1 父程序与子程序

如果在当前bash中再开启一个新的bash时,那么当前的bash则成了父程序,而新开的bash就是子程序。

1
2
3
bash        #进入子程序

exit #退出子程序

二者的特点是:
- 父程序的自定义变量不会被子程序继承,仅环境变量可以被子程序继承 - 子程序结束后,子程序内的各项变量或动作将会结束而不会传回父程序

使用export指令将自定义变量转化为环境变量后,这个变量就能够被子程序继承了。

1
export 变量名称

子程序内执行

顾名思义,以此类指令执行的脚本将会在子程序内执行,不会继承父程序的变量。子程序内执行又分为直接指令下达以bash程序执行这两种[2]

直接指令下达(绝对路径、相对路径与$PATH)

如果以直接指令下达的方式运行脚本,需要脚本具有可执行权限,因此,在执行脚本前还需要额外加一句下面的指令:

1
chmod a+x scripts.sh

以直接指令下达的三种方式如下所示:

  • 以绝对路径的形式执行:例如指令/bin/ls /etc,将会列出/etc目录下的文件信息,前面的/bin/ls就是以绝对路径的形式执行了名为ls的脚本指令(没错,ls等常见的指令其实就是一个个脚本程序哦~)。

  • 以相对路径的形式执行:如果你此时正处于/bin目录下,那么你可以直接使用指令./ls /etc来实现同样的功能,./就是“当前目录”的意思。
    >由于指令的执行需要变量(bash章节才会提到)的支持,若你的可执行文件放置在本目录,并且本目录并非正规的可执行文件目录(/bin, /usr/bin等为正规),此时要执行指令就得要严格指定该可执行文件。“./”代表“本目录”的意思,所以“./run.sh”代表“执行本目录下, 名为run.sh的文件”啰![3]

  • 利用环境变量PATH执行:透过$PATH这个变量的顺序搜寻到的第一个命令来运行。如果将scripts.sh放入PATH变量指定的工作目录下,我们就可以直接输入scripts.sh来执行这个脚本!

当然,使用alias设置别名也能实现同样的效果,不过我认为这只是一个“小花招”,就没有把它列为第四种方式。

看到这里,有的同学可以会产生一个疑问:上面提到的ls等脚本指令,我在实际使用的时候都是直接使用的,根本就没有采用什么绝对路径、相对路径和所谓的PATH变量啊,那它到底是怎么执行的?

好,问到点子上了,我们分别看一下ls指令的执行顺序和PATH变量的具体内容:
图2 ls指令 了解了吗?原来ls指令是一个别名,而且它所存在的路径/usr/bin也被记录在PATH变量内了。(/usr/bin/bin相当于快捷方式一样的存在;--color=auto这一参数选项表示对打印出来的信息加上一定的颜色区分)

以bash程序执行(bash scripts.sh与sh scripts.sh)

与上一种直接指令下达方式不同,“以bash程序执行”的的这种直接指令下达并不需要脚本程序具有可执行权限。脚本执行的方式也非常简单,如下:

1
2
3
bash scripts.sh
#或者使用下面的方式
sh scripts.sh

现在举个例子瞧瞧吧:

1
2
3
4
5
#! /bin/bash
read -p "please input your firstname" fir_name
read -p "please input your lastname" la_name

echo “your full name is ${fir_name}${la_name}
最后运行的结果如下:

图3 sh02.sh在子程序内执行 我们可以发现在脚本执行完毕后无法在父程序中打印出脚本中的两个变量。

父程序内执行(source与.)

顾名思义,以父程序内执行的形式执行脚本,那么脚本执行的环境就在父程序,就像坐高铁,一路畅通。
这类指令有两个,分别是source.,使用方式如下:

1
2
3
source scripts.sh   #scripts.sh不需要可执行权限

. scripts.sh #scripts.sh同样不需要可执行权限

值得一提的是,source.这两个都是shell自带的内建命令,这两个命令是等价的关系。也就是说这两条命令的执行是完全一样的。使用 type source 和 type . 可以看出它们都是内建命令;使用 help source 和 help . 也可以看出这两个命令的作用一模一样。因此,这两个命令是等价的,用哪个都行[4]

图4 scripts.sh在父程序内执行

我们同样使用上一个例子进行测试:

图5 sh02.sh在父程序内执行

我们可以发现这次在脚本执行完毕后可以在父程序中打印出脚本中的两个变量。这也是为啥我们有时需要不注销系统而要让某些写入~/.bashrc的配置生效时,使用source ~/.bashrc而不是使用sh ~/.bashrc[5]


脚本执行指令辨析(source , . , sh , bash , ./)
http://example.com/2024/06/21/脚本执行指令辨析/
作者
叶逸昇
发布于
2024年6月21日
许可协议