8

This question has been asked at superuser is-there-a-way-to-reload-environment-variables-in-emacs, but no good solution was given.

I am using EmacsClient with often more than 30 buffers open, if I change an environment variable in the shell, I need to exit EmacsClient ( and reopen all the buffers) or I have to manually set the environment variable also in Emacs. I find it annoying that I cannot update the environment variables easily in Emacs. Any suggestions?

  • There is no straightforward way to do this, because changing an environment variable in the parent process will not update its value as exported to a child. – Erik Hetzner Jun 17 '15 at 18:33
7

exec-path-from-shell provides the exec-path-from-shell-copy-env command, which lets you copy the value of environment variables to Emacs sessions. For instance, M-x exec-path-from-shell-copy-env RET FOO sets the value of $FOO in Emacs as well.

Note that exec-path-from-shell-copy-env spawns a new shell to extract the value of the environment variable. Hence it will only work for variables that you set in your shell configuration files (e.g. .bashrc), but not for variables only set in a running shell session with export. Extracting these variables is generally impossible without convoluted hacks that inspect /proc/ or similar API for running processes.

  • Regarding the latter/transient values, if Emacs is running as a server then passing the updated values through to emacsclient directly from that shell would be easy enough. – phils Jan 6 '15 at 19:17
  • @phils Thanks, see my updated answer.. – Håkon Hægland Jan 6 '15 at 20:24
5

As a workaround, the following can be used (Linux, Bash):

  • First run printenv -0 > env.txt from the Bash terminal window,
  • Then from within Emacs, run
(defun my-update-env ()
  (interactive)
  (let ((str 
         (with-temp-buffer
           (insert-file-contents "env.txt")
           (buffer-string))) lst)
    (setq lst (split-string str "\000"))
    (while lst
      (setq cur (car lst))
      (when (string-match "^\\(.*?\\)=\\(.*\\)" cur)
        (setq var (match-string 1 cur))
        (setq value (match-string 2 cur))
        (setenv var value))
      (setq lst (cdr lst)))))

Update

I turns out that this can be done more elegantly using the --eval option of the emacsclient command: Define a Bash script update_emacs_env:

#! /bin/bash

fn=tempfile
printenv -0 > "$fn" 
emacsclient -s server_name -e '(my-update-env "'"$fn"'")' >/dev/null

where server_name is your Emacs server name, and my-update-env is a function defined by your ~/.emacs file:

(defun my-update-env (fn)
  (let ((str 
         (with-temp-buffer
           (insert-file-contents fn)
           (buffer-string))) lst)
    (setq lst (split-string str "\000"))
    (while lst
      (setq cur (car lst))
      (when (string-match "^\\(.*?\\)=\\(.*\\)" cur)
        (setq var (match-string 1 cur))
        (setq value (match-string 2 cur))
        (setenv var value))
      (setq lst (cdr lst)))))

Now you can simply type update_emacs_env from the shell command line to update the Emacs environment variables..

  • And you could run the "printenv" from inside the function too... – mankoff Jan 6 '15 at 18:33
  • @mankoff Actually, I think you could not.. :) (It would print the old values then) – Håkon Hægland Jan 6 '15 at 18:34
  • Can't you spawn a shell with login flag? Or source the .bashrc, .bash_profile, etc.? – mankoff Jan 6 '15 at 19:22
  • Yes.. but it would not help for the special case if I export in the shell directly from command line, using export VAR=value – Håkon Hægland Jan 6 '15 at 19:24
  • Yes I didn't think of that case. Elegant solution with the client! – mankoff Jan 7 '15 at 3:52
3

I used to use this:

function export-emacs {
    if [ "$(emacsclient -e t)" != 't' ]; then
        return 1
    fi

    for name in "${@}"; do
        value=$(eval echo \"\$${name}\")
        emacsclient -e "(setenv \"${name}\" \"${value}\")" >/dev/null
    done
}

Lets you export a named variable, E.G:

export EDITOR=vim
export-emacs EDITOR

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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