Shell—关于source,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 ~~~"

当执行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执行不到这里,因此不会打印

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

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

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Caso_卡索

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值