Skip to content
This repository has been archived by the owner on Mar 3, 2023. It is now read-only.

load $PATH when launched as an app #6956

Closed
willwhitney opened this issue May 26, 2015 · 16 comments
Closed

load $PATH when launched as an app #6956

willwhitney opened this issue May 26, 2015 · 16 comments
Labels
enhancement mac Issues that occur on macOS but not on other platforms.

Comments

@willwhitney
Copy link

When Atom is launched as an application, it doesn't get the user's PATH, because it was launched by launchctl. This means that packages like script and hydrogen have to tell the user to launch Atom from the command line. Some packages (like hydrogen) can't even be installed without the PATH because their dependencies use native extensions built with node-gyp. There exist tools such as fix-path, but they clobber the user's PATH even if they've set something on purpose (with e.g. a virtualenv).

Having access to the user's PATH will become more and more important as people build packages that interface more deeply with languages, other tools, and the user's environment. Forcing the user to configure each package with complete paths to the binaries it needs is possible, but inelegant, and becomes intractable with general-purpose tools.

This seems like a clear situation where making this change to Atom itself would dramatically simplify life for many packages and eliminate many bugs arising from poor attempts to capture the PATH.

@thomasjo thomasjo added mac Issues that occur on macOS but not on other platforms. enhancement labels May 26, 2015
@rgbkrk
Copy link

rgbkrk commented May 26, 2015

At least from the node runtime, a process can be found on the launchctl list filtering out for the process.pid:

$ launchctl list | grep Atom
83917   -   0x7fcf11d092e0.anonymous.Atom
84086   -   0x7fcf11d0c8d0.anonymous.Atom Helper
83917   -   0x7fcf11e02cd0.anonymous.Atom
84089   -   0x7fcf11d0bcf0.anonymous.Atom Helper
84088   -   0x7fcf11d0ba40.anonymous.Atom Helper
84086   -   0x7fcf11c11930.anonymous.Atom Helper
83919   -   0x7fcf11c0f8a0.anonymous.Atom Helper

Here's the init.coffee I'm now using (as of seconds ago):

try
  childProcess = require('child_process')

  atomProcs = childProcess.execSync("launchctl list | grep #{process.pid} | grep Atom").toString().split()
  launchRegex = ///^#{process.pid}\t[0\-]\t.*\.Atom///
  matches = (line for line in atomProcs when launchRegex.exec(line))

  if matches.length > 0
    console.log("Fixing paths for Atom")
    process.env.PATH = childProcess.execFileSync('/bin/bash', ['-c', 'echo $PATH']).toString().trim()
    process.env.GOPATH = childProcess.execFileSync('/bin/bash', ['-c', 'echo $GOPATH']).toString().trim()

catch exception
  console.error("Exception during PATH fixes: #{exception}")

It would be great for Atom to detect if it's running from launchd and build the process.env by shelling out on OS X.

@mathiasringhof
Copy link

launchctl can be used to give Atom the correct path even when launching using Spotlight / Dock.

From the man page describing the sub command config:

config system | user parameter value

Sets persistent configuration information for launchd(8)
domains.

One of the two available parameters is path:

path

Sets the PATH environment variable for all services
within the target domain to the string value.

This worked for me:

sudo launchctl config system path /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

Using the user instead of the system domain had no effect.

If you don't want to permanently modify your launchctl config you can also start the following script at bootup, say from Apple Script:

launchctl setenv PATH $PATH

@basnijholt
Copy link

Git filter clean smudge doesn't use the correct python version for me, took me a while before I got here.

Any updates on this?

@derwaldgeist
Copy link

+1
This problem also affects other environment variables on MacOS. I'm using an addon package for Meteor that requires access to a variable called $PACKAGE_DIRS. This variable is available to the package if I start Atom from the terminal, but not if I start it normally as an app.

@UltCombo
Copy link

+1
There are several packages related to terminal operations which could benefit from this.

@ghost
Copy link

ghost commented Sep 18, 2015

