通过SSH包装命令:如何处理复杂引号?HPC集群场景实践
解决HPC节点通过前端执行带复杂引号的bq命令问题
我太懂这种引号嵌套的痛苦了!当要把带多层引号的命令通过SSH传到前端节点时,直接像wget那样传参很容易因为shell的引号解析规则搞砸。下面给你几个实用的解决方案,按推荐程度排序:
方案1:用Here Document( heredoc)传递命令(最推荐)
这种方式完全不用纠结引号转义,把整个bq命令原封不动地传给前端节点的bash执行:
#!/bin/bash ssh frontal bash << 'EOF' bq --format=json query "SELECT * FROM [bigquery-public-data:cloud_storage_geo_index.sentinel_2_index] WHERE sensing_time LIKE '2016%' AND mgrs_tile == '32ULU' ORDER BY sensing_time ASC LIMIT..." EOF
关键点在于<< 'EOF'的单引号——它会让本地shell不对 heredoc 内部的任何内容做解析,引号、变量、特殊符号都会原封不动地发送到前端节点的bash,完美避免引号冲突。
方案2:用printf %q自动转义特殊字符
如果更习惯用单行命令传递,可以用printf %q把整个bq命令转义成shell能正确识别的格式:
#!/bin/bash # 先把完整的bq命令定义成变量 BQ_CMD="bq --format=json query \"SELECT * FROM [bigquery-public-data:cloud_storage_geo_index.sentinel_2_index] WHERE sensing_time LIKE '2016%' AND mgrs_tile == '32ULU' ORDER BY sensing_time ASC LIMIT...\"" # 转义后通过ssh传递给前端的sh执行 ssh frontal sh -c "$(printf %q "$BQ_CMD")"
printf %q会自动处理所有特殊字符(引号、空格、通配符等),生成一个可以被任意shell正确解析的字符串,不用担心转义错误。
方案3:支持动态参数的版本
如果以后需要修改命令里的参数(比如LIMIT的值),可以去掉 heredoc 的单引号,让本地shell替换变量后再传递:
#!/bin/bash # 从脚本参数获取LIMIT值,比如执行脚本时用 ./bq_wrapper 100 LIMIT=$1 ssh frontal bash << EOF bq --format=json query "SELECT * FROM [bigquery-public-data:cloud_storage_geo_index.sentinel_2_index] WHERE sensing_time LIKE '2016%' AND mgrs_tile == '32ULU' ORDER BY sensing_time ASC LIMIT $LIMIT" EOF
这里注意不要给EOF加单引号,这样本地shell会把$LIMIT替换成你传入的数值,再把完整命令发送到前端节点。
内容的提问来源于stack exchange,提问作者DuGNu
相关产品推荐
相关产品推荐

