Ruby system方法执行curl命令报错:请求体无法解析为有效JSON
解决Logstash exec插件中curl发送Stride消息的转义问题
我之前也踩过类似的坑,本质是Ruby的system方法和shell命令的转义逻辑冲突导致的,给你一步步拆解解决:
为什么会报错?
你的报错里三个关键问题,全是转义不当闹的:
The request body cannot be parsed as valid JSON:JSON格式被破坏,shell把你转义的双引号当成了自己的语法符号,而非JSON的一部分Couldn't resolve host 'first':shell把JSON里空格后的内容(比如first)当成了新的curl参数(主机名),因为引号没正确闭合[globbing] unmatched close ...:括号不匹配,同样是转义错误让shell误解了命令结构
核心问题:当你用字符串形式给Ruby的system传命令时,命令会先经过Ruby的转义解析,再交给shell二次解析,单层的\转义根本不够用。
两种可靠的解决方案
方案1:用数组形式调用system(推荐)
Ruby的system方法支持传入数组,每个元素对应一个命令参数,这样完全跳过shell的解析,不需要任何转义,直接写正常的JSON即可:
# 在IRB里测试的代码 system( 'curl', '-X', 'POST', 'https://your-stride-webhook-url', # 替换成你的Stride webhook地址 '-H', 'Content-Type: application/json', '-d', '{"body": "测试消息内容"}' )
对应到Logstash的exec插件配置(如果你的Logstash版本支持数组形式的command参数):
exec { command => [ 'curl', '-X', 'POST', 'https://your-stride-webhook-url', '-H', 'Content-Type: application/json', '-d', '{"body": "%{message}"}' # 这里可以直接用Logstash的字段替换 ] }
这种方式最稳妥,完全避免转义混乱。
方案2:字符串形式的双重转义
如果你的场景只能用字符串传命令,必须做双重转义:Ruby先把\\解析成\,shell再把\"解析成JSON里的双引号。示例如下:
# IRB测试代码 system('curl -X POST https://your-stride-webhook-url -H "Content-Type: application/json" -d "{\\\"body\\\": \\\"测试消息内容\\\"}"')
对应Logstash配置:
exec { command => 'curl -X POST https://your-stride-webhook-url -H "Content-Type: application/json" -d "{\\\"body\\\": \\\"%{message}\\\"}"' }
这里的\\\"是关键:Ruby解析后变成\",shell再把它识别为JSON中的双引号,不会把JSON内容拆成多个curl参数。
测试小技巧
先在IRB里用数组形式测试命令,确保能成功发送消息到Stride,再把逻辑迁移到Logstash里,这样能快速定位是转义问题还是Logstash配置问题。
内容的提问来源于stack exchange,提问作者vishless
相关产品推荐
相关产品推荐

