C++程序从Bash接收参数异常:双引号包裹内容被拆分排查
问题根因定位
首先,你的bash测试脚本运行正常,已经排除了客户系统shell本身解析双引号异常的可能,90%以上的概率出在你发布的merge程序入口是shell包装脚本,传参时未正确添加双引号。
你可以注意到异常输出中argv[0]的路径为/mnt/.../bin/merge,但客户执行的命令是调用上层目录的../Merge-xxx/merge,说明这个上层的merge是用来引导真实二进制的shell包装脚本,常见的错误写法如下:
#!/bin/bash # 错误写法:$@没有加双引号,会将传入的带空格的参数再次分词拆分 exec /path/to/bin/merge $@
#!/bin/bash # 正确写法:添加双引号保留参数的原有边界 exec /path/to/bin/merge "$@"
如果包装脚本用了错误写法,原本被双引号包裹的-F 0.3 -I -o mergeout传到脚本后,再传递给真实二进制时会被再次按空格拆分,就会出现你看到的参数被拆成多个argv项的问题,且这个问题只会在调用包装脚本时触发,你直接测试二进制、直接测试自己写的bash脚本都不会复现。
其他可能的低概率原因
- 客户执行merge命令时复制的内容包含智能引号(左右弯的全角引号),shell无法识别这种引号的包裹作用,直接将其当做普通字符处理,导致参数被拆分。而客户测试脚本时手动输入的是标准英文半角双引号,所以测试结果正常。
- 客户的shell环境中配置了merge对应的alias或自定义shell函数,传参时使用了未加引号的
$*/$@导致参数二次拆分。 - 客户的命令中双引号前存在不可见的转义字符(比如从文档复制时带入的隐藏反斜杠),导致引号失去包裹作用。
调试验证步骤
- 让客户直接调用异常输出里的真实二进制文件测试,命令如下:
/mnt/raid/1_Merge_Kernel_testing/combined_command_testing/Merge-2021-11-22_0906_NOVEMBER_DEV9-Ubuntu20.04_x86_64/bin/merge --autoXML merge_combine_command_small_testcase/input.xml -o autoxml -M "-F 0.3 -I -o mergeout"
如果直接调用真实二进制参数正常,即可确认是上层包装脚本的传参问题。
- 让客户执行
type -a merge检查是否存在alias或自定义函数覆盖了预期的程序入口。 - 让客户在执行命令前加
set -x开启shell调试,观察shell解析后的参数列表,即可确认是shell解析阶段就拆分了参数,还是传递到程序后才出现的拆分。
内容的提问来源于stack exchange,提问作者Geom
相关产品推荐
相关产品推荐

