swift - 在 Swift 中终止 macOS 命令行工具的子进程
问题描述
我正在用 swift 编写一个执行 shell 命令的 macOS 命令行工具:
let process = Process()
process.launchPath = "/bin/sleep"
process.arguments = ["100"]
process.launch()
process.waitUntilExit()
但是,如果中断 ( CTRL-C
) 或终止信号被发送到我的程序,这些 shell 命令不会被终止,而是继续执行。
如果我的程序意外终止,有没有办法自动终止它们?
解决方案
这是我们在CTRL-C
使用两个管道子进程时为了对中断 ( ) 做出反应所做的。
背后的想法:阻塞waitUntilExit()
调用替换为异步terminationHandler
。dispatchMain()
用于服务调度事件的无限循环。在接收到Interrupt
信号时,我们调用interrupt()
子进程。
封装子进程启动和中断逻辑的示例类:
class AppTester: Builder {
private var processes: [Process] = [] // Keeps references to launched processes.
func test(completion: @escaping (Int32) -> Void) {
let xcodebuildProcess = Process(executableName: "xcodebuild", arguments: ...)
let xcprettyProcess = Process(executableName: "xcpretty", arguments: ...)
// Organising pipe between processes. Like `xcodebuild ... | xcpretty` in shell
let pipe = Pipe()
xcodebuildProcess.standardOutput = pipe
xcprettyProcess.standardInput = pipe
// Assigning `terminationHandler` for needed subprocess.
processes.append(xcodebuildProcess)
xcodebuildProcess.terminationHandler = { process in
completion(process.terminationStatus)
}
xcodebuildProcess.launch()
xcprettyProcess.launch()
// Note. We should not use blocking `waitUntilExit()` call.
}
func interrupt() {
// Interrupting running processes (if any).
processes.filter { $0.isRunning }.forEach { $0.interrupt() }
}
}
用法(即main.swift
):
let tester = AppTester(...)
tester.test(....) {
if $0 == EXIT_SUCCESS {
// Do some other work.
} else {
exit($0)
}
}
// Making Interrupt signal listener.
let source = DispatchSource.makeSignalSource(signal: SIGINT)
source.setEventHandler {
tester.interrupt() // Will interrupt running processes (if any).
exit(SIGINT)
}
source.resume()
dispatchMain() // Starting dispatch loop. This function never returns.
shell中的示例输出:
...
▸ Running script 'Run Script: Verify Sources'
▸ Processing Framework-Info.plist
▸ Running script 'Run Script: Verify Sources'
▸ Linking AppTestability
^C** BUILD INTERRUPTED **
推荐阅读
- asp.net-core - dotnet Core Authentication OpenIdConnectProtocolException:消息包含错误:OneLogin 后的“invalid_client”
- python - NumPy 在二维数组中切片正方形
- c - C++ 指针增量
- sql-server - SQL Server - 使用生效日期跟踪历史属性,如何忘记(不再有效)属性
- sharepoint - 一个 SharePoint 中的所有根驱动器项目都具有相同的 ID?
- ethereum - 在 Solidity(智能合约/以太坊)中是否有更复杂的函数可以调用?
- python - 将这些数据集中的数组组合成一个 HDF5 文件,最后得到一个 2D
- c++ - C++ ValueError bitset::_M_copy_from_ptr 当字符串和位集的大小正确时
- electron - 如果将电子应用程序上传到服务器,它可以作为网站运行吗?
- html - 如何在旋转时将两个 SVG 合并为一个