【问题标题】:stderr not being redirected to variable when bash script run from NSTask/Process in Swift当 bash 脚本从 Swift 中的 NSTask/Process 运行时,stderr 没有被重定向到变量
【发布时间】: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 3Process 类,它不起作用 - 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


【解决方案1】:

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

如果 Xcode App 在 Debug 模式下运行,它就不起作用。但如果我“存档”应用程序并将其导出到“macOS 应用程序”,它确实可以工作!

Release 版本和 Debug 版本的 App 沙盒环境可能有关系。我不这么认为,但显然确实如此。

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2021-08-19
      • 2010-10-01
      • 2021-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-09
      • 2012-03-09
      • 2016-03-29
      相关资源
      最近更新 更多