感谢这个帖子, 解决了我之前利用exec-path-from-shell 总是不能正确读取环境变量且拖慢emacs启动的问题。
感觉 exec-path-from-shell 的用 call-process 的同步写法会拖累启动速度似乎是必然的。启动一个异步的 process 会有什么用影响吗?
有什么环境变量是必须要同步的写入的吗?
如果异步不影响,那根本没必要启动时就加载这个
在 Emacs 29 刚出来时用了一会从源码编译出来的,用了如下代码来解決 macOS 上的 PATH 问题
(let ((paths
(eval-when-compile
(with-temp-buffer
(call-process-shell-command "cat /etc/paths /etc/paths.d/*" nil t)
(split-string (buffer-string))))))
(setenv "PATH" (mapconcat #'identity paths ":"))
(setq exec-path (append paths (list exec-directory))))
起作用的前提是用 macOS 特有的 /etc/paths.d
来管理 path 而不是用 shell profile,作用上等同于用 /usr/libexec/path_helper
。
这是把 paths 写在 /etc/paths.d 里面吗👀
private/etc/paths.d $ ls
10-pkgsrc 40-XQuartz TeX
private/etc/paths.d $ cat *
/opt/pkg/sbin
/opt/pkg/bin
/opt/X11/bin
/Library/TeX/texbin
private/etc/paths.d $ cat ../paths
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin
写死PATH肯定能加快启动。mac上还有一种办法,emacs-plus 编译的时候现在会自动嵌入当前环境变量,理论上都不需要 exec-path-from-shell
。不过对于经常变化的场景下就比较麻烦了,所以我选择用 zinit,速度和功能都令人满意。
请教一下,这么配置:
;; Environment: the same path as in your shell, bash or zsh
(when (or sys/macp sys/linuxp (daemonp))
(use-package exec-path-from-shell
;; :demand t
:config (setq exec-path-from-shell-check-startup-files nil)
:hook (after-init . exec-path-from-shell-initialize)))
有效吧?
不行,必须立即初始化,否则有些包可能不正常。而且只需在GUI和daemon下启用。
;; Environment: the same path as in your shell, bash or zsh
(when (or sys/mac-x-p sys/linux-x-p (daemonp))
(use-package exec-path-from-shell
:init (exec-path-from-shell-initialize)))
谢谢,大佬
先更新了下配置,有空再仔细看下怎么优化 ~
优化很简单,一个是 (setq exec-path-from-shell-arguments '("-l"))
,或者用 zinit之类的管理zsh/bash
环境变量相关的配置放到 .zshenv (for zsh) or .profile(for bash) 中, 就可以了是吧?
加入这行配置:
(setq exec-path-from-shell-arguments '("-l"))
启动减少到 1 秒左右:
不加:
exec-path-from-shell
在几年前(具体记不得了)用时,就发现很慢,现在没在看过它的实现了。
为了快,2个方面可以改进会有较大的提升:
- 将需要copy的环境变量在Emacs退出时保存在文件中,下次加载该文件,读出环境变量;这个过程会很稳定,而且快。
-
setenv
仅是维护Emacs内置变量process-environment
, 也就是说Emacs对环境的更改都是通过维护process-environment
的;这是一个interactive
函数,考虑了很多场景,也就是说会慢, 可以写1个最简单的可以快很多; -
getenv
同样也是慢的,情况简单的考虑用getenv-internal
会快;
具体可以看 https://github.com/junjiemars/.emacs.d/blob/cc/config/shells.el
是的,这样会快很多。坏处就是动态的环境变量都无法读取,只能读取固定文件的配置。
动态的环境变量是指什么呢?
- 启动Emacs前,更改环境变量,Emacs启动后加载上次的环境变量,这时出现不一致,在Emacs重启后再次与环境一致。
- 启动Emacs后变动,更改环境变量,任何程序也无法获知变动的环境变量,这是系统决定的,也是Emacs 使用
process-environment
的理由;但是在Emacs重启后再次与环境一致。
我说的动态是指shell启动时动态确定的变量,比如要通过语句判断的(跨平台中用得很多)。这样更灵活,如果配置比较稳定就不需要。
其实现在应该根本不用这个插件,在 mac 上 emacs plus 会自动 inject path,在 linux 上好像 path 就是正常的
不用 emacs-plus 还是需要用它的
Linux下不行,除非PATH环境变量是固定的。
要我说直接写死 path 在配置里得了搞这么多麻烦的,反正 mac 都是个人用,也不是在服务器上要天天换来换去需要全自动化部署的。我的 emacs 启动速度 0.5s,linux 上 0.2s,从来都是把它当 vim 一样随开随关的。