BASH SSH脚本中如何将远程循环数组索引传递给全局函数使用
问题根因
- 你写在SSH双引号内的变量默认会被本地Bash在执行SSH命令前提前展开,不会传到远程再解析。你代码里的
${usr1[$j]}中的$j是本地变量,SSH执行前本地没有给j赋值,默认取值为空,所以永远取到的是${usr1[0]}即user1。 - 你定义的
tusr是本地函数,写在命令替换$(tusr usr1 "\$j")里的逻辑也是在本地执行的,同样因为本地j为空,永远返回user1。 - 你之前尝试转义
$j时出现语法报错,是因为转义后的\$j在本地展开时会变成字符串$j,本地数组需要数字作为索引,把字符串$j当索引就会触发 operand expected 错误。 - 额外补充:你的本地数组
usr1和函数tusr都不会被自动传到远程主机,就算你成功把$j传到了远程,远程也找不到对应的数组和函数,依然无法正常执行。
修复方案
最简单稳定的实现方式是先把本地的数组、函数定义序列化后传到远程,再在远程执行遍历逻辑,修改后可运行的代码如下:
usr1=("user1" "user2") # 如果要保留自定义函数,可以保留,后续导出到远程即可 function tusr { declare -n tmpp="$1"; echo "${tmpp[$j]}" } function testchk { echo "Logging in as $myuser to $1" # 导出本地数组和函数的定义 local arr_def="$(declare -p usr1)" local func_def="$(declare -f tusr)" # 远程先恢复数组、函数定义,再执行遍历逻辑,所有远程要用到的变量全部加转义 ssh -tq $myuser@$1.bar.com " $arr_def $func_def for j in \${!usr1[@]}; do echo \$j echo \${usr1[\$j]} echo \"Checking \$(tusr usr1 \$j):\" done " } srv="foo" testchk "$srv"
如果不需要保留tusr函数,可以直接在远程用数组取值,简化代码:
usr1=("user1" "user2") function testchk { echo "Logging in as $myuser to $1" local arr_def="$(declare -p usr1)" ssh -tq $myuser@$1.bar.com " $arr_def for j in \${!usr1[@]}; do echo \$j echo \${usr1[\$j]} echo \"Checking \${usr1[\$j]}:\" done " } srv="foo" testchk "$srv"
两种方案的执行结果都和你预期的输出一致。
内容的提问来源于stack exchange,提问作者qwedcxzas
相关产品推荐
相关产品推荐

