如何从(远程)子shell向父shell传递复杂序列化变量?
在子shell中实现类似名称引用的变量同步(支持任意变量名与安全序列化)
问题背景
需要实现子shell中运行的函数能修改父shell的任意变量(比如关联数组),达到同shell环境下declare -n名称引用的等效效果。
之前找到的旧方案仅支持简单变量和固定变量名,且依赖本地文件、反向管道等方法——但我的场景是函数在远程运行,这些方法都不可用,只接受Bash专属解决方案。
同shell环境下的可行示例:
#!/bin/bash func() { declare -n var="$1" var["a"]="word1" var["b"]="word2" } declare -A x=() func x for e in "${!x[@]}"; do printf "[%s]=%s\n" "$e" "${x[$e]}" ; done
运行输出:
[b]=word2 [a]=word1
但如果func x在子shell中执行,父shell无法获取修改后的变量值。
尝试的初步方案
用declare -p序列化变量,子shell输出变量定义语句,父shell用eval执行:
func2() { declare -A X=() X["p"]="word3" declare -p X }
父shell执行eval "$( func2 )"后就能使用关联数组X,但存在两个问题:
- 仅支持固定变量名,无法适配传入的任意变量名;
- 直接用
declare -p配合eval存在安全风险,不确定如何用printf "%q"做安全转义。
解决方案
1. 支持任意传入的变量名
子shell函数接收目标变量名作为参数,内部用临时变量处理数据,最后生成对应目标变量名的声明语句。
2. 安全序列化实现
通过printf "%q"对变量名、数组键和值做转义,避免特殊字符导致的注入问题。
完整示例代码:
#!/bin/bash # 子shell中运行的函数(可远程执行) remote_func() { local target_var="$1" # 临时存储数据的关联数组 declare -A temp_arr=() # 模拟业务逻辑,修改临时数组 temp_arr["a"]="word with spaces" temp_arr["b"]="word; with; semicolons" temp_arr["c"]="word\"with\"quotes" # 生成安全的declare语句 printf "declare -A %s=(" "$(printf "%q" "$target_var")" local first_entry=1 for key in "${!temp_arr[@]}"; do if [[ $first_entry -eq 1 ]]; then first_entry=0 else printf " " fi printf "[%q]=%q" "$key" "${temp_arr[$key]}" done printf " )\n" } # 父shell中调用 declare -A my_arr=() # 假设remote_func在子shell/远程执行,捕获输出后eval eval "$(remote_func my_arr)" # 验证结果 for e in "${!my_arr[@]}"; do printf "[%s]=%s\n" "$e" "${my_arr[$e]}" ; done
方案说明
- 变量名适配:通过接收参数
target_var,动态生成对应变量名的声明语句,不再局限于固定名称; - 安全性保障:所有变量名、数组键和值都通过
printf "%q"转义,确保特殊字符(空格、分号、引号等)不会被解析为shell命令,避免注入风险; - 兼容性:仅依赖Bash的内置命令,符合仅限Bash的要求,且无需本地文件、管道等依赖,适配远程执行场景。
内容的提问来源于stack exchange,提问作者Albert Camu
相关产品推荐
相关产品推荐

