【发布时间】:2016-11-25 14:54:21
【问题描述】:
编辑:
这里是实际 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 - 进程/NSTask 不工作
但是,如果我从 Xcode 中的应用程序运行相同的脚本,使用 Swift 3 和 Process 类,它不起作用 - 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。
任何人都可以阐明这个问题,并帮助我解决这个问题吗?非常感谢您的尝试!
【问题讨论】:
-
defaults在您的路径中吗? -
@123,是的。从命令行绝对是的。从 Swift 代码中,我假设是这样,因为如果我运行另一个“默认读取”命令(仅使用标准输出的命令),一切都会按预期工作。
-
如果你不捕获命令并让它输出到STDERR,它会输出任何东西吗?
-
@123,你的意思是从我的脚本中取出'2>&1'并运行它?如果是这样,它也不会输出任何内容。
-
不要把它放在
$()之外并删除重定向。
标签: bash redirect command-line stderr nstask