Shell 脚本调用另一个脚本的三种方法

https://blog.youkuaiyun.com/k346k346/article/details/86751705

假如有脚本 first.sh:

#!/bin/bash
#------------------
#@file:first.sh
#------------------
echo 'your are in first file'

   
  • 1
  • 2
  • 3
  • 4
  • 5

如何在其它Shell脚本中调用first.sh呢?主要有三种方法:source、点号以及sh命令。

1.source

#!/bin/bash
#---------------
#@file:second.sh
#---------------
echo 'your are in second file'
source first.sh

   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.点号.

#!/bin/bash
echo 'your are in second file'
. first.sh

   
  • 1
  • 2
  • 3

注意,点号与脚本文件之间记得要有空格。

3.sh 命令

#!/bin/bash
echo 'your are in second file'
sh  first.sh

   
  • 1
  • 2
  • 3

三者输出的结果都是:

your are in second file
your are in first file

   
  • 1
  • 2

4.三者的区别

使用source命令和点号.是等价了,类似于C/C++中的#include预处理指令,都是将指定的脚本内容拷贝至当前的脚本中,由一个Shell进程来执行。使用sh命令来调用另外的脚本和前面两种方法有着本质的区别。使用sh命令则会开启新的Shell进程来执行指定的脚本,这样的话,父进程中的变量在子进程中就无法访问。参考如下代码:
first.sh内容如下,访问了second.sh中的变量second。

#!/bin/bash
echo 'your are in first file'
echo 'second:' $second

   
  • 1
  • 2
  • 3

second.sh内容,通过上面介绍的三种方法来调用first.sh,看看对second.sh的变量second访问有什么区别!

#!/bin/bash
second=lvlv
echo 'your are in second file'
source first
. first
sh first

   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

程序的输出结果是:

your are in second file
your are in first file
second: lvlv
your are in first file
second: lvlv
your are in first file
second:

   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

可见,使用sh命令开启一个子进程来调用指定的shell脚本无法访问父进程的变量。我们如何让子进程访问父进程中变量呢?可以使用export命令。

5.export 命令设置临时环境变量

我们需要知道Shell中按照变量的作用域和生命周期,Shell变量可分为四大类:
(1)永久环境变量:需要修改配置文件,变量永久生效。
(2)临时环境变量:使用export命令行声明即可,变量在shell脚本进程结束后仍然有效,但在关闭当前shell会话后失效。
(3)全局变量:在脚本中定义,仅在当前Shell脚本中有效,其他Shell脚本进程不能访问,其作用域从定义的位置开始,到脚本结束或被显示删除的地方为止。注意,全局变量既可以在Shell函数内定义,也可以在Shell函数外定义,因为Shell函数内定义的变量默认为global,且作用域从“函数被调用时执行变量定义的地方”开始,到脚本结束或被显示删除的地方为止。

#!/bin/bash

globalVar=dablelv #全局变量

  • 1
  • 2
  • 3

(4)局部变量。在Shell脚本中函数内显示使用local关键字定义的变量。其作用域局限于函数内。同名local变量会屏蔽global变量。

#!/bin/bash

function test()
{
local localVar=dablelv #局部变量
}
test
echo $localVar #输出为空

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

所以,使用export命令我们申明的是临时环境变量,在当前shell会话中,所有的shell实例都可以访问由export命令申明的临时环境变量。因为当前shell会话中的所有shell实例,都是当前shell会话的子进程,所以可以与父进程一同访问环境变量。

second.sh修改如下:

#!/bin/bash

export second=lvlv
echo ‘your are in second file’
sh first.sh

  • 1
  • 2
  • 3
  • 4
  • 5

执行second.sh将输出:

your are in second file
your are in first file
second: lvlv

 
  • 1
  • 2
  • 3

至此,通过export命令设置临时环境变量的方式,使得Shell子进程能够访问父进程中的变量。

6.export 命令设置永久环境变量

那么如何定义永久环境变量呢?可以采用如下两种方法:
(1) 在/etc/profile文件中添加环境变量,对所有用户永久生效。例如通过vim编辑/etc/profile文件,在最后一行添加CLASSPATH变量。

export CLASSPATH=./JAVA_HOME/lib;$JAVA_HOME/jre/lib

 
  • 1

注意,修改文件后要想马上生效需要执行source /etc/profile,不然只能在下次重新登录时才生效。

