好的,所以我试图从MacOS的Swift应用程序中以bash运行Mosquitto发布命令。这是我的代码:
@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命令中的转义字符可以防止引号使命令混乱。也许是逃逸字符引起了问题?
我不知道该错误试图告诉我什么。任何建议将不胜感激。谢谢。
编辑-我已经确定了Swift工作中的一些基本命令(pwd,cd等)的链接。因此,它肯定已经正确设置为能够运行这样的命令,我只是不知道为什么它不能运行Mosquitto发布命令。
答案 0 :(得分:1)
该错误消息的直接原因是/usr/bin/env
没有-c
选项,显然您将其与/bin/bash -c "command ..."
混合了。同样,env
命令只能启动一个可执行文件,而不能与&&
链接在一起的多个命令一起启动。
另一个问题是从Finder运行应用程序时找不到mosquitto_pub
二进制文件。讨论中已证明,此程序(通过Homebrew)安装在/usr/local/bin
中。该目录通常位于Terminal Shell的搜索路径中,但不是从Finder启动应用程序时。
为程序使用绝对路径是一种选择:
let mosquittoCommand = "/usr/local/bin/mosquitto_pub --cert blahblah.pem ..."
如注释中所述,设置启动路径(作为绝对路径),应在其中执行命令的工作目录以及命令参数作为数组更容易:
let task = Process()
task.launchPath = "/usr/local/bin/mosquitto_pub"
task.arguments = [
"--cert",
"blahblah.pem",
// ...
"-i",
"blahblahblah"
]
task.currentDirectoryPath = "/Users/Me/Desktop/certs"
这使得不需要引用参数并通过外壳进行调用。
或者,您可以通过env
启动程序(以便在多个可能的位置找到该程序),然后在搜索路径中添加“ / usr / local / bin”:
// 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")
使工作目录可以使用任何用户名。