问题
I'm trying to make a mac app where the user can type in commands just like they would in the mac terminal, I got most of it working however I found out that the $PATH variable of apps run from the finder or xcode is different than the $PATH variable the Terminal uses.
I can run commands and also found a way to add a predefined path to the application's $PATH variable but I need a way to automatically read the Terminal's $PATH variable and copy it to the Application's $PATH variable. This should be automated as users will have different path's inside their variable.
I also found out that when I run the application from the terminal with "open appname.app" the correct $PATH variable is used (the same one the terminal uses)
This is my code so far:
let task = Process()
var env = ProcessInfo.processInfo.environment
var path = env["PATH"]! as String
path = "/usr/local/bin:" + path
env["PATH"] = path
task.environment = env
task.launchPath = "/usr/bin/env"
task.arguments = ["echo","$PATH"]
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
task.launch()
task.waitUntilExit()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output: String = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as! String
print(output)
This will add "/usr/local/bin" to the Application's $PATH but I need a way to copy the values from the Terminal's $PATH.
Thanks!
回答1:
Adding bash Shell Path
The default shell paths can be found in /etc/paths
and /etc/path.d/
. One way to read the shell paths is to use the path_helper
command. Extending the code example above and using bash as the shell:
let taskShell = Process()
var envShell = ProcessInfo.processInfo.environment
taskShell.launchPath = "/usr/bin/env"
taskShell.arguments = ["/bin/bash","-c","eval $(/usr/libexec/path_helper -s) ; echo $PATH"]
let pipeShell = Pipe()
taskShell.standardOutput = pipeShell
taskShell.standardError = pipeShell
taskShell.launch()
taskShell.waitUntilExit()
let dataShell = pipeShell.fileHandleForReading.readDataToEndOfFile()
var outputShell: String = NSString(data: dataShell, encoding: String.Encoding.utf8.rawValue) as! String
outputShell = outputShell.replacingOccurrences(of: "\n", with: "", options: .literal, range: nil)
print(outputShell)
let task = Process()
var env = ProcessInfo.processInfo.environment
var path = env["PATH"]! as String
path = outputShell + ":" + path
env["PATH"] = path
task.environment = env
task.launchPath = "/usr/bin/env"
task.arguments = ["/bin/bash", "-c", "echo $PATH"]
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
task.launch()
task.waitUntilExit()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
var output: String = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as! String
output = output.replacingOccurrences(of: "\n", with: "", options: .literal, range: nil)
print(output)
Note:
- This code example calls the shell in non-interactive mode. This means that it won't execute any user specific profiles; such as
/Users/*userid*/.bash_profile
. - The paths can be listed multiple times in the
PATH
environment variable. They will be traversed from left to right.
References
There are a couple of threads on application and shell PATH's for OS X which provide more context How to set system wide environment variables on OS X Mavericks and Setting the system wide path environment variable in mavericks
来源:https://stackoverflow.com/questions/41535451/how-to-access-the-terminals-path-variable-from-within-my-mac-app-it-seems-to