Node.js如何根据查询字符串动态生成shell命令并执行?
问题原因及修复方案
问题根因
- 参数名不匹配:你之前尝试用
queryObject.num获取参数,但实际请求的查询参数名为qs1,自然获取不到值返回undefined - 无效请求干扰:浏览器访问时会自动发送
/favicon.ico路径的请求,这类请求没有携带qs1参数,也会生成sh /mypath/undefined.sh的异常命令 - 异步逻辑错误:
child_process.exec是异步执行API,你当前代码在命令还没执行完成时就直接返回了响应,既拿不到实时执行结果,全局变量还会在并发请求时出现值污染。
注意:直接把用户传入参数拼接到shell命令执行的写法风险极高,即使做了参数校验也不建议在公网环境部署,仅可在内网可信环境下使用
修复后完整代码
const http = require('http'); const url = require('url'); const exec = require('child_process').exec; http.createServer(function (req, res) { // 解析请求路径和查询参数 const urlObj = url.parse(req.url, true); const pathname = urlObj.pathname; const queryObject = urlObj.query; // 过滤非目标路径的无效请求(比如favicon.ico请求) if (pathname !== '/t.js') { res.writeHead(404, {'Content-Type': 'text/html'}); res.end('Not Found'); return; } // 严格校验参数合法性,仅允许1/2/3三个合法值,避免命令注入风险 const validValues = ['1', '2', '3']; const targetNum = queryObject.qs1; if (!validValues.includes(targetNum)) { res.writeHead(400, {'Content-Type': 'text/html'}); res.end('参数非法,仅支持qs1取值为1、2、3'); return; } // 拼接执行命令 const comandd = `sh /mypath/${targetNum}.sh`; // 命令执行完成后再返回响应 exec(comandd , (error, stdout, stderr) => { let output1 = ""; if (error) { output1 = `error: ${error.message}`; } else if (stderr) { output1 = `stderr: ${stderr}`; } else { output1 = `Name: ${stdout}`; } res.writeHead(200, {'Content-Type': 'text/html'}); res.write(output1); res.end(); }); }).listen(8889);
关键修改说明
- 新增请求路径校验,仅处理
/t.js路径的合法请求,过滤无关请求干扰 - 新增参数严格校验,仅允许约定的三个参数值,从根源避免命令注入风险
- 将响应返回逻辑移到
exec的回调函数内,确保命令执行完成后再返回最新结果 - 去掉了全局的
output1、comandd变量,改为请求内局部变量,避免多个并发请求互相污染变量值
内容的提问来源于stack exchange,提问作者center1010
相关产品推荐
相关产品推荐

