'非法选项-C'试图从Swift运行终端命令 [英] 'illegal option -- c' trying to run a terminal command from Swift

查看:101
本文介绍了'非法选项-C'试图从Swift运行终端命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,所以我试图从MacOS的Swift应用程序中以bash运行Mosquitto发布命令.这是我的代码:

Okay so I'm trying to run a Mosquitto publish command in bash from a Swift application for MacOS. Here is my code:

@IBAction func buttonClicked(_ sender: Any) {
        let mosquittoCommand = "mosquitto_pub --cert blahblah.pem --key blahblah.key --cafile blahblah.pem -h 'blah.blah.com' -p 443 -t 'blah/blah/blah/blah' -m '{\"msg\": \"blahblahblah\", \"time\": \"2019-08-07T15:12:00Z\", \"id\": \"blah-blah-blah\", \"localpwd\": \"blahblahblah\"}' --tls-alpn x-amzn-mqtt-ca -i 'blahblahblah'"

        print(shell("cd /Users/Me/Desktop/certs && " + mosquittoCommand))
    }

    func shell(_ command: String) -> String {
        let task = Process()
        task.launchPath = "/usr/bin/env"
        task.arguments = ["-c", command]

        let pipe = Pipe()
        task.standardOutput = pipe
        task.launch()

        let data = pipe.fileHandleForReading.readDataToEndOfFile()
        let output: String = NSString(data: data, encoding: String.Encoding.utf8.rawValue)! as String

        return output
    }

我遇到以下错误:

/usr/bin/env: illegal option -- c
usage: env [-iv] [-P utilpath] [-S string] [-u name]
           [name=value ...] [utility [argument ...]]

您必须相信我,在终端窗口中直接运行命令可以按预期运行.唯一的区别是mosquitto命令中的转义字符可以防止引号使命令混乱.也许是逃逸字符引起了问题?

You'll have to trust me that running the command in a terminal window directly works as expected. The only difference is the escape characters in the mosquitto command to prevent the quotations messing up the command. Perhaps the escape chars are causing the problems?

我不知道该错误试图告诉我什么.任何建议将不胜感激.谢谢.

I have no idea what the error is trying to tell me. Any advice would be greatly appreciated. Thanks.

编辑-我已经确定了Swift工作中的一些基本命令(pwd,cd等)的链接.因此,它肯定已经正确设置为能够运行这样的命令,我只是不知道为什么它不能运行Mosquitto publish命令.

EDIT - I've made sure chaining some basic commands (pwd, cd... etc) from Swift works. So it's definitely set up correctly to be able to run commands like this, I just don't know why it can't run the Mosquitto publish command.

推荐答案

错误消息的直接原因是/usr/bin/env没有-c选项,显然您将其与/bin/bash -c "command ..."混合了.同样,env命令只能启动一个可执行文件,而不能与&&链接在一起的多个命令一起启动.

The immediate reason for the error message is that /usr/bin/env does not have a -c option, apparently you mixed that up with /bin/bash -c "command ...". Also the env command can only start a single executable, not multiple commands chained together with &&.

另一个问题是从Finder运行应用程序时找不到mosquitto_pub二进制文件.在讨论中发现,该程序(通过Homebrew)安装在/usr/local/bin中.该目录通常在Terminal Shell的搜索路径中,但是不在从Finder启动应用程序时.

The other problem is that the mosquitto_pub binary is not found when running your app from the Finder. As it turned out in the discussion, this program is installed (via Homebrew) in /usr/local/bin. That directory is usually in the search path of a Terminal shell, but not when an application is started from the Finder.

为程序使用绝对路径是一种选择:

Using an absolute path for the program is one option:

let mosquittoCommand = "/usr/local/bin/mosquitto_pub --cert blahblah.pem ..."

正如评论中已经说过的,设置启动路径(作为绝对路径),执行命令的工作目录以及命令参数作为数组更容易:

As already said in the comments, it is easier to set the launch path (as an absolute path), the working directory where the command should be executed, and the command arguments as an array:

let task = Process()
task.launchPath = "/usr/local/bin/mosquitto_pub"
task.arguments = [
    "--cert",
    "blahblah.pem",
    // ...
    "-i",
    "blahblahblah"
]
task.currentDirectoryPath = "/Users/Me/Desktop/certs"

这使引用参数和通过shell调用变得不必要.

This makes quoting the arguments and calling via the shell unnecessary.

或者,您可以通过env启动程序(以便在多个可能的位置找到该程序),然后在搜索路径中添加"/usr/local/bin":

Alternatively you can start the program via env (so that it is found at multiple possible locations) but then you have add "/usr/local/bin" to the search path:

// Add "/usr/local/bin" to search path:
var env = task.environment ?? [:]
if let path = env["PATH"] {
    env["PATH"] = "/usr/local/bin:" + path
} else {
    env["PATH"] = "/usr/local/bin"
}
task.environment = env

task.launchPath = "/usr/bin/env"
task.arguments = [
    "mosquitto_pub",
    "--cert",
    "blahblah.pem",
    // ...
    "-i",
    "blahblahblah"
]
task.currentDirectoryPath = "/Users/Me/Desktop/certs"

最后,您可以使用

task.currentDirectoryURL = FileManager.default
    .homeDirectoryForCurrentUser
    .appendingPathComponent("certs")

使工作目录可以使用任何用户名.

to make the working directory work with any user name.

这篇关于'非法选项-C'试图从Swift运行终端命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