27

Having some issues with PATH settings on Emacs that are affecting my Haskell environment:

I'm using ZSH, and when I go to the command line and call echo $PATH, it returns: /Users/g/Library/Haskell/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin

This is coming from .zprofile configuration where I have:

# Set the list of directories that Zsh searches for programs.
path=(
  ~/Library/Haskell/bin
  /usr/local/{bin,sbin}
  $path
)

So, from command line, when I call which cabal, I correctly get: /Users/g/Library/Haskell/bin/cabal

When I start Emacs and go to the shell and call which cabal, I get: /usr/bin/cabal which is causing me issue since it's a different version.

When I inspect echo $PATH from the Emacs shell, I see: /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/g/Library/Haskell/bin:/usr/local/sbin

I've no idea how on earth the PATH can be different...

Anyone knows how to get my ZSH shell and Emacs to agree on the same PATH? I suspect that's what's controlling where cabal is being loaded from.

UPDATE: Running echo $SHELL from Emacs prints: /bin/zsh

UPDATE 2: This is on OSX.

UPDATE 3: I have tried to use exec-path-from-shell module and it does not work. I still have same issues, and as a side effect, it messes up my terminal theme colours :(

UPDATE 4: I've installed Emacs via brew install --cocoa --srgb emacs and I run emacs that's linked this way:

~ ❯❯❯ which emacs
/usr/local/bin/emacs
~ ❯❯❯ l /usr/local/bin/emacs
lrwxr-xr-x  1 g  admin    30B 29 Jan 18:34 /usr/local/bin/emacs -> ../Cellar/emacs/24.4/bin/emacs
~ ❯❯❯ l /usr/local/Cellar/emacs/24.4/bin/emacs
-r-xr-xr-x  1 g  admin    87B 29 Jan 18:34 /usr/local/Cellar/emacs/24.4/bin/emacs
7
  • Are you using ZSH as your login shell?
    – wasamasa
    Commented Apr 16, 2015 at 16:36
  • Not sure what you mean by login shell exactly, but I guess I called chsh... back in the day to change my default shell Commented Apr 16, 2015 at 16:46
  • I'm using iTerm2 btw... Commented Apr 16, 2015 at 16:47
  • 2
    Apparently not, modify PATH in ~/.profile or /etc/profile then.
    – wasamasa
    Commented Apr 16, 2015 at 17:23
  • 1
    Set your environment variables in ~/.zshenv, which will be consistently sourced however the shell is started (interactive vs. non-interactive). If exec-path-from-shell is messing up your terminal theme colours, you can set exec-path-from-shell-arguments to nil before calling exec-path-from-shell-initialize to make sure it's not running the interactive parts of your zsh config.
    – sanityinc
    Commented Apr 18, 2015 at 10:48

7 Answers 7

29

You can also install exec-path-from-shell package and add this to your init file:

(exec-path-from-shell-initialize)
4
  • 1
    The question would be better with a link to the cited package.
    – Drew
    Commented Apr 17, 2015 at 14:15
  • You're right, I've just edited my answer.
    – Basak
    Commented Apr 18, 2015 at 14:58
  • 1
    This is all I ever wanted. Commented Jan 20, 2017 at 23:21
  • This package is quite slow on macos, however... it noticeably slows down emacs startup.
    – AdamC
    Commented Mar 13, 2023 at 22:49
11

This is an OSX annoying environment issue, the $PATH appearing in Emacs is coming from /etc/paths file, which then gets appended with whatever I've set in the shell. I added /Users/g/Library/Haskell/bin to the top of the /etc/paths file and it then worked fine.

Going into shell and calling echo $PATH in Emacs shows now: /Users/g/Library/Haskell/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/sbin

And cabal's version is indeed cabal-install version 1.22.2.0 :D

Thanks all!!

4
  • Thanks to beOn for his hints in this $PATH on OSX post. Commented Apr 17, 2015 at 7:18
  • 2
    A better solution is to modify path in ~/.zshenv. Changes there are reflected in Emacs' PATH Commented Apr 24, 2015 at 15:57
  • I can confirm that simply doing echo export PATH=$PATH > ~/.zshenv makes Emacs' M-x shell pick it up on the next invocation. Commented Aug 16, 2016 at 21:35
  • In 2020, OSX Mojave 10.14.6 doesn't appear to set the Mac Emacs path per the /etc/paths file. A Mac Emacs subshell does seem to have run ~/.bashrc but not ~/.profile_bash, so you could set it in ~/.bashrc
    – Dave X
    Commented May 15, 2020 at 1:31
7

If you start emacs from your GUI environment (gnome, kde, ...) your shell startup scripts will not be sourced into your environment. So the $PATH that you carefully set in your .zsh will not be loaded. GUI environments do not generally source these, though they may load your ~/.profile file.

You can try adding this to your .pam_environment:

PATH DEFAULT=${PATH}:/MYHOMEDIR/Library/Haskell/bin:/usr/local/bin:/usr/local/sbin

You will need to restart your GUI session to load it.

This document might help you to get your $PATH variable set properly:

https://help.ubuntu.com/community/EnvironmentVariables#Session-wide_environment_variables

I use the ~/.pam_environment file to managed environment variables that I need to be accessible from my shell or emacs processes.

PS: An astute commenter points out that you are probably on Mac. I don't know how to set up your $PATH in the Mac GUI, but the point still stands regarding the difference between your shell's environment and the GUI environment. How you set up the $PATH for the GUI seems to depend on the OS version. However you can use:

(setenv "PATH" (concat (getenv "PATH") ":/foo/bar"))

in your ~/.emacs.d/init if you just want a solution that should work.

PPS: If you want to run a shell in emacs, you are probably better off using ansi-term rather than shell.

2
  • 2
    I doubt the question is about Linux given the questioner mentioned the use of iTerm 2.
    – wasamasa
    Commented Apr 16, 2015 at 22:39
  • I must say this was a mystery for me. Thank you very much good person.
    – jgomo3
    Commented May 3, 2022 at 13:04
3

If some part of the PATH gets lost then you can add it in your ~/.emacs

;;; We add /path/to/something/extra by appending it to the path
(setenv "PATH" (concat (getenv "PATH") ":/path/to/something/extra"))
;;; /path/to/something/extra is now at the end of the PATH.
;;; or you can use:
;(setenv "PATH" (concat "/path/to/something/extra:" (getenv "PATH")))
;;; /path/to/something/extra is now at the beginning of the PATH.

To avoid PATH issues, I always start emacs from the command line with the PATH exported from ~/.bashrc.

0
3

Another way to accomplish this is to simply tell the shell that it's a login shell so that it sources all of the right files. I do this for bash by setting explicit-bash-args to ("--noediting" "--login"). It looks like the equivalent for zsh would be to set explicit-zsh-args to ("-l").

So in my .emacs:

(setq explicit-bash-args '("--noediting" "--login"))

In yours, something like:

(setq explicit-zsh-args '("-l"))

I think the "--noediting" is unnecessary, and there doesn't seem to be a way to tell zsh about this, but that might be something to investigate if this doesn't work as well as you'd hope.

1
  • 1
    This works for a shell run under Emacs. It does not work for commands run directly within Emacs, such as via M-x shell-command.
    – mernst
    Commented Jul 30, 2018 at 18:41
1

You can also set an OS X-wide default path by for example saving a property list like this as ~/Library/LaunchAgents/my.startup.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>my.startup</string>
  <key>ProgramArguments</key>
  <array>
    <string>sh</string>
    <string>-c</string>
    <string>launchctl setenv PATH /usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

The new path should be shown in shells, Emacs, and other applications after you log out and back in.

This method does not change the path in applications that are opened as login items or when applications are reopened at login after a forced shutdown. If you have Emacs, a terminal application, or other applications where you want to change the path in login items, you'll have to remove them.

In 10.9 and earlier you can also add a line like this to /etc/launchd.conf:

setenv PATH /usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin

However support for /etc/launchd.conf was removed in 10.10.

0

The given solutions didn't work for me. The reason is the latest Emacs compiled with --with-native-compilation picks up the PATH before loading init.el (to start compiling the packages with gcc).

This solution works if you put it into early-init.el.

(defun set-exec-path-from-shell-PATH ()
  "Set up Emacs' `exec-path' and PATH environment variable to match
that used by the user's shell.

This is particularly useful under Mac OS X and macOS, where GUI
apps are not started from a shell."
  (interactive)
  (let ((path-from-shell (replace-regexp-in-string
              "[ \t\n]*$" "" (shell-command-to-string
                      "$SHELL --login -c 'echo $PATH'"
                            ))))
    (setenv "PATH" path-from-shell)
    (setq exec-path (split-string path-from-shell path-separator))))

(set-exec-path-from-shell-PATH)

Taken from https://www.emacswiki.org/emacs/ExecPath.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.