I've been trying for some days now to find and equivalent to Ruby's exec in Swift.
I haven't yet been able to find a solution. Multiple sources online suggest how to forward predefined input to STDIN of the child process and out to read its output, but now how to start a child process and let it take control of the STDIN and STDOUT as if the Swift process was letting it take over.
The use case would be to run SSH commands and develop an in-house company tool, formerly in Ruby, that would allow similar features as heroku run /bin/sh for instance. I am already able to replicate things like heroku logs, since they donnot require user input.
The basic idea of starting a new process and attaching it to STDIN and STDOUT doesn't seem to be working as expected.
let task = Process()
task.launchPath = "/usr/bin/env"
task.arguments = ["bash", "-c", "read"]
task.standardInput = FileHandle.standardInput
task.standardOutput = FileHandle.standardOutput
task.standardError = FileHandle.standardError
task.launch()
task.waitUntilExit()
Any ideas or hints of how to achieve this ?
This appears to be a bug in Apple's Foundation. The intended behaviour should be that not assigning any of those would get you your desired result. As the documentation says:
(Similar things are said for
stdoutandstderrtoo)However,
stdindoesn't seem to be actually connected, so your input is being received by your Swift process, rather thanbash -c read.According to this similar discussion here on Swift Forums about allowing users to enter passwords into a subprocess,
Processis a wrapper aroundposix_spawn, but callingposix_spawndirectly worksCommandand Python'ssubprocess.runalso useposix_spawn, but they work correctly.SwiftFoundationframework from source and using theProcessclass from that, also works.Based on the above points, I think this is a bug.
For now, you can use this workaround (this is also from the Swift Forums post)