简体   繁体   English

在Swift中从Cocoa App运行终端命令失败:“未找到命令”,但在Swift中使用命令行工具运行

[英]Running terminal commands from Cocoa App in Swift failing: “command not found” but works using Command Line Tool in swift

I created an App that exports all of my iMessages into an app I use for journaling. 我创建了一个将所有iMessage导出到用于日记的应用程序的应用程序。 It accesses the chat.db file in Libary/Messages/ to do this. 为此,它将访问Libary / Messages /中的chat.db文件。 This part works great 这部分效果很好

I was required to use frameworks and Command Line Tools won't allow you to bundle Frameworks in macOS. 我被要求使用框架,并且命令行工具不允许您在macOS中捆绑框架。 I would have preferred to for this all to be a script and avoid Cocoa altogether, but was required to use a full Cocoa application because of the need for bundled Frameworks 我本来希望将其全部用作脚本并完全避免使用Cocoa,但是由于需要捆绑的框架,因此要求使用完整的Cocoa应用程序

I can enter commands like pwd and get a response back. 我可以输入pwd命令并获得响应。 However, when I try to run the terminal commands for the journaling app, it fails with "command not found" 但是,当我尝试运行日记应用程序的终端命令时,它失败并显示“找不到命令”

If I run the exact same command from within terminal, or from within a Swift Command Line Tool in Xcode, it works. 如果我从终端或Xcode的Swift命令行工具中运行完全相同的命令,则它可以工作。 However, now that I'm using an actual Cocoa app it won't work. 但是,既然我正在使用实际的Cocoa应用程序,它将无法使用。

Here is an example of my code: 这是我的代码示例:

   let pipe = Pipe()
let task = Process()
task.launchPath = "/bin/sh"
task.arguments = ["-c", String(format:"%@", "dayone2 new 'Hello'")]
task.standardOutput = pipe
let file = pipe.fileHandleForReading
task.launch()
if let result = NSString(data: file.readDataToEndOfFile(), encoding: String.Encoding.utf8.rawValue) {
    return result as String
}
else {
    return "--- Error running command - Unable to initialize string from file data ---"
}

and the response: /bin/sh: dayone2: command not found 和响应: /bin/sh: dayone2: command not found

Add "--login" as the first task argument: 添加"--login"作为第一个任务参数:

task.arguments = ["--login", "-c", "dayone2 new 'Hello'"]

and that should fix your error. 这应该可以解决您的错误。

Explanation: 说明:

When you run Terminal the shell starts up as a login shell, from man sh : 当您运行Terminal时,shell从man sh作为登录shell启动:

When bash is invoked as an interactive login shell, or as a non-inter-active shell with the --login option, it first reads and executes commands from the file /etc/profile , if that file exists. 当bash作为交互式登录shell或通过--login选项作为非交互式shell调用时,它首先从文件/etc/profile (如果存在)读取并执行命令。 After reading that file, it looks for ~/.bash_profile , ~/.bash_login , and ~/.profile , in that order, and reads and executes commands from the first one that exists and is readable. 读取该文件后,它将~/.bash_login顺序查找~/.bash_profile~/.bash_login~/.profile ,并从存在且可读的第一个命令中读取并执行命令。

Among other things the commands in these files typically set the $PATH environment variable, which defines the search path the shell uses to locate a command. 这些文件中的命令通常会设置$PATH环境变量,该变量定义外壳程序用来查找命令的搜索路径。

When you run your command line tool in the Terminal it inherits this environment variable and in turn passes it on to the shell it invokes to run your dayone2 command. 当您在终端中运行命令行工具时,它会继承该环境变量,然后将其传递到外壳程序上,它会调用该外壳程序来运行dayone2命令。

When you run a GUI app there is no underlying shell and the $PATH variable is set to the system default. 运行GUI应用程序时,没有基础外壳,并且$PATH变量设置为系统默认值。 Your error "command not found" indicates that your dayone2 command is not on the default path. 您的错误“未找到命令”表明您的dayone2命令不在默认路径上。

HTH HTH

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM