0

So I have a shell function that looks like this:

func shell(command: String) -> String {
    var output = ""
    var error = ""

    do {
        let task = Process()

        task.launchPath = "/bin/bash"

        task.arguments = ["-c", command]

        let outputPipe = Pipe()
        task.standardOutput = outputPipe
        let errorPipe = Pipe()
        task.standardError = errorPipe

        try task.run()

        let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
        output = NSString(data: outputData, encoding: String.Encoding.utf8.rawValue)! as String
        let errorData = errorPipe.fileHandleForReading.readDataToEndOfFile()
        error = NSString(data: errorData, encoding: String.Encoding.utf8.rawValue)! as String
    }
    catch let err as NSError{
        output = err.localizedDescription
    }
    return error + "\n" + output + "\n"
}

Into this function I pass my command, which is a Mosquitto Publish command - mosquitto_pub. Bash doesn't seem to know where this is unless I specify /usr/local/bin/mosquitto_pub. With that at the start of the command string it works perfectly. The problem is that I don't know that it will be installed at that location for all users so I can't rely on a hard coded path. So I need to find it first and add it to my command string before passing it to the shell function.

In a terminal I can use which mosquitto_pub and it returns the full path. Excellent. However, when I pass which mosquitto_pub as a command to the shell function via my swift program, it doesn't return anything. I've also tried type instead of which, but it responds with /bin/bash: line 0: type: mosquitto_pub: not found

Anyone know why the terminal can find it normally but not when it's being used from within my Swift program?

SuperHanz98
  • 2,090
  • 2
  • 16
  • 33
  • I assume that it is the same problem as in your previous question https://stackoverflow.com/q/57396691/1187415. `/usr/local/bin` is not in the search path of the app, therefore the `which` command cannot find the executable. You can *add* it to the search path and use env, as I suggested in https://stackoverflow.com/a/57398511/1187415. – Martin R Aug 12 '19 at 10:59
  • Hi @MartinR, the problem I had with env is that listing the commands one after another in an array didn't work, and as you pointed out env has no -c option to read them in as one string. Hence I switched to bin/bash instead of env – SuperHanz98 Aug 12 '19 at 11:45
  • Adding /usr/local/bin to the PATH variable in the process environment should help also if you use /bin/bash. – Martin R Aug 12 '19 at 11:47
  • But Mosquitto might not necessarily be installed in `usr/local/bin`. I want to use `which` so that it can locate Mosquitto wherever it is installed – SuperHanz98 Aug 12 '19 at 11:48
  • `which` also relies on the PATH variable. If you install the binary in `/some/strange/path` then which/type/bash will not find it. The difference between the Terminal and an App (started from the Finder) is that the former has /usr/local/bin in the search path by default, and the latter has not. – Martin R Aug 12 '19 at 11:51
  • Ah so `which` only searches through the path variable? Could I use some other command to locate Mosquitto? – SuperHanz98 Aug 12 '19 at 11:55
  • The path variable is "it". Most installed software will leave at least a symlink in /usr/local/bin which will reference where the main program of the software package is actually installed. IF just using the symlink is not good enough, perhaps because you want to run an internal component of the package, then you might need to expand the symlink in software (use realpath) and follow it where it leads. – Gem Taylor Aug 12 '19 at 19:40

0 Answers0