【问题标题】:How can I stop printing Terminal in Swift如何停止在 Swift 中打印终端
【发布时间】:2022-01-22 20:42:37
【问题描述】:

我想让下面的代码适用于 Swift,没有/dev/null 2>&1 的代码可以正常工作,只要我添加/dev/null 2>&1,它就不起作用,我怎样才能正确添加它?

let task = Process()
task.executableURL = URL(fileURLWithPath: "/bin/bash/dev/null 2>&1")
task.arguments = ["-c", """
                    echo "Hello, world!"
                    cd ${HOME}
                    cd Desktop
                    mkdir "New Folder"
                    echo "Folder is Successfully created!"
                    """]
task.launch()

【问题讨论】:

  • 不清楚。 2>&1 表示将错误输出 (stderr) 放入正常输出 (stdout)。那么 ""/bin/bash/dev/null 2>&1"" 怎么可能是文件路径呢?如果在task,如果你不读取输出,那么检查输出,但不打印呢?错误一也一样。
  • @Larme:我在 Bash 方面并不先进,但就我现在而言,2>&1 应该静音以防万一。同样正如我在问题中提到的,我在询问正确的用例方式,我只是自己添加。需要学习正确的方法。
  • @ioscoder 你这里的脚本只是一个示例脚本,还是你真的想在$HOME/New Folder 创建一个新目录?因为如果是后者,您根本不需要为此使用 ProcessbashFileManager 将是正确的方法。
  • @ItaiFerber:非常感谢,但我希望它在 swift 中用于 bash 目的。有一段时间我想要静音打印。

标签: swift bash shell terminal


【解决方案1】:

这里有两个主要问题:

  1. 您要运行的二进制文件的可执行 URL 需要指向该二进制文件 — 它不能接受参数,因为 /bin/bash/dev/null 2>&1 不是磁盘上的有效路径。如果要运行/bin/bash,可执行的URL只能包含/bin/bash
  2. 您尝试执行的重定向也没有完全正确地写出。简要地:
    • 2>&1bash 中的意思是“请将stderr (2) 指向stdout (1) 当前指向的位置”
    • 为了首先重定向stdout,仅仅指定/dev/null是不够的——你需要告诉bash“请将stdout指向/dev/null”,这是用简写>/dev/null完成的(注意前面的> 意思是“重定向”)

这些重定向的语法是您正在运行的实际 shell 的一部分,虽然 bash 可能理解 >/dev/null,但这并不适用于所有进程。

请求bash 重定向的一种方法是将重定向请求包含在您正在运行的shell 脚本中(即,您传递给-c 的内容)。这开始进入bash 的细节以及它如何处理重定向,但是一个如何实现这一点的示例:

task.arguments = ["-c", """
                        exec >/dev/null 2>&1
                        # The rest of your script.
                        """]

exec 行导致bash 影响重定向,并且它在脚本的其余部分保持活动状态。解释细节可能超出范围,但请查看How to redirect output of an entire shell script within the script itself? 了解更多信息。

但是:

代替这种bash 特定的方法,一种不太脆弱且更具表现力的方法来实现这一点,即在Process 本身上显式设置.standardOutput.standardError 属性。您可以使用以下内容从bash 外部重定向stdoutstderr

let task = Process()
task.executableURL = URL(fileURLWithPath: "/bin/bash")
task.arguments = ["-c", "..."]
task.standardOutput = FileHandle.nullDevice // Equivalent to /dev/null
task.standardError = FileHandle.nullDevice
task.launch()

Process 上的.standardInput.standardOutput.standardError 帮助指示进程的输入来自何处以及其输出去向。默认情况下,这些是从您当前的进程继承的(这就是为什么您甚至会在自己的输出中看到bash 的输出),但您可以将FileHandle 分配给将输出写入文件,或设置Pipe 以便能够直接读取输出。

上述重定向适用于任何进程,而不仅仅是bash,建议您使用这些语义属性而不是依赖bash 解析。


如果您不关心具体重定向到/dev/null,您可以通过传入nil 而不是FileHandle.nullDevice,或者关闭进程的stdoutstderr

task.standardOutput = nil
task.standardError = nil

对于此特定应用程序,此分配将与重定向到 /dev/null 具有相同的效果:脚本的输出将被静音。

技术上这两者之间存在差异(如果脚本正在检查其 stdoutstderr 的输出位置),但在最常见的用例中,这将是等效的.考虑将其用作“简化”而不是直接引用 FileHandle.nullDevice

【讨论】:

  • 感谢您帮助我,但第一块中关于 task.arguments = [">/dev/null", "2>&1", "-c", "..."] 的代码对 Swift 错误没有多大帮助:/bin/bash: >/dev/null: No such file or directory
  • @ioscoder 在我的机器上它似乎可以工作,但间歇性地工作。我强烈推荐使用.standardOutput.standardError,我想我会完全删除最初的建议。
  • 你的回答解决了我的问题,我想知道如何快速正确地使用/dev/null 2>&1
  • @ioscoder 有关该方法的更多信息,stackoverflow.com/questions/314675/… 可能会对一些细节有所帮助。
  • 谢谢,我会尝试使用exec >/dev/null 2>&1,你的回答完全解决了我的问题我只是需要更多地学习如何使用>/dev/null 2>&1,更新:我刚刚尝试过,它可以工作,再次感谢. :)
猜你喜欢
  • 2020-06-03
  • 2019-07-13
  • 1970-01-01
  • 2016-02-07
  • 1970-01-01
  • 1970-01-01
  • 2018-05-08
  • 2020-02-16
  • 2022-11-02
相关资源
最近更新 更多