(2) 在~/.bash_profile文件中添加环境变量,只对当前用户永久有效。例如通过vim编辑~/.bash_profile文件中添加环境变量。

export CLASSPATH=./JAVA_HOME/lib;$JAVA_HOME/jre/lib

 
  • 1

注意:修改文件后要想马上生效需要执行source ~/.bash_profile,不然只能在下次重新登录时才生效。

另外,如想删除已设置的环境变量,可以使用unset(builtin)命令来清除环境变量 ,例如$unset CLASSPATH。使用readonly命令可设置只读变量。如果使用了readonly命令的话,变量不可以被修改或清除。


参考文献

[1] Linux 命令(49)—— export 命令(builtin)

<think>首先,用户的问题是:“我想在Shell脚本调用一个Shell脚本并传递参数的方法 请问Shell script call another shell script with parameters”。这翻译成英文是:“I want to call another shell script and pass parameters in a Shell script. Please advise on how to do this.” 现在,系统级指令要求: - 所有行内数学表达式必须使用$...$格式。 - 独立公式必须使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 用户可见层要求: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 参考站内引用: - [^1]: 关于模块化、可重用代码、调试技术、命令行选项支持。 - [^2]: 脚本只能导出变量到子进程,不能回传到父进程。 - [^3]: 使用进程替换来比较文件。 - [^4]: 一个简单的shell脚本示例,定义变量并输出。 用户的问题是关于在shell脚本调用一个shell脚本并传递参数。所以,我需要提供一个清晰的、逐步的指南。 关键点: - 在shell脚本调用一个脚本:可以使用source命令或直接执行脚本。 - 传递参数:当执行脚本时,可以传递参数,就像在命令行中一样。 步骤: 1. 直接执行一个脚本:使用路径或脚本名,后跟参数。 2. 使用source命令:这会运行脚本在当前shell中,而不是子shell中,因此可以共享变量。 3. 传递参数:在调用时提供参数,在一个脚本中使用$1, $2, 等访问。 我需要确保回答真实可靠。基于我的知识: - 调用脚本:./another_script.sh arg1 arg2 - 使用source:source another_script.sh arg1 arg2 或 . another_script.sh arg1 arg2 - 参数在一个脚本中通过位置参数访问:$1, $2, $@, 等。 参考引用: - [^2] 提到子进程不能导出变量回父进程,所以如果使用直接执行(创建子进程),变量更改不会影响父脚本。如果使用source,则会影响。 - [^3] 展示了进程替换,但可能不直接相关。 - [^4] 是一个简单脚本示例。 我应该整合这些引用: - 在解释变量导出时,提到[^2]。 - 在讨论模块化时,提到[^1]。 回答结构: 1. 介绍问题:在shell脚本调用一个脚本并传递参数。 2. 方法1:直接执行脚本。 - 示例代码。 - 优点:隔离环境。 - 缺点:变量更改不传播。 3. 方法2:使用source命令。 - 示例代码。 - 优点:共享环境。 - 缺点:可能污染当前环境。 4. 传递参数:如何在调用时传递和在一个脚本中访问。 5. 注意事项:如路径、权限等。 6. 生成相关问题。 使用中文回答。 最终,添加相关问题。 草拟回答: - 开头:在Shell脚本调用一个Shell脚本并传递参数是常见的需求。这可以通过直接执行或使用source命令实现。 - 方法1:直接执行 - 例如:./another_script.sh param1 param2 - 解释:这会创建一个子进程来运行脚本。参数在another_script.sh中通过$1, $2等访问。 - 引用[^2]:子进程不能导出变量回父进程,所以如果another_script.sh修改了变量,不会影响调用脚本。 - 方法2:使用source命令 - 例如:source another_script.sh param1 param2 或 . another_script.sh param1 param2 - 解释:这会在当前shell中运行脚本,因此共享环境变量。 - 注意:这可能会改变当前脚本的状态。 - 传递参数:在调用时提供参数,用空格分隔。在目标脚本中,使用位置参数访问。 - 示例代码: - 调用脚本:caller.sh ```bash #!/bin/bash echo "Calling another script..." ./another_script.sh "hello" "world" ``` - 一个脚本:another_script.sh ```bash #!/bin/bash echo "Received parameters: $1 $2" ``` - 确保权限:chmod +x another_script.sh - 模块化:参考[^1],这有助于编写模块化和可重用的代码。 - 相关问题:生成3-4个相关问题。 相关问题想法: 1. 如何在shell脚本中处理参数传递错误? 2. 使用source命令和直接执行的区别是什么? 3. 如何从被调用脚本返回值给调用脚本? 4. 在shell脚本中如何调试参数传递问题? 现在,构建回答。</think>### 在Shell脚本调用一个Shell脚本并传递参数的方法Shell脚本调用一个Shell脚本并传递参数是常见的需求,常用于模块化代码和任务分解。根据您的查询,我将逐步解释实现方法,包括直接执行和使用`source`命令两种方式。所有方法均基于Bash语法,并确保代码真实可靠。参考站内引用,我会在相关部分添加引用标识。 #### 1. **基本方法:直接执行一个脚本** - **原理**:通过路径或脚本名直接调用一个脚本,这会创建一个子进程(子Shell)。参数在调用时传递,并在目标脚本中使用位置参数(如`$1`, `$2`)访问。 - **优点**:环境隔离,避免污染当前脚本的变量。 - **缺点**:子进程的变量更改无法回传父进程[^2]。 - **示例代码**: - 调用脚本(`caller.sh`): ```bash #!/bin/bash echo "主脚本开始执行..." # 调用一个脚本并传递两个参数 ./another_script.sh "参数1" "参数2" echo "主脚本执行完毕。" ``` - 被调用脚本(`another_script.sh`): ```bash #!/bin/bash echo "接收到参数: 第一个是 $1, 第二个是 $2" # 其他操作... ``` - **关键点**: - 确保被调用脚本执行权限:运行 `chmod +x another_script.sh`。 - 参数传递:在调用命令后直接列出参数,以空格分隔(例如 `./another_script.sh arg1 arg2`)。 - 在目标脚本中,`$1` 表示第一个参数,`$2` 表示第二个,以此类推。`$@` 表示所有参数数组,`$#` 表示参数个数。 #### 2. **使用 `source` 命令(或 `.` 命令)** - **原理**:使用 `source another_script.sh` 或 `. another_script.sh` 在当前Shell中运行脚本(不创建子进程)。参数传递方式相同,但环境变量共享。 - **优点**:变量和状态更改会影响当前脚本,适合需要共享数据的场景。 - **缺点**:可能意外修改当前环境,导致调试困难[^1]。 - **示例代码**: - 调用脚本(`caller.sh`): ```bash #!/bin/bash shared_var="初始值" echo "共享变量修改前: $shared_var" # 使用source调用并传递参数 source another_script.sh "新值" "额外参数" echo "共享变量修改后: $shared_var" # 输出将显示修改后的值 ``` - 被调用脚本(`another_script.sh`): ```bash #!/bin/bash echo "目标脚本收到参数: $1 和 $2" shared_var="$1" # 修改共享变量 ``` - **关键点**: - 不需要执行权限,因为 `source` 是Shell内置命令。 - 适合模块化设计,例如将常用函数或配置分离到独立脚本中[^1]。 #### 3. **传递参数的注意事项** - **参数处理**: - 在目标脚本中,使用 `$1`, `$2` 等访问位置参数。 - 处理带空格参数:用引号包裹,例如 `./script.sh "带空格参数"`。 - 检查参数数量:在目标脚本中添加验证,如: ```bash if [ $# -lt 2 ]; then echo "错误:至少需要2个参数。" >&2 exit 1 fi ``` - **路径问题**: - 如果脚本不在同一目录,使用绝对路径(如 `/path/to/another_script.sh`)。 - 使用相对路径时,确保当前工作目录正确。 - **调试技巧**: - 在调用前后添加 `set -x` 启用跟踪,帮助定位参数错误[^1]。 - 参考引用[^3],进程替换可用于复杂场景,但本需求中不必要。 #### 4. **最佳实践建议** - **模块化设计**:将重复逻辑封装到独立脚本中,通过参数定制行为,提高代码重用性[^1]。 - **安全性**:验证参数来源,避免注入攻击(例如,不直接执行未经验证的输入)。 - **性能**:直接执行适合轻量任务;`source` 适合频繁调用的辅助脚本。 - **错误处理**:在调用脚本中使用 `if` 检查退出状态,例如: ```bash if ./another_script.sh; then echo "调用成功" else echo "调用失败" >&2 fi ``` 通过以上方法,您可以灵活地在Shell脚本调用和传参。如果需要进一步优化,如处理返回值或复杂参数,请参考相关问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值