Just edit process.env.PATH on the init file, you can append more paths there.

@UltCombo
Copy link

@peduxe Did you read my comment above? I'm talking about hundreds of package authors affected by this issue. And obviously, telling all these packages' users to "just edit their init file" is not an acceptable solution.

Letting alone that your suggestion goes completely against DRY -- if I add something to my PATH environment variable, I expect it to be available in all applications that make use of the PATH variable without having to hack around weird configs on each app every time I edit the PATH. That is the whole point of having environment variables, after all.

@basnijholt
Copy link

@UltCombo I completely agree with you. Things should just work when you install them, out of the box.

@ghost
Copy link

ghost commented Sep 18, 2015

@UltCombo Yes you're right it should be corrected no matter what, I simply provided a quick solution for those who didn't know about it.

@UltCombo
Copy link

@peduxe Oh, sorry for the misunderstanding. 😄

By the way, I've added fix-path to my Atom package as a temporary workaround for the issue, but it comes at its own cost as described in the OP (e.g. if you've overridden/extended the PATH in your init script, then fix-path will overwrite your changes).

@iskeld
Copy link

iskeld commented Oct 21, 2015

The solution suggested by @mathiasringhof didn't work for me on El Capitan, I had to use "user" domain:

sudo launchctl config user path /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

@justo
Copy link

justo commented Dec 22, 2015

I don't like hardcoding my path anywhere since it's assembled through my dotfiles and changes when I update node with NVM. Having said that one of the previous solutions posted using process.env.SHELL and echo $PATH didn't work because it grabbed my ZSH welcome message as well. Adding this to my init.coffee works (on El Capitan) by only getting the last line echoed:

childProcess = require('child_process')

shellOutput = childProcess.execFileSync(process.env.SHELL, ['-i', '-c', 'echo $PATH']).toString().trim().split('\n')
process.env.PATH = shellOutput[shellOutput.length - 1]

More explanation in the gist: https://gist.github.com/justo/4a92655056f43d32ae72

@steelbrain
Copy link
Contributor

I have fixed the $PATH OSX issue in AtomLinter providers a few hours ago and here's how I did it. I evaluated several different npm packages available to do the job, they either didn't work, were slow or had no caching at all. If we would have 30 linter providers, they would spawnSync 60 processes to determine path.

Therefore I've created my own consistent-path npm module that does not modify globals and returns a correct $PATH for you to use and caches the value across the entire app. It works on all three major OSes.

I would recommend this to every Atom package developer who's experiencing this issue

@joefitzgerald
Copy link
Contributor

I think this needs to be solved in core, and not via an npm package or an atom package (and I say this as the author of https://atom.io/packages/environment).

I think we need to do two things to fix Atom's handling of the environment:

  1. Solve the OS X "open Atom via a launchctl launched process" (i.e. Finder, Dock, Spotlight, open) centrally in atom but only for the OS X platform; either by patching process.env, or providing some central function that provides access to a sane environment regardless of the platform being used
  2. Provide a project-level API for the environment, so that when a user launches Atom twice - for two different projects - each project can use its own environment (e.g. SOMEVAR=true atom project-one and SOMEVAR=false atom project-two), which would use the aforementioned sane environment if the project was not launched from the terminal

/cc @lee-dohm

@skull-squadron
Copy link
Contributor

skull-squadron commented Apr 21, 2017

The hack to set env vars in ~/.atom/init.coffee works / doesn't nondeterministically because packages can load before it. There needs to be a ~/.atom/boot.coffee or something which is run synchronously, before all packages, so that the early environment can be set cleanly.

@lock
Copy link

lock bot commented Apr 2, 2018

This issue has been automatically locked since there has not been any recent activity after it was closed. If you can still reproduce this issue in Safe Mode then please open a new issue and fill out the entire issue template to ensure that we have enough information to address your issue. Thanks!

@lock lock bot locked and limited conversation to collaborators Apr 2, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement mac Issues that occur on macOS but not on other platforms.
Projects
None yet
Development

No branches or pull requests