'illegal option -- c' 尝试 运行 来自 Swift 的终端命令
'illegal option -- c' trying to run a terminal command from Swift
好的,所以我正在尝试从 Swift MacOS 应用程序 运行 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 ...]]
您必须相信我,运行在终端 window 中执行命令可以直接按预期工作。唯一的区别是 mosquitto 命令中的转义字符,以防止引号弄乱命令。也许转义字符导致了问题?
我不知道错误试图告诉我什么。任何建议将不胜感激。谢谢。
编辑 - 我已经确定从 Swift 链接一些基本命令(pwd、cd...等)是有效的。所以它肯定设置正确,能够 运行 这样的命令,我只是不知道为什么它不能 运行 Mosquitto 发布命令。
错误消息的直接原因是 /usr/bin/env
没有 -c
选项,显然您将其与 /bin/bash -c "command ..."
混淆了。此外,env
命令只能启动单个可执行文件,不能启动与 &&
链接在一起的多个命令。
另一个问题是当 运行 您的应用程序从 Finder 中找不到时 mosquitto_pub
二进制文件。正如讨论中所证明的那样,该程序安装(通过 Homebrew)在 /usr/local/bin
中。该目录通常位于终端 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"
这使得引用参数和通过 shell 调用变得不必要。
或者您可以通过 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")
使工作目录适用于任何用户名。
好的,所以我正在尝试从 Swift MacOS 应用程序 运行 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 ...]]
您必须相信我,运行在终端 window 中执行命令可以直接按预期工作。唯一的区别是 mosquitto 命令中的转义字符,以防止引号弄乱命令。也许转义字符导致了问题?
我不知道错误试图告诉我什么。任何建议将不胜感激。谢谢。
编辑 - 我已经确定从 Swift 链接一些基本命令(pwd、cd...等)是有效的。所以它肯定设置正确,能够 运行 这样的命令,我只是不知道为什么它不能 运行 Mosquitto 发布命令。
错误消息的直接原因是 /usr/bin/env
没有 -c
选项,显然您将其与 /bin/bash -c "command ..."
混淆了。此外,env
命令只能启动单个可执行文件,不能启动与 &&
链接在一起的多个命令。
另一个问题是当 运行 您的应用程序从 Finder 中找不到时 mosquitto_pub
二进制文件。正如讨论中所证明的那样,该程序安装(通过 Homebrew)在 /usr/local/bin
中。该目录通常位于终端 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"
这使得引用参数和通过 shell 调用变得不必要。
或者您可以通过 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")
使工作目录适用于任何用户名。