多个 NSTasks 导致输出不一致
Multiple NSTasks Causing Inconsistent Output
我正在开发一个 Swift 应用程序,该应用程序与外部二进制文件(通过 NSTask)交互,并且 return 每行的输出都是字符串数组。
多次调用 executeCommand 函数时,命令开始无法达到 return 预期数据。
在下面的 Playground 示例中,我正在轮询 diskutil 以获取卷名称。
在调试区,我得到的第一个响应是:
- 不适用(无文件系统)
- Macintosh 高清
- 无法获取音量
姓名
- 无法获取卷名
- 无法获取卷名
只需重新运行 Playground 结果:
- 不适用(无文件系统)
- 无法获取卷名 <-- Macintosh HD 发生了什么?
- 无法获取卷名
- 无法获取卷名
无法获取卷名
import Cocoa
func executeCommand(launchPath: String, arguments: [String], additionalDelay: Int=0) -> [String] {
let outputPipe = NSPipe()
var outputArray = [String]()
let task = NSTask()
task.launchPath = launchPath
task.arguments = arguments
task.standardOutput = outputPipe
outputPipe.fileHandleForReading.waitForDataInBackgroundAndNotify()
NSNotificationCenter.defaultCenter().addObserverForName(NSFileHandleDataAvailableNotification, object: outputPipe.fileHandleForReading , queue: nil) {
notification in
let output = outputPipe.fileHandleForReading.availableData
let outputString = String(data: output, encoding: NSUTF8StringEncoding) ?? ""
outputArray = outputString.componentsSeparatedByCharactersInSet(.newlineCharacterSet())
outputPipe.fileHandleForReading.waitForDataInBackgroundAndNotify()
}
task.launch()
sleep(UInt32(additionalDelay)) // Additional delay
task.waitUntilExit()
// Remove last empty line from output array.
if outputArray.count > 0 {
outputArray.removeLast()
}
return outputArray
}
// Example usage
// Output volume name from provided disk identifier
func volumeName(identifier: String) -> String {
let volumeNameCommand = "/usr/sbin/diskutil info \(identifier) | awk '/Volume Name:/' | sed 's/Volume Name://g'| sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'"
let volumeNameOutput = executeCommand("/bin/bash", arguments: ["-c", volumeNameCommand])
var volumeName = "Unable to obtain volume name"
if volumeNameOutput.count > 0 {
volumeName = volumeNameOutput[0]
}
return volumeName
}
let identifiers = ["/dev/disk0","/dev/disk1","/dev/disk2","/dev/disk3","/dev/disk4"]
for identifier in identifiers {
print(volumeName(identifier))
}
我确实需要一致的结果,但不明白我哪里出错了。
如有任何帮助,我们将不胜感激!
我认为任务的异步执行导致了不一致的结果。下面是一个按预期工作的新函数:
func executeCommand(launchPath: String, arguments: [String]) -> [String] {
let task: NSTask = NSTask()
let pipe: NSPipe = NSPipe()
task.launchPath = launchPath
task.arguments = arguments
task.standardOutput = pipe
task.launch()
task.waitUntilExit()
let handle = pipe.fileHandleForReading
let data = handle.readDataToEndOfFile()
let outputString = String(data: data, encoding: NSUTF8StringEncoding) ?? ""
var outputArray = [String]()
outputArray = outputString.componentsSeparatedByCharactersInSet(.newlineCharacterSet())
return outputArray
}
我正在开发一个 Swift 应用程序,该应用程序与外部二进制文件(通过 NSTask)交互,并且 return 每行的输出都是字符串数组。
多次调用 executeCommand 函数时,命令开始无法达到 return 预期数据。
在下面的 Playground 示例中,我正在轮询 diskutil 以获取卷名称。
在调试区,我得到的第一个响应是:
- 不适用(无文件系统)
- Macintosh 高清
- 无法获取音量 姓名
- 无法获取卷名
- 无法获取卷名
只需重新运行 Playground 结果:
- 不适用(无文件系统)
- 无法获取卷名 <-- Macintosh HD 发生了什么?
- 无法获取卷名
- 无法获取卷名
无法获取卷名
import Cocoa func executeCommand(launchPath: String, arguments: [String], additionalDelay: Int=0) -> [String] { let outputPipe = NSPipe() var outputArray = [String]() let task = NSTask() task.launchPath = launchPath task.arguments = arguments task.standardOutput = outputPipe outputPipe.fileHandleForReading.waitForDataInBackgroundAndNotify() NSNotificationCenter.defaultCenter().addObserverForName(NSFileHandleDataAvailableNotification, object: outputPipe.fileHandleForReading , queue: nil) { notification in let output = outputPipe.fileHandleForReading.availableData let outputString = String(data: output, encoding: NSUTF8StringEncoding) ?? "" outputArray = outputString.componentsSeparatedByCharactersInSet(.newlineCharacterSet()) outputPipe.fileHandleForReading.waitForDataInBackgroundAndNotify() } task.launch() sleep(UInt32(additionalDelay)) // Additional delay task.waitUntilExit() // Remove last empty line from output array. if outputArray.count > 0 { outputArray.removeLast() } return outputArray } // Example usage // Output volume name from provided disk identifier func volumeName(identifier: String) -> String { let volumeNameCommand = "/usr/sbin/diskutil info \(identifier) | awk '/Volume Name:/' | sed 's/Volume Name://g'| sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'" let volumeNameOutput = executeCommand("/bin/bash", arguments: ["-c", volumeNameCommand]) var volumeName = "Unable to obtain volume name" if volumeNameOutput.count > 0 { volumeName = volumeNameOutput[0] } return volumeName } let identifiers = ["/dev/disk0","/dev/disk1","/dev/disk2","/dev/disk3","/dev/disk4"] for identifier in identifiers { print(volumeName(identifier)) }
我确实需要一致的结果,但不明白我哪里出错了。
如有任何帮助,我们将不胜感激!
我认为任务的异步执行导致了不一致的结果。下面是一个按预期工作的新函数:
func executeCommand(launchPath: String, arguments: [String]) -> [String] {
let task: NSTask = NSTask()
let pipe: NSPipe = NSPipe()
task.launchPath = launchPath
task.arguments = arguments
task.standardOutput = pipe
task.launch()
task.waitUntilExit()
let handle = pipe.fileHandleForReading
let data = handle.readDataToEndOfFile()
let outputString = String(data: data, encoding: NSUTF8StringEncoding) ?? ""
var outputArray = [String]()
outputArray = outputString.componentsSeparatedByCharactersInSet(.newlineCharacterSet())
return outputArray
}