前言

Shell脚本执行的方式有很多种,虽然说不管什么方式,脚本都能运行,但是不同的方式却有不同的效果,这点尤其在多脚本中特别重要,下面就通过一些案例简单了解一下各种姿势的效果!

一、调用Shell脚本的方式

1.1、常用方式

  1. $shell $File
  2. source $File
  3. exec $File
  4. ./$File

变量解析:

$shell:表示通过指定shell解析器进行调用,常见的有bash及sh等

$File:表示我们的脚本文件名

1.2、主要区别

使用不同的调用方式,会对初始脚本的变量及执行流程,进程号有一定的影响,所以下面就分别以脚本PID,变量来说明

二、找不同

2.1、脚本内容

本次实验需要两个脚本,在这里就简单分为1.sh和2.sh,具体脚本内容如下:

首先是1.sh,这个比较好理解,就是我

  • 打印1.sh所在的进程PID号,
  • 打印调用1.sh的时候,显示的进程文件名,
  • 声明一个全局变量
  • 从2.sh文件继承一个全局和局部变量值并打印
$ cat 1.sh
#!/bin/bash
echo -e "当前PID为  $$"
echo "当前文件名为 $0"
export a="1.sh的全局变量获取成功"
d="1.sh的局部变量获取成功"
echo "从2.sh继承一个全局变量 $b"
echo "从2.sh继承一个局部变量 $c"

然后2.sh这个需要一点点Shell脚本基础才好理解,简单来说就是,我定义了多个函数(不调用就只是摆设),然后从执行方式获取我需要调用的方式,这个值来自传参1,也就是执行脚本的时候,在后边加上的第一个参数 ,然后根据这个参数去调用对应的函数,以此达到不同的效果,后面则是打印2.sh这个脚本所在的进程PID,然后打印一个变量a(1.sh有声明,所以这个打印变量就是为了验证变量是否在两个脚本之间共享)

$ cat 2.sh
#!/bin/bash
##这是2
echo "当前PID $$"
export b="成功"
c="成功"
s(){
        source 1.sh
}
e(){
        exec ./1.sh
}
f(){
        ./1.sh
}
b(){
        bash 1.sh
}
se=$1
case $se in
        s)
                s;;
        e)
                e;;
        f)
                f;;
        b)
                b;;
esac
echo -e "当前PID $$"
echo $a
echo $d
echo "当前文件名为 $0"

2.2、开始验证

为了充分验证,在父脚本的执行上,我同样使用不同的方式执行

2.2.1、source调用

shell脚本调java Shell脚本调用_局部变量

从结果来看,使用s函数的时候,脚本进程PID和文件名都一样,并且局部和全局变量也成功继承了,也就是说,使用source调用脚本的时候,相当于两个脚本合二为一了,变成了一个脚本,父脚本可以获取子脚本的所有信息

 2.2.2、exec调用

在exec函数调用上就有点奇妙了,当使用source执行2.sh的时候,整个终端都会关闭,所以只能使用下面两个方式去运行父脚本

shell脚本调java Shell脚本调用_shell脚本调java_02

 从结果可以得出结论:

  • 当使用exec进行调用脚本的时候,被调用的脚本进程与父脚本是一致的
  • 子脚本只能继承父脚本的全局变量,无法继承局部变量值
  • 调用了子脚本之后,父脚本之后的语句就不会被执行,不管父脚本的执行方式是怎样的,结果都一样!

2.2.3、./$File

shell脚本调java Shell脚本调用_全局变量_03

从结果来看,可以得出以下结论:

  • 2.sh(父脚本)与1.sh(子脚本)的进程是不一样的
  • 子脚本只能继承父脚本的全局变量,无法继承局部变量值(无论主脚本使用怎样执行方式)
  • 父脚本能获取子脚本的所有变量(前提是使用source执行父脚本,否则无法获取子脚本的局部变量)
  • 父脚本调用子脚本结束之后会继续执行后面的语句

2.2.4、$shell调用

shell脚本调java Shell脚本调用_局部变量_04

从结果来看,可以得出以下几点结论:

  • 父脚本的进程与子脚本进程ID不一样
  • 子脚本无法获取父脚本的局部变量(无论使用怎样的执行及调用方式)
  • 父脚本可以获取子脚本的所有变量(前提是主脚本使用source执行,否则只能获取全局变量)
  • 能准确识别出到当前脚本文件名

 

三、总结

从不同的方式得出的结果来看,每一种方式都有其不同的特点,所以需要充分考虑其特点,才能更好的写好Shell脚本,不同的特点必然有其不用的应用场景,变量声明的使用,需要根据其性质去决定要设置全局还是局部,正确的用好调用方式,才能得到更好的效果,执行方式也非常重要