在swift5中,我想运行一个Process()
读取standardOutput
和standardError
而不阻塞,这样我就可以解析它们。
此示例代码一旦调用带有for try await line in errorPipe.fileHandleForReading.bytes.lines
的行,程序执行将被阻止。standardOutput读取器停止打印
import Foundation
let outputPipe = Pipe()
let errorPipe = Pipe()
let process = Process()
process.executableURL = URL(fileURLWithPath:"/sbin/ping")
process.arguments = ["google.com"]
process.standardOutput = outputPipe
process.standardError = errorPipe
try? process.run()
func processStdOut() async
{
for i in 0..<5 {
print("processStdOut X ", i)
try? await Task.sleep(nanoseconds: 1_000_000_000)
}
do {
for try await line in outputPipe.fileHandleForReading.bytes.lines {
print("stdout Line: \(line)")
}
} catch {
NSLog("processStdOut Error \(error.localizedDescription)")
}
NSLog("processStdOut finished")
}
func processStdErr() async
{
for i in 0..<5 {
print("processStdErr X ", i)
try? await Task.sleep(nanoseconds: 2_000_000_000)
}
do {
for try await line in errorPipe.fileHandleForReading.bytes.lines {
print("stderr Line: \(line)")
}
} catch {
NSLog("processStdErr Error \(error.localizedDescription)")
}
NSLog("processStdErr finished")
}
await withTaskGroup(of: Void.self) { group in
group.addTask {
await processStdErr()
}
group.addTask {
await processStdOut()
}
group.addTask {
process.waitUntilExit()
}
}
字符串
请注意,如果您通过断开wifi或网络standardOutput来强制数据进入standardError,则会再次解除阻塞。
还有什么我应该尝试的吗?
2条答案
按热度按时间hjzp0vay1#
是的,标准的
bytes
实现在standardError
上同时使用bytes
时也会阻塞standardOutput
。下面是一个简单的
bytes
实现,它不会阻塞,因为它利用了readabilityHandler
:字符串
因此,以下代码在同时处理
standardOutput
和standardError
时不会遇到相同的问题:型
vxf3dgd42#
大多数程序默认默认缓冲策略,由于你无法控制
/sbin/ping
如何处理输出,其中一个管道可能会阻塞FileHandle.AsyncBytes
的实现(不知道为什么)。我通过调用.availableData
来避免阻塞,从而同时使用两个管道。字符串
然后我得到以下(修剪后的)输出:
型
我尝试了默认为
stderr
的curl
,它也没有阻塞:型
编辑:
使用以下C程序进行测试:
型
它返回以下输出:
型