Shell脚本间相互调用

在Shell中要如何调用别的shell脚本,或别的脚本中的变量,函数呢?

方法一:   . ./subscript.sh

方法二:   source ./subscript.sh

注意:

1.两个点之间,有空格,千万注意.

2.两个脚本不在同一目录,要用绝对路径

3.为简单起见,通常用第一种方法

例如:

代码如下:

main.sh           #主脚本

subscripts.sh     #子脚本,或者说被调脚本

[code]

[code]

###subscripts.sh 脚本内容如下:###

#!/bin/bash

string="Hello,World! \n"

代码如下:

###main.sh 脚本内容如下###

#!/bin/bash

. ./subscripts.sh

echo -e ${string}

exit 0

输出结果:

代码如下:

# chmod +x ./main.sh

# ./main.sh

Hello,World!

#

注意:

1.被调脚本可以没有执行权限,调用脚本必须有可执行权限

2.chmod +x ./main.sh   #注意这里要有点,否则bash脚本可能找不到

 

<think>我们参考提供的引用资料,来回答用户的问题:如何在Shell脚本调用其他脚本,以及Shell脚本如何调用和执行。 根据引用[1]和[2],在Shell脚本调用另一个脚本有三种方法:fork、exec、source。它们之的区别主要在于是否创建新的子shell以及环境变量的继承关系。 1. **fork**:即直接执行脚本(如`./my.sh`或`sh my.sh`)。这种方式会创建一个新的子shell来执行脚本,子shell执行完毕后返回父shell。子shell会继承父shell的环境变量,但子shell中对环境变量的修改不会影响父shell。 2. **exec**:使用`exec`命令执行脚本(如`exec ./my.sh`)。这种方式会用新的脚本替换当前shell,即执行完脚本后不会返回原来的shell。因此,原脚本中`exec`之后的代码不会被执行。 3. **source**:使用`source`命令或点号(`.`)执行脚本(如`source my.sh`或`. my.sh`)。这种方式不会创建子shell,而是在当前shell环境中执行脚本。因此,脚本中定义的变量和函数在当前shell中可以直接使用。 引用[3]通过一个例子展示了不同调用方式对变量的影响: - 以子shell方式调用(fork)时,子脚本中修改变量不会影响父脚本中的变量。 - 使用source(在当前shell中执行)时,子脚本中修改变量会影响父脚本中的变量。 引用[4]给出了一个source调用的示例:在main.sh中通过`. ./subscripts.sh`调用subscripts.sh,使得subscripts.sh中定义的变量string可以在main.sh中使用。 因此,在Shell脚本调用其他脚本的方法及区别总结如下: | 调用方式 | 命令格式 | 是否创建子shell | 环境变量影响 | |----------------|----------------------------|----------------|----------------------| | fork | `./script.sh` 或 `sh script.sh` | 是 | 子shell的变量不影响父shell | | exec | `exec ./script.sh` | 替换当前shell | 不返回,后续代码不执行 | | source | `source script.sh` 或 `. script.sh` | 否 | 脚本中的变量和函数会影响当前shell | 根据需求选择合适的调用方式: - 如果希望子脚本的执行不影响当前shell的环境(比如临时执行一个任务,然后继续当前脚本),使用fork。 - 如果希望执行完子脚本后不返回当前脚本(比如用新脚本替换当前进程),使用exec。 - 如果希望子脚本中定义的变量或函数在当前脚本中可用,使用source。 下面通过一个例子来演示三种调用方式的区别: 假设有两个脚本:`father.sh`和`child.sh`。 `child.sh`的内容: ```bash #!/bin/bash echo "In child.sh: PID=$$" v_child="child" ``` `father.sh`的内容: ```bash #!/bin/bash v_child="father" echo "1. 使用fork方式调用:" ./child.sh # 或者 sh child.sh echo "father.sh中 v_child=$v_child" echo "2. 使用exec方式调用:" exec ./child.sh # 注意:exec之后的代码不会执行 echo "这行不会输出" echo "3. 使用source方式调用:" source ./child.sh echo "father.sh中 v_child=$v_child" ``` 执行`father.sh`(注意需要给`child.sh`执行权限:`chmod +x child.sh`): - 第一部分(fork):子进程执行`child.sh`,输出子进程的PID(与父进程不同),然后回到父进程,父进程中的`v_child`仍然是"father"。 - 第二部分(exec):执行`child.sh`并替换当前进程,因此`child.sh`执行完后不会返回`father.sh`,所以后续的代码(包括第三部分)都不会执行。 - 第三部分(source):由于exec已经替换了进程,所以不会执行到这里。如果我们注释exec部分,那么source部分会执行,此时`child.sh`中的变量赋值`v_child="child"`会在当前shell(即father.sh的shell)中生效,因此输出`v_child=child`。 注意:实际执行时,由于exec会替换进程,所以第三部分不会执行。为了看到所有效果,我们可以将第二部分注释。 因此,根据用户的问题,我们给出以下回答: 在Shell脚本调用其他脚本,主要有三种方式:fork(直接执行)、exec(替换当前进程)、source(在当前shell中执行)。它们的主要区别在于是否创建新的子进程以及环境变量的继承关系。 - **fork(直接执行)**:使用`./script.sh`或`sh script.sh`,会创建子shell执行脚本,子shell中定义的变量不会影响父shell。 - **exec**:使用`exec ./script.sh`,会使用新的脚本替换当前shell,原脚本中exec之后的代码不会被执行。 - **source**:使用`source script.sh`或`. script.sh`,在当前shell中执行脚本脚本中定义的变量和函数在当前shell中生效。 根据实际需求选择调用方式: - 如果希望子脚本独立运行且不影响当前环境,使用fork。 - 如果希望执行子脚本后不再返回当前脚本,使用exec。 - 如果希望子脚本中定义的变量或函数在当前脚本中可用,使用source。 §§相关问题§§ 1. Shell脚本中三种调用方式(fork, exec, source)的具体使用场景是什么? 2. 在Shell脚本调用另一个脚本时,如何传递参数? 3. 如何判断一个脚本是在子shell中执行还是在当前shell中执行? 4. Shell脚本中如何获取子脚本的退出状态?</think>### Shell脚本调用其他脚本的方法 在Shell脚本调用其他脚本有三种主要方法:**fork**、**exec** 和 **source**,它们的行为和影响环境变量的方式有显著区别: | 方法 | 命令格式 | 是否创建子Shell | 环境变量影响 | 后续代码执行 | |---------|---------------------------|-----------------|----------------------------|-----------------| | **fork** | `./script.sh` 或 `sh script.sh` | 是 | 子Shell变量不影响父Shell | 继续执行 | | **exec** | `exec ./script.sh` | 替换当前进程 | 不返回父Shell | 替换后代码不执行 | | **source** | `source script.sh` 或 `. script.sh` | 否 | 脚本变量直接影响当前Shell | 继续执行 | --- #### 1. **fork(创建子Shell)** - **原理**:启动新的子Shell进程执行脚本,子进程继承父进程的环境变量,但子进程的变量修改**不会**影响父进程。 - **示例**: ```bash # father.sh v_test="parent" echo "调用脚本前: $v_test" # 输出: parent ./child.sh # fork方式调用 echo "调用脚本后: $v_test" # 输出: parent(值未变) # child.sh v_test="child" # 修改仅在子Shell生效 ``` - **适用场景**:需要隔离环境变量的场景(如临时任务)。 --- #### 2. **exec(替换当前进程)** - **原理**:用新脚本**替换**当前Shell进程,原脚本后续代码**不会执行**。 - **示例**: ```bash # father.sh echo "Before exec" exec ./child.sh # 进程被替换 echo "This line NEVER runs" # 不会执行 # child.sh echo "Child script running" ``` - **输出**: ``` Before exec Child script running ``` - **适用场景**:需要彻底切换执行环境(如引导程序)。 --- #### 3. **source(在当前Shell执行)** - **原理**:**不创建子Shell**,直接在当前Shell执行脚本脚本中的变量和函数**直接影响**当前环境。 - **示例**: ```bash # father.sh v_test="parent" source ./child.sh # 或 . ./child.sh echo "变量值: $v_test" # 输出: child(被子脚本修改) # child.sh v_test="child" # 直接修改当前Shell的变量 ``` - **适用场景**:需要共享变量/函数(如环境配置脚本)。 --- ### 关键区别总结 1. **环境变量隔离** - `fork`:子Shell变量不影响父Shell(隔离)[^2][^3]。 - `source`:变量直接修改当前Shell(共享)[^3][^4]。 - `exec`:无返回值,直接替换进程。 2. **执行流程** - 只有`exec`会终止原脚本后续代码[^1]。 3. **权限要求** - `fork`和`exec`需要脚本有**执行权限**(或通过`sh`调用)。 - `source`可直接调用无执行权限的脚本。 --- ### 最佳实践建议 - 需共享变量 → 用 `source` - 需隔离环境 → 用 `fork` - 需彻底替换进程 → 用 `exec` > 示例完整代码可参考:[^3][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值