Good morning,
in my OSx App I would like to execute a command from the shell. As long as I did it with apple script or in the Terminal window it worked fine. but when I execute it via swift it won't work. the command is:
ssh -p 10001 root@nozbfa.anywareip.net -L 23389:192.168.38.11:3389 -f sleep 20I tried it via a function
@discardableResult
func shell(_ args: String...) -> String {
let task = Process()
task.launchPath = "/bin/bash/"
task.arguments = args
let pipe = Pipe()
task.standardOutput = pipe
task.launch()
task.waitUntilExit()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
guard let output: String = String(data: data, encoding: .utf8) else { return "" } return output
}shell("ssh", script)var script is:
-p 10001 root@nozbfa.anywareip.net -L 23389:192.168.38.11:3389 -f sleep 20and it returns:
/usr/bin/ssh: /usr/bin/ssh: cannot execute binary filewhat am I doing wrong?
I would like to execute a command from the shell
I strongly recommend against that. The shell is a vastly complex system with lots of sharp edges, which makes it much harder to call via
Process. For example, every time you want to pass in a path, you have to quote that path. Worse yet, this complexity often introduces really subtle security vulnerabilities.
It’s better to invoke the command in question (in this case
ssh) directly.
Having said that, I can certainly offer you feedback about your code:
Line 4 is wrong. You shouldn’t rely on
being present, and you certainly shouldn’t have a trailing slash on it. Usebash
./bin/shI don’t understand what you’re trying to do with line 5. Generally the shell takes:
A path to a script as an argument
A script via the
option-c
It looks like you’re trying to pass in the script without using
, which is not going to work.-cLines 9 and 10 need to be reversed. Remember that pipes have a limited buffer size (can’t find the value right now but it’s around 8 KiB if I remember correctly). If the child process outputs more than that amount of data before exiting, it’s write will block. That’ll deadlock because:
You don’t start reading until the child exits
The child won’t exit until you start reading
Finally, is your app sandboxed? If so, that introduces another level of complexity (-:
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"