简介

    这篇文章主要描述如何通过主脚本去调用其他脚本中的方法,调用的过程中可能出现哪些坑,如何避免。

        

目录

1. 主脚本调用其他脚本的方法

1.1. bash方法

1.2. source方法

2. 避坑技巧

2.1. 路径配置无效

2.2. source变量冲突

3. 总结


        

1. 主脚本调用其他脚本的方法

使用主脚本调用其他脚本通常使用2种方法:

  • bash 脚本名
  • source 脚本名

还有一种 . 脚本名 的方法与 source 脚本名 差不多,但偶尔会出现无法调用的问题,这里就不解释了。

1.1. bash方法

使用传统的 bash 方法就是在当前脚本中执行 bash 去调用另一个脚本。来看一下例子

【主脚本代码】

#!/bin/bash
echo "============= 我是主脚本, 准备去调用其他脚本 ============="

bash ./scr.sh    # 调用其他脚本

echo "============= 我是主脚本, 其他脚本已执行完成 ============="

【另一个脚本代码】

#!/bin/bash
echo "我是其他脚本"

来执行主脚本,看一下结果:可以正常调用

        

这种方法虽然可以调用另一个脚本,但另一个脚本却无法共享主脚本的变量

【主脚本代码】

#!/bin/bash
var=10    # 定义一个变量
echo "我是主脚本, 变量var的值是: ${var}"

bash ./scr.sh    # 调用其他脚本

 【另一个脚本代码】

#!/bin/bash
echo "我是其他脚本, 变量var的值是: ${var}"

主脚本中定义的变量无法作用到其他脚本中

        

虽然这里的变量无法作用到其他脚本,但可以通过传参的方式拿过去

 【主脚本代码】

#!/bin/bash
var=10
echo "我是主脚本, 变量var的值是: ${var}"

bash ./scr.sh "${var}"    # 向另一个脚本传递参数

 【另一个脚本代码】

#!/bin/bash
var="$1"    # 接收一个位置参数
echo "我是其他脚本, 变量var的值是: ${var}"

结果如下:参数传递成功

注意:这种方法只适用于少量参数

        

1.2. source方法

source 与 bash 方法完全不同,bash 是直接去执行另一个脚本,而 source 是将另一个脚本的代码读取过来。还记得为什么配置环境变量到 ~/.bashrc 后,需要执行 source ~/.bashrc 才生效吗,就是为了将 ~/.bashrc 中的配置信息读取到本地才能生效,所以使用 source 执行其他脚本文件也是同样的道理。

使用与上面同样的方法,在主脚本中配置一个变量,然后 source 另一个脚本

 【主脚本代码】

#!/bin/bash
var=10
echo "我是主脚本, 变量var的值是: ${var}"

source ./scr.sh    # 调用其他脚本

 【另一个脚本代码】

#!/bin/bash
echo "我是其他脚本, 变量var的值是: ${var}"

        

为什么说 source 是将另一个变量的代码读取到本地,看一下这个例子就明白了。

 【主脚本代码】

#!/bin/bash
echo "我是主脚本"

source ./scr.sh    # 调用其他脚本
Func    # 调用另一个脚本的函数

 【另一个脚本代码】

#!/bin/bash
# 只定义函数,不调用
Func(){
    echo "我是另一个脚本的函数Func"
    }

我们在主脚本中使用 source 另一个脚本后,在主脚本调用另一个脚本中的函数。而在另一个脚本中只定义函数,不调用。

  • 通过这两个例子可以确定,使用 source 后,两个脚本的变量和函数都可以共用。需要共享变量较多时,使用 source 最佳。

        

2. 避坑技巧

2.1. 路径配置无效

在平时写代码时,一般会指定一个当前路径。喜欢用 pwd 的伙伴注意了,这会出现问题。

  【主脚本代码】

#!/bin/bash
init_path=$(pwd)    # 使用pwd来定义当前路径
scr_path="${init_path}/scr.sh"  # 通过当前路径连接另一个脚本的路径

echo "我是主脚本"

source ${scr_path}    # 调用其他脚本

 【另一个脚本代码】

#!/bin/bash
echo "我是另一个脚本"

在当前路径下执行是没问题的

但如果我们当前是在另一个路径下,无法调用另一个脚本

看吧,报了一个找不到文件的错误,而且路径也不是我们希望的那个位置。这是因为脚本中使用 pwd 定义初始路径导致的问题,pwd 这个命令表示当前终端在哪个路径下,而不是脚本在哪个路径下,所以在执行时路径发生了变化。

        

要解决这个问题也非常简单,将 pwd 改成

init_path=$(dirname $0)    # dirname $0 表示脚本的目录

或者

init_path=$(dirname ${BASH_SOURCE})

使用 $0 后,主脚本只能使用 bash 执行,使用 source 报错

使用 ${BASH_SOURCE} 同时支持 bash 和 source

        

2.2. source变量冲突

在前面的《目录 1.2》中提到过,source 另一个脚本后,变量和函数是共享的,所以也会导致变量被修改。

   【主脚本代码】

#!/bin/bash
var=10

echo "我是主脚本, 当前var为: ${var}"

source ./scr.sh    # 调用其他脚本

echo "我是主脚本, 调用另一个脚本后, 当前var为: ${var}"

 【另一个脚本代码】

var=20
echo "我是另一个脚本, 这里的var为: ${var}"

由于变量共享,所以其他脚本的全局变量名与当前脚本的全局变量名相同的话,是会被修改的。

        

避免的方法

  1. 如果不需要共享变量的情况下,建议使用 bash,不使用 source
  2. 如果需要共享大量变量的情况下,使用 source,但非主脚本的变量全部定义为局部变量。

    【主脚本代码】

#!/bin/bash
var=10

echo "我是主脚本, 当前var为: ${var}"

source ./scr.sh    # 调用其他脚本

echo "我是主脚本, 调用另一个脚本后, 当前var为: ${var}"

 【另一个脚本代码】

Func(){
    local var=20    # 定义局部变量
    echo "我是另一个脚本, 这里的var为: ${var}"
    }
Func

非主脚本的代码都使用函数封装,并且将所有变量定义为局部变量,即使变量名称相同也不会发生冲突。

        

3. 总结

1、当需要共享大量变量的情况下,使用 source 调用另一个脚本。但另一个脚本的代码尽量都使用函数封装,将函数中的变量定义为局部变量,避免名称冲突。

2、当不需要共享变量时,或者少量变量时,可以使用 bash 调用另一个脚本。当然,这还是看个人习惯吧。

3、不论是主脚本还是其他脚本,都可以 source 或 bash 多个其他脚本。如果是 source,则全部共享。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