Gulp中gulp-nodemon的stream.on('exit')无法执行服务停止任务问题
Gulp Ctrl+C 未执行清理任务的解决方案
问题根源
- 监听的
exit事件时机错误:进程触发exit时已进入退出流程,Gulp无法正常调度新的异步任务,导致后续stop任务未执行。 - Ctrl+C发送的是
SIGINT中断信号,而非exit事件,你监听了错误的信号类型。 - 清理任务未正确标记异步完成,触发Gulp“任务未完成”的错误提示。
解决步骤
1. 监听正确的信号:SIGINT
Ctrl+C触发的是SIGINT信号,此时进程仍在运行,可正常执行清理逻辑。
2. 确保清理任务正确处理异步
Gulp 4+要求异步任务必须通过回调、返回Promise/Stream、async函数标记完成,否则会报错。
3. 示例代码实现
定义停止任务
回调版本:
const { exec } = require('child_process'); function stopMongodb(done) { exec('mongod --shutdown', (err) => { err ? console.error('MongoDB停止失败:', err) : null; done(); // 标记任务完成 }); } function stopRedis(done) { exec('redis-cli shutdown', (err) => { err ? console.error('Redis停止失败:', err) : null; done(); }); }
async/await版本(更简洁):
const { exec } = require('child_process').promises; async function stopMongodb() { try { await exec('mongod --shutdown'); } catch (err) { console.error('MongoDB停止失败:', err); } } async function stopRedis() { try { await exec('redis-cli shutdown'); } catch (err) { console.error('Redis停止失败:', err); } }
修改dev任务的信号监听
function dev(done) { // 此处编写你的dev任务逻辑:启动服务、监听文件变化等 // 监听Ctrl+C触发的SIGINT信号 process.on('SIGINT', async () => { console.log('Stopping services and server...'); // 依次执行停止任务(根据上面的版本二选一) // 回调版本 await new Promise(resolve => stopMongodb(resolve)); await new Promise(resolve => stopRedis(resolve)); // async版本 // await stopMongodb(); // await stopRedis(); console.log('Services stopped. Exiting...'); process.exit(0); // 手动终止进程 }); done(); // 标记dev任务启动完成 } // 导出任务 exports.dev = dev; exports['stop-mongodb'] = stopMongodb; exports['stop-redis'] = stopRedis;
关键注意事项
- 禁止在
exit事件中执行异步任务:该事件是进程退出前的最后通知,此时无法调度新的异步操作。 - 必须手动调用
process.exit(0):清理任务执行完毕后,需主动终止进程,避免卡在Gulp任务循环中。 - 自行调整
exec中的命令:根据你的服务启动方式,修改停止命令的路径或参数,确保能正确终止MongoDB和Redis。
内容的提问来源于stack exchange,提问作者Waakul
相关产品推荐
相关产品推荐

