当前位置:   article > 正文

Shell—关于source,bash如何执行_若以source来执行脚本,则代表在 填空 1 的bash内运行

若以source来执行脚本,则代表在 填空 1 的bash内运行

  通过对一个脚本问题的分析,发现了自己的一个知识误区,我想,有必要写篇博客总结一下。

关于source

  source test.sh 与 . test.sh 二者用法相同。是读取脚本test.sh中的内容,依次在当前脚本中执行,且不会建立新的子shell去执行。被引用脚本 test.sh中的所有新建、改变变量的语句都会保存在当前shell里面,并被执行。
   一般,在被引用脚本 test.sh中会封装一个公用的代码或是校验类的接口函数,供其他脚本调用。
  尤其需要理解区分的是,source不同于 “./ test.sh” 和 “/bin/bash test.sh”,此二者有本质的区别,后者是在当前脚本中执行子shell,会产生新的进程来执行,而且在父shell中不能调用子shell中包含的函数接口。而source之后的文件内容已被加载到当前脚本中,就可以调用其内部定义的函数。

本文测试的 test.sh 脚本如下,作为被引用的脚本文件

#!/bin/bash
echo "Enter test.sh"
function func1()
{
    echo "enter function 1"
}
function func2()
{
    echo " $1: source $2 "
    echo "Exit test.sh"
    exit 0
}
echo "Exit test.sh ~~~"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

当执行exec.sh脚本时,exec.sh 中执行 ./test.sh,结果如下
@xiaoma
验证:在父shell中不能调用子shell中包含的函数接口

bash如何执行

  通过分析源码,bash是把执行的shell中的内容存储到hash表。source作为内置命令,其实现也在bash源码中(builtins/source.def 内置方法的文件都在builtins目录),当bash执行到source命令时,会将引用的脚本文件内容读入一个缓冲区,保存于一段临时开辟的hash表中,然后通过调用函数push_scope(VC_BLTNENV, tempporary_env)push到当前脚本的上下文中,在哪里引用,就在哪加入当前脚本的上下文。最后,bash依次往下执行当前脚本。
本文中测试的当前脚本 source.sh 如下:

#!/bin/bash

if [ $# -ne 1 ]
then
	echo "Usage: $0 source_file"
fi
source_file=$1
echo "First source $source_file"
source $source_file
echo "Exec func1 function"
func1
echo "Second source $source_file"
. $source_file
echo "Exec func2 function"
func2 "$0 $source_file"
echo "Exit source.sh"  # func2 中存在 exit 0, bash执行不到这里,因此不会打印
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在命令行执行 ./source.sh test.sh 打印如下:
@xiaoma
Bash执行过程如下:
@xiaoma
从上图看得出来,每一次source,当前执行脚本中就会重新读取被引用脚本 test.sh的内容并执行,因此在实际写shell时,要避免多次source一个文件,此处是为了示例source执行的过程。

  对于简单的命令,要更加理解到位,不然还是会犯一些低级的小错误。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/243901
推荐阅读
相关标签
  

闽ICP备14008679号