当 bash 脚本从 Swift 中的 NSTask/Process 运行时,stderr 不会被重定向到变量



编辑:

以下是实际 Xcode 测试项目的链接:

https://github.com/briggsm/StdErrTest

有了这个,我认为重现和看到这个问题将非常容易。

原文:

我有一个可执行文件(chmod +x)bash脚本(myScript.sh),如下所示:

#!/bin/sh
# auto login disabled
ald=$(defaults read /Library/Preferences/com.apple.loginwindow autoLoginUser 2>&1)
echo "ald: $ald"

命令行工作

如果我从命令行运行此脚本,它可以完美运行:

$ ./myScript.sh 
ald: 2016-11-25 17:13:14.467 defaults[26645:619328] 
The domain/default pair of (/Library/Preferences/com.apple.loginwindow, autoLoginUser) does not exist

输出来自stderr.

Xcode/Swift - Process/NSTask 不起作用

但是如果我使用Swift 3Process类从 Xcode 中的应用程序运行相同的脚本,它不起作用 -stderr似乎没有被重定向到stdout,变量 (ald) 只是一个空字符串。

作为参考,这是我的ViewController.swift代码:

import Cocoa
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func runProcessClicked(_ sender: NSButton) {
// Make sure we can find the script file. Return if not.
guard let path = Bundle.main.path(forResource: "myScript", ofType:".sh") else {
print("n  Unable to locate: myScript.sh!")
return
}
// Init outputPipe
let outputPipe = Pipe()
// Setup & Launch our process
let ps: Process = Process()
ps.launchPath = path
//ps.arguments = arguments
ps.standardOutput = outputPipe
ps.launch()
ps.waitUntilExit()
// Read everything the outputPipe captured from stdout
let data = outputPipe.fileHandleForReading.readDataToEndOfFile()
var outputString = String(data: data, encoding: String.Encoding.utf8) ?? ""
outputString = outputString.trimmingCharacters(in: .whitespacesAndNewlines)
// Return the output
print("[output: (outputString)]")
}
}

单击按钮后,我看到的输出是:

[output: ald:]

如果myScript.sh运行一个命令,该命令只是输出到stdout,该值确实存储在ald中,我可以从命令行和 Xcode 中看到它。

所以在我看来,问题是stderr没有在通过 Swift 运行流程/任务的上下文中重定向到stdout

任何人都可以阐明这个问题,并帮助我解决这个问题吗?非常感谢您的尝试!

嗯,也许与其说是"答案",不如说是"发现",但我会在这里发布,以防其他人发现它有用。

如果 Xcode App 在调试模式下运行,则它不起作用。但是,如果我"存档"该应用程序并将其导出到"macOS 应用程序",它确实有效!

可能与发布版本与调试版本中的应用程序沙盒环境有关。我不这么认为,但显然确实如此。

不过,我仍然想知道为什么它在 Xcode 中不起作用(在调试模式下),因为在 Xcode 中进行调试显然非常有用!

任何额外的想法将不胜感激!

我不知道这是否有帮助,但是我在尝试将stderror重定向到我的程序正在启动的NSTask(调试时)时遇到了类似的问题。 我发现如果我编辑方案并在"选项"选项卡下将控制台设置从"使用 Xcode"更改为"使用终端",我能够在调试器中成功重定向 stderror 并注册通知。

最新更新