通过-daemon参数让Emacs在后台运行使之避免随X崩溃而退出
我的X server有时会停止响应,这时我不得不将之杀掉再重启. 也许是我的配置有问题,每次X server启动时,一开始分辨率总是很低(since it starts off in low-graphics mode ). 直到我手工重启图形登录管理器之后(我用的是sddm)才恢复正常. 总之,由于很难调试和修复这个问题, 我决定将注意力放在重启X时真正对我造成困扰的事情上:即,X退出时,Emacs也会跟着退出. M-x recover-session
能够很好的恢复我修改过的文件,而且一般来说我也会记得一打开Emacs就调用该命令来恢复上次的修改,但有时我会忘了这样做,则结果是我丢失了之前做出的那些更改.
考虑到我调用了 (server-start)
以便允许不同的Emacs客户端连接到同一进程. 因此每次我需要重启X时,我都会先切换到控制台,使用 emacsclient -c
连接上Emacs, 然后使用 M-x save-buffers-kill-emacs
来关闭Emacs. 但是我依然需要在重启X后重启Emacs.
使用 emacs --daemon
可以将Emacs作为后台进程运行,然后使用 emacsclient -c
连接上它. 然而,当我这么操作时,emacsclient frame并未应用我设置的主题. 需要为 after-make-frame-functions
变量添加下面函数才能修复这个问题:
(defun my/setup-color-theme () (interactive) (color-theme-solarized-dark) (set-face-foreground 'secondary-selection "darkblue") (set-face-background 'secondary-selection "lightblue") (set-face-background 'font-lock-doc-face "black") (set-face-foreground 'font-lock-doc-face "wheat") (set-face-background 'font-lock-string-face "black") (set-face-foreground 'org-todo "green") (set-face-background 'org-todo "black")) (add-hook 'after-make-frame-functions (lambda (frame) (select-frame frame) (my/setup-color-theme)))
我对 emacs --daemon
和 emacsclient -c
这种方式很满意,因此我决定更进一步,让它在我开启电脑时就自动运行. 我试过使用 https://www.emacswiki.org/emacs/EmacsAsDaemon 中的init脚本. 但是由于我的Linux版本使用的是systemd,因此启动该init脚本会导致一个"缺少service文件"的错误信息. 所以我删除了这个init脚本然后创建了自己的脚本作为代替 ~/.config/systemd/user/emacs.service
:
[Unit] Description=Emacs: the extensible, self-documenting text editor [Service] Type=forking ExecStart=/usr/local/bin/emacs --daemon ExecStop=/usr/local/bin/emacsclient --eval "(progn (setq kill-emacs-hook 'nil) (kill-emacs))" Restart=always TimeoutStartSec=0 [Install] WantedBy=default.target
接着我用自己的一般用户账号来运行下面这些命令:
systemctl --user enable emacs systemctl --user start emacs
再然后,我将 ~/.xsession
中的 emacs
修改为 emacsclient -c
, 这样新产生的X session会连接上已有的session而不是重新创建一个新session. 这样一来,每次我重启电脑时,Emacs都会以我用户的权限启动,当我启动X时,都会有一个emacsclient连接上这个Emacs.
然而,我发现,重启X依然会倒使Emacs daemon崩溃掉. 这个bug在 emacs --daemon
中有相关警告,它可能跟GTK有关. 我使用 ./configure --with-x-toolkit=lucid; make; make install
重新编译Emacs后,似乎就没什么问题了; 我可以随意重启X而不会影响Emacs了. 而且这样还带来一个好处: 由于Emacs是在我启动计算机时进行的初始化,而我所需要作的仅仅是连接上那个进程而已,因此当我登录用户后,给人的感觉Emacs启动真的很快.
最后一点: 我注意到TRAMP无法找到我的SSH keyring,因此当我用Org Babel运行远程服务器上的代码(就像下面这段代码一样)时,TRAMP会卡住等待我输入passphrass:
#+begin_src sh :dir [email protected]:~ perl library-new.pl Business #+end_src
由于我的SSH socket看起来就像 /tmp/ssh-BLAHBLAHBLAH/agent.PROCESSID
一样, EmacsWiki中所描述的SSH_AUTH_SOCK设置方法(Environment=SSH_AUTH_SOCK=%t/keyring/ssh)不适用于我. 好在 https://github.com/nhoffman/.emacs.d/blob/master/init.org 中的脚本适用于我.
(defun my/ssh-refresh () "Reset the environment variable SSH_AUTH_SOCK" (interactive) (let (ssh-auth-sock-old (getenv "SSH_AUTH_SOCK")) (setenv "SSH_AUTH_SOCK" (car (split-string (shell-command-to-string "ls -t $(find /tmp/ssh-* -user $USER -name 'agent.*' 2> /dev/null)")))) (message (format "SSH_AUTH_SOCK %s --> %s" ssh-auth-sock-old (getenv "SSH_AUTH_SOCK"))))) (my/ssh-refresh)
另外, emacs --daemon
并不会使用我在KDE中配置的默认浏览器. 当我打开Org mode中的URL链接时会打开一个新的Chromium进程,而不是使用Google Chrome浏览器. 我通过将 browse-url-browser-function
的值从 browse-url-default-browser
改为 browse-url-generic
从而解决这个问题:
(setq browse-url-generic-program "google-chrome") (setq browse-url-browser-function 'browse-url-generic)
让我们来看看这样设置后的效果如何吧!