Shell脚本两次source同一脚本参数未更新的原因及source解决方案
问题原因及解决办法
原因分析
source命令会在当前Shell进程的环境中执行目标脚本,而非启动独立子进程。这意味着脚本里定义的变量(比如MODE)会直接留在当前Shell的全局环境中,不会随脚本执行结束被销毁。- 另一个核心问题是
getopts的内部变量OPTIND:它记录了getopts下一个要处理的参数位置。第一次执行run-1.sh后,OPTIND已经被更新到参数列表的末尾;第二次调用时,getopts直接从这个位置开始解析,相当于跳过了所有传入的参数,导致MODE没有被重新赋值,依然保留第一次的"George"。
基于source命令的解决办法
1. 每次调用前重置OPTIND
在trigger.sh里,每次source调用前手动把OPTIND重置为1,让getopts重新从第一个参数开始解析:
#!/usr/bin/env bash echo "Configuring tests" echo "Source 1" OPTIND=1 source ./run-1.sh -m "George" echo "Source 2" OPTIND=1 source ./run-1.sh -m "Fred" echo "End"
2. 在run-1.sh内部主动重置变量
在run-1.sh的开头,直接重置OPTIND和MODE,彻底避免前一次调用的残留值影响:
#!/usr/bin/env bash # 重置变量,清除上次source的残留 OPTIND=1 MODE="" echo "IN run-1" while getopts m: flag; do case "${flag}" in m) MODE=${OPTARG} ;; esac done echo "before mode" echo "$MODE" echo "after mode"
3. 用函数封装逻辑(更规范的方案)
把run-1.sh的逻辑改成函数,通过source加载函数后再调用——这样变量可以限定在函数内部,不会污染全局环境:
首先修改run-1.sh为函数定义:
#!/usr/bin/env bash run_mode() { echo "IN run-1" local MODE="" # 局部变量,每次调用独立 OPTIND=1 # 函数内重置OPTIND,不影响全局 while getopts m: flag; do case "${flag}" in m) MODE=${OPTARG} ;; esac done echo "before mode" echo "$MODE" echo "after mode" }
然后修改trigger.sh:
#!/usr/bin/env bash # 先source加载函数 source ./run-1.sh echo "Configuring tests" echo "Source 1" run_mode -m "George" echo "Source 2" run_mode -m "Fred" echo "End"
内容的提问来源于stack exchange,提问作者Swanand
相关产品推荐
相关产品推荐

