如何在并行运行的Bash脚本间实现变量的读写共享?
Bash父脚本与并行子脚本共享变量的解决方案
问题根源
Bash中用bash ./children.sh &启动的子脚本会以独立子进程运行。子进程仅继承父进程环境变量的副本,所有变量修改仅在子进程自身地址空间生效,父进程无法直接感知——这是Linux/Unix进程模型的固有特性。
方案1:子脚本输出变量更新,父进程捕获赋值
无需额外文件,利用子进程标准输出传递变量值,父进程等待子进程结束后提取并更新变量。
修改子脚本children2.sh
让它在最后输出变量赋值语句:
#!/bin/bash for i in {1..3} do echo "### SECOND PROCESS $i" done # 输出变量更新指令供父进程执行 echo "SOME_VAR=20"
修改父脚本parent.sh
等待所有子进程完成,捕获输出并执行变量赋值:
#!/bin/bash SOME_VAR=100 export SOME_VAR # 创建临时文件存储子进程输出 tmp_output=$(mktemp) # 启动并行子进程,输出写入临时文件 bash ./children1.sh >> "$tmp_output" & pid1=$! bash ./children2.sh >> "$tmp_output" & pid2=$! # 等待所有子进程结束 wait $pid1 $pid2 # 从输出中提取变量赋值并执行 grep "^SOME_VAR=" "$tmp_output" | source /dev/stdin # 清理临时文件 rm "$tmp_output" echo "New SOME_VAR value: $SOME_VAR"
执行bash ./parent.sh后,父脚本的SOME_VAR会被更新为20。
方案2:使用命名管道(FIFO)实时传递变量更新
命名管道是轻量级IPC机制,比普通文件更优雅,支持实时传递变量更新。
修改父脚本parent.sh
创建临时FIFO,启动监听进程读取并更新变量:
#!/bin/bash SOME_VAR=100 export SOME_VAR # 创建临时命名管道 fifo=$(mktemp -u) mkfifo "$fifo" # 后台启动FIFO监听进程,执行接收到的变量赋值 while read -r line; do eval "$line" done < "$fifo" & listener_pid=$! # 启动并行子进程,将FIFO路径传递给children2.sh bash ./children1.sh & bash ./children2.sh "$fifo" & # 等待所有子进程完成 wait %2 %3 # 清理FIFO并终止监听进程 rm "$fifo" kill "$listener_pid" 2>/dev/null echo "New SOME_VAR value: $SOME_VAR"
修改子脚本children2.sh
向FIFO写入变量更新指令:
#!/bin/bash for i in {1..3} do echo "### SECOND PROCESS $i" done # 向传入的FIFO路径写入变量更新 echo "SOME_VAR=20" > "$1"
该方案支持子进程中途实时更新父进程变量,无需等待所有子进程结束。
补充说明
- 若不需要实时更新,方案1更简洁,无额外进程管理开销;
- 所有Unix-like系统中,进程间无法直接共享内存变量,必须通过IPC机制(管道、FIFO等)传递变量更新。
内容的提问来源于stack exchange,提问作者Krzysztof Kaczyński
相关产品推荐
相关产品推荐

