3

I'm developing console app for mac os in swift and i want to access user environment variables when calling bash command. I use the following code to run bash command in swift:

@discardableResult
func shell(_ command: String) -> String? {
    let task = Process()
    task.launchPath = "/usr/bin/env"
    task.arguments = ["bash", "-c", command]
    let pipe = Pipe()
    task.standardOutput = pipe
    task.launch()
    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(data: data, encoding: String.Encoding.utf8)

    return output
}

When i run /usr/bin/env in my terminal i see the desired variable but when i run shell("/usr/bin/env") in code i don't see one. The ProcessInfo.processInfo.environment["MY_ENV_VAR"] also don't show me the needed variable. How to access user defined env vars in swift?

2
  • Do you execute the compiled program from the Terminal, or from within Xcode? Commented Feb 16, 2019 at 15:32
  • within Xcode, tried Debug executable/No Debug executable/Release Commented Feb 16, 2019 at 15:36

2 Answers 2

4

I've been struggling with a very similar problem recently. While I don't have a perfect solution for you, I do have some suggestions.

First, it really matters where exactly MY_ENV_VAR has been defined. If it is inside of a .bashrc file, you'll need to start up bash in interactive mode with -i so it reads that file. If it is defined in .bash_profile, you'll need use -l to start a so-called login shell.

In my particular case, I have to use both -i and -l to see the env vars I'm after. This all gets even more complex if the user doesn't use bash. I use fish, for example, so my required ENV variables aren't visible to bash at all, regardless of the bash invocation.

So, what I actually do is first determine what shell is being used, and then invoke that shell with -i -l -c. zsh, bash and fish all support these options.

It's a real pain, and I'm not even sure that method is reliable. But, it is working for me across a number of different user environments.

Sign up to request clarification or add additional context in comments.

1 Comment

the -l is that what i've wanted
0
ProcessInfo.processInfo.environment

Will give you the environment variables for the user which launch the app but Xcode don't launch the app with your rights and environment.

So for the testing phase you can define the needed variable in Xcode like the photo below

enter image description here

If you want to be sure, write the following code in a file (e.i: "main.swift"):

import Foundation

print(ProcessInfo.processInfo.environment)

And in a shell execute swiftc main.swift then ./main and you will see the use variables

But you can use the C function getenv

  • it take a UnsafePointer<Int8> which is the key you need (i.e: "HOME") : a C char *
  • An return a UnsafeMutablePointer<Int8>! : The value

2 Comments

this is not exact answer. I need to access env from macos, from CI. In your solution its hardcoded in Xcode, so can be attacked by hacker and retrieved.
This is for Xcode env. But op want to access Mac's env like password stored in .zshrc or .bashrc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.