Express中调用QZ-Tray实现LQ-310打印无响应问题求助
问题排查与解决方案
1. 异步执行顺序错误
你的代码中fs.writeFile和shell.exec都是异步操作,但未保证执行顺序——shell脚本可能在invoice.json写入完成前就执行,导致QZ-Tray读取无效数据;同时shell.exec默认异步,未等待其完成就返回响应,无法捕获执行状态。
修复方式:将shell执行逻辑放到writeFile的回调中,确保文件写入完成后再触发打印,同时捕获shell执行的输出与错误:
const printInvoice = (req, res) => { fs.writeFile(`src/invoice/invoice.json`, JSON.stringify(req.body), (err) => { if (err) { console.error('文件写入失败:', err); return res.status(500).json({ error: '文件写入失败' }); } const shell = require('shelljs'); const path = require('path'); // 使用绝对路径避免工作目录问题 const scriptPath = path.resolve(__dirname, 'src/invoice/qz-tray.sh'); shell.echo('Running qz-tray'); // 捕获shell执行的所有输出 const { code, stdout, stderr } = shell.exec(`bash ${scriptPath}`, { silent: false }); console.log('Shell执行输出:', stdout); console.error('Shell执行错误:', stderr); console.log('Shell退出码:', code); fs.readFile(`src/invoice/invoice.json`, (err, data) => { if (err) { console.error('文件读取失败:', err); return res.status(500).json({ error: '文件读取失败' }); } res.json(JSON.parse(data)); }); }); }
2. 相对路径失效
bash src/invoice/qz-tray.sh使用相对路径,当Express应用的工作目录不是项目根目录时,会找不到脚本。必须使用绝对路径定位脚本文件,如上例中的path.resolve方式。
同时确保脚本有执行权限:
chmod +x src/invoice/qz-tray.sh
3. QZ-Tray的运行逻辑误区
QZ-Tray是客户端工具,依赖浏览器环境与本地QZ-Tray服务的连接。后端直接通过shell脚本调用QZ-Tray相关代码,可能缺少必要的上下文(比如未建立与QZ-Tray服务的连接、无浏览器端的授权)。
正确流程应为:
- 后端接收请求,生成并存储打印数据(如
invoice.json) - 前端页面请求后端获取打印数据,然后通过QZ-Tray的前端JS API触发打印
若必须在后端触发,需确保脚本中正确实现了与QZ-Tray本地服务的连接逻辑,且当前运行Express的用户有权限访问QZ-Tray的默认端口(2112)。
4. 脚本执行日志缺失
在qz-tray.sh中添加日志输出,可直接排查脚本是否执行、执行到哪一步:
#!/bin/bash # 添加日志到临时文件 echo "[$(date)] 脚本开始执行" >> /tmp/qz-tray-debug.log # 你的原有打印逻辑 # ... echo "[$(date)] 脚本执行结束,退出码: $?" >> /tmp/qz-tray-debug.log
之后查看日志文件:
cat /tmp/qz-tray-debug.log
5. 错误处理不规范
异步回调中直接throw err会导致Express无法捕获错误,进而导致请求挂起无响应。必须通过res.status(500)返回错误响应,如上述代码中的处理方式。
内容的提问来源于stack exchange,提问作者Rusydy
相关产品推荐
相关产品推荐

