如何在for循环内的ssh命令中正确传递自定义路径变量?
问题原因
你的报错是典型的引号嵌套解析错误导致的:
你写的ssh user@xxx.xxx.xxx.xxx "find $VAR_PATH -iname "*.so"" 里外层用了双引号,内层"*.so"的双引号会被本地shell提前识别为外层双引号的闭合,后续的*.so不会被包裹在引号内,会触发本地shell的通配符展开:如果本地当前目录存在.so后缀的文件,*.so会被替换成实际的文件名列表,传到远程服务器的find命令就会多出无效参数,直接报错。
你硬编码路径的时候刚好本地目录没有.so文件,通配符没展开所以碰巧能运行,换个环境照样会出问题。
正确写法
写法1:转义内部引号,避免本地提前解析
把内层的匹配规则用单引号包裹,确保*.so作为完整参数传到远程:
VAR_PATH="/predefined/path/to/A" echo $VAR_PATH for file_path in `ssh user@xxx.xxx.xxx.xxx "find $VAR_PATH -iname '*.so'"` do echo $file_path done
转义内层双引号也可以实现相同效果:
ssh user@xxx.xxx.xxx.xxx "find $VAR_PATH -iname \"*.so\""
写法2:更安全的变量传递(兼容含特殊字符的路径)
如果你的路径可能包含空格、特殊字符,推荐把本地变量作为远程命令的位置参数传递,完全隔离本地和远程的解析逻辑,避免注入风险:
VAR_PATH="/predefined/path/to/A" echo $VAR_PATH for file_path in `ssh user@xxx.xxx.xxx.xxx bash -c 'find "$1" -iname "*.so"' _ "$VAR_PATH"` do echo $file_path done
这里的_是占位符,对应远程bash的$0参数,后面的$VAR_PATH会被原样传递给远程的$1,不会被本地提前解析,兼容性更强。
额外优化建议
不推荐用for循环遍历find的输出,如果文件名包含空格、换行符的话会被拆分乱码,更稳妥的写法是用while read:
VAR_PATH="/predefined/path/to/A" ssh user@xxx.xxx.xxx.xxx "find \"$VAR_PATH\" -type f -iname '*.so' -print0" | while IFS= read -r -d '' file_path do echo "$file_path" done
内容的提问来源于stack exchange,提问作者Codeme
相关产品推荐
相关产品推荐

