You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vapor 4部署Ubuntu后Process执行Shell命令延迟至进程退出才运行

核心根因

Linux平台Foundation库Process实现和macOS存在差异,现有执行函数缺少子进程等待逻辑、未完全消费子进程输出缓冲区,导致子进程启动后进入挂起状态,直到Vapor主进程退出时,所有挂起的子进程才会被系统回收执行,因此出现停止应用时消息批量发出的现象。

修复方案

1. 调整Shell执行函数

添加waitUntilExit调用,同时捕获标准错误输出避免缓冲区堵塞导致进程挂起:

func runShellScript(_ cmd: String) -> String? {
    let outputPipe = Pipe()
    let errorPipe = Pipe()
    let process = Process()
    process.launchPath = "/bin/sh"
    process.arguments = ["-c", cmd]
    process.standardOutput = outputPipe
    process.standardError = errorPipe
    process.launch()
    // 等待子进程执行完成
    process.waitUntilExit()
    // 读取所有输出避免缓冲区残留
    let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
    let errorData = errorPipe.fileHandleForReading.readDataToEndOfFile()
    
    // 按需打印错误日志排查问题
    if let errorStr = String(data: errorData, encoding: .utf8), !errorStr.isEmpty {
        print("Shell执行错误: \(errorStr)")
    }
    
    return String(data: outputData, encoding: .utf8)
}

2. 适配Vapor异步特性

不要在路由的事件循环线程直接执行同步Shell调用,会堵塞事件循环影响其他请求处理,建议将调用丢到全局后台队列执行,同时对传入的消息做单引号转义避免命令注入风险:

// 路由内调用逻辑
let slackCLIPath = "/home/linuxbrew/.linuxbrew/bin/"
let escapedMessage = myMessageComingFromThePOST.replacingOccurrences(of: "'", with: "'\\''")
DispatchQueue.global().async {
    _ = runShellScript("\(slackCLIPath)slack chat send '\(escapedMessage)' '#myChannel'")
}

可选优化

可以直接使用Vapor内置的ConsoleKit库的非阻塞进程执行API,原生适配Linux环境,不会堵塞事件循环,无需手动维护Process逻辑。


内容的提问来源于stack exchange,提问作者cdf1982

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 19:24:04