I run a source build of emacs 28.0.50 and I have it installed in a non-standard location. This post will show you how to use
update-alternatives to be able to use
emacsclient effectively. I had problems because I had a mismatched emacs and emacsclient trying to work with each other. TL;DR make sure you have matching versions of emacs and emacsclient for health and happiness.
My set up, with ohmyzsh
~/.zshrc file I have this line:
That tells anything that wants to launch an editor what I’d prefer to see in front of me, from general work to git commit messages. If in doubt, use -that- editor. Simples. Anyway, being a Mint user for a while now and loving it more every day, I realised that the current setup on my old-ish machine wasn’t ideal; I have a lot of custom files in my
~/.bin folder to make life slicker and some of those files relate to Emacs, namely:
- enw –> run emacs in the terminal,
- enc –> run emacs in the terminal with both
--nwand no colour
Having an older machine, I decided I wanted to start using
emacsclient just to avoid having to wait a few seconds too many, I am a hardcore Emacs user of some 25 years now, you’d think I’d have done this already but no!
So, determined to get my PC feeling as slick as possible, I knew that the time had come not only to do battle with the Emacs client configuration but also the
update-alternatives script which is stock on most Debian based distros. The first time I ever tangled with it it felt hard but actually it’s not that bad, and very VERY useful for a cleaner command line experience. And what’s not to like about that ?
First steps: some poking at the box…
I first went back to the GNU site and read this page to get some memories back!
I then optimistically tried to go for it straight away:
╰─$ systemctl --user enable emacs Failed to enable unit: Unit file emacs.service does not exist.
Bummer…so, I went to the place where I have my custom source build, the folder
/opt/emacs, and had a look around to see what was given to me:
╰─$ find -name "*.service" ./lib/systemd/user/emacs.service ./share/emacs/28.0.50/etc/emacs.service
So many to choose from…one of them would be the correct one, so, using
diff to compare them:
╰─$ diff ./lib/systemd/user/emacs.service ./share/emacs/28.0.50/etc/emacs.service 0a1,4 > ## If your Emacs is installed in a non-standard location, you may need > ## to copy this file to a standard directory, e.g. ~/.config/systemd/user/ . > ## If you install this file by hand, change the "Exec" lines below > ## to use absolute file names for the executables. 7,8c11,12 < ExecStart=/opt/emacs/bin/emacs --fg-daemon < ExecStop=/opt/emacs/bin/emacsclient --eval "(kill-emacs)" --- > ExecStart=emacs --fg-daemon > ExecStop=emacsclient --eval "(kill-emacs)"
So all I had to do was copy the correct one to my local
systemd configuration folder for user services, what could be simpler ?
╰─$ cd ~/.config/systemd cd: no such file or directory: systemd
OK, so, nobody ever used it before… time to make one then with:
╰─$ cd mkdir -p ~/.config/systemd/user ╰─$ cp /opt/emacs/share/emacs/28.0.50/etc/emacs.service ./systemd/user/.
Spot the deliberate mistake, sadly, I didn’t. The next part is longer but it also was a great learning experience at the same time so I’ve written it up, warts and all, armed with the confidence of a fool who believes he’s done the right thing, I then tried this to enable the script:
╰─$ systemctl --user enable emacs Created symlink /home/sean/.config/systemd/user/ (cont) default.target.wants/emacs.service (cont) → /home/sean/.config/systemd/user/emacs.service.
Looks good, no errors, wow, almost done then. ….. :|
╰─$ emacsclient -c emacsclient: can't find socket; have you started the server? To start the server in Emacs, type "M-x server-start". emacsclient: No socket or alternate editor. Please use: --socket-name --server-file (or environment variable EMACS_SERVER_FILE) --alternate-editor (or environment variable ALTERNATE_EDITOR)
╰─$ systemctl start emacs Failed to start emacs.service: Unit emacs.service not found. ╭─sean@sean-MS-7891 ~/.config ‹node-› ‹› ╰─$ systemctl start --user emacs Failed to start emacs.service: Unit emacs.service is not loaded properly: (cont) Exec format error. See user logs and 'systemctl --user status emacs.service' for details. ╭─sean@sean-MS-7891 ~/.config ‹node-› ‹› ╰─$ systemctl --user status emacs.service ● emacs.service - Emacs text editor Loaded: error (Reason: Exec format error) Active: inactive (dead) Docs: info:emacs man:emacs(1) https://gnu.org/software/emacs/
It took me a while to realise… I had copied the wrong file from the diff output in my haste to get it all working, this meant I had to do this to correct it:
╰─$ cp /opt/emacs/lib/systemd/user/emacs.service ./systemd/user/.
Using this page now as reference: https://www.emacswiki.org/emacs/EmacsAsDaemon
╰─$ systemctl enable --user emacs ╰─$ systemctl start --user emacs
…but the command didn’t returned so assumed all was well….on a startup this would probably be spawned (think
&) and be fine…simple way to check is to see what’s now running in the background! But just as I was about to CTRL-C it, it came back with this sorry arsed message:
Job for emacs.service failed because a timeout was exceeded. See "systemctl --user status emacs.service" and "journalctl --user -xe" for details.
Argh!!! So, I went back to -the- Emacs site and found this page: https://www.emacswiki.org/emacs/EmacsAsDaemon which showed some differences between the script on my machine and the ideal setup, namely the
Type was not set to forking on my version, so I changed it to be this, it of course being
[Unit] Description=Emacs text editor Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/ [Service] Type=forking ExecStart=/usr/bin/emacs --daemon ExecStop=/usr/bin/emacsclient --eval "(kill-emacs)" Environment=SSH_AUTH_SOCK=%t/keyring/ssh Restart=on-failure [Install] WantedBy=default.target
Charged with hope, I saved this and then:
╰─$ systemctl start --user emacs Job for emacs.service failed because a timeout was exceeded. See "systemctl --user status emacs.service" and (cont) "journalctl --user -xe" for details.
And asking for some more information:
╰─$ systemctl --user status emacs.service 1 ↵ ● emacs.service - Emacs text editor Loaded: loaded (/home/sean/.config/systemd/user/emacs.service; enabled; vendo Active: active (running) since Sat 2020-08-01 06:59:28 BST; 2min 14s ago Docs: info:emacs man:emacs(1) https://gnu.org/software/emacs/ Process: 8991 ExecStart=/opt/emacs/bin/emacs --daemon (code=exited, status=0/S Main PID: 8992 (emacs) CGroup: /firstname.lastname@example.org/emacs.service └─8992 /opt/emacs/bin/emacs --daemon Aug 01 06:59:26 sean-MS-7891 systemd: Starting Emacs text editor... Aug 01 06:59:27 sean-MS-7891 emacs: Loading time... Aug 01 06:59:27 sean-MS-7891 emacs: Loading time...done Aug 01 06:59:27 sean-MS-7891 emacs: Loading paren... Aug 01 06:59:27 sean-MS-7891 emacs: Loading paren...done Aug 01 06:59:28 sean-MS-7891 emacs: Starting Emacs daemon. Aug 01 06:59:28 sean-MS-7891 systemd: Started Emacs text editor.
WAT? WAAAAT?It says it’s running!!! At this point I was close to almost getting a tad miffed but being a seasoned veteran, used to realising my own fallibility, I knew I’d still not got something right so I then decided to check what was being run when I type these things on faith:
╰─$ which emacsclient /usr/bin/emacsclient ╰─$ ll /usr/bin/emacsclient lrwxrwxrwx 1 root root 29 Mar 27 10:15 /usr/bin/emacsclient (cont) -> /etc/alternatives/emacsclient ╰─$ ll /etc/alternatives/emacsclient lrwxrwxrwx 1 root root 28 Mar 27 10:15 /etc/alternatives/emacsclient (cont) -> /usr/bin/emacsclient.emacs25 ╰─$ sudo update-alternatives --list emacsclient [sudo] password for sean: /usr/bin/emacsclient.emacs25 ╭─sean@sean-MS-7891 ~/.config/systemd/user ‹node-› ‹› ╰─$ sudo update-alternatives --list emacs /opt/emacs/bin/emacs /usr/bin/emacs25-x
SOLVED: mismatched versions, thanks to this Reddit thread which tipped me off as to what might be the source of this problem: version mismatch!
update-alternative to make it CLI friendly
There is a program called
update-alternatives which you may or may not be aware of. When you type the name of a program to run from the command line, it may not be running what you think! If you look in a folder called
/etc/alternatives/ you will find an enormous amount of symbolic links (sym-links) to actual real programs. What
update-alternatives does is manage those links so that you can use different versions of things from the command line without having to know where they are, this is great for version updates etc. I suggest some light reading on the matter at some point.
Anyway, realising that I had to make them versions the same, I did some viewing and then set about making things right with the world:
0 was a mistake, but I didn’t know what number to use at the time as the prioroty..read on!)
OK, looks good (mwah hah hah to come…), let’s finally go back to having it started as a system service when the machine boots up so I don’t have to wait so long:
Instant! success!! No errors no time-out errors etc…well, this is great I must say…I thought I’d see what emacs related processes were running now:
The first one is cool, second is our grep and the last one is ’cos I was already running a session of emacs, to maintain the history that became this article actually.
So finally, using emacsclient is now a done deal right?
emacsclient: can't find socket; have you started the server? To start the server in Emacs, type "M-x server-start". emacsclient: No socket or alternate editor. Please use: --socket-name --server-file (or environment variable EMACS_SERVER_FILE) --alternate-editor (or environment variable ALTERNATE_EDITOR)
Sensing that something was still not right with The Force I knew that the final check was to make sure that the alternative links were correctly set for both emacs and emacsclient so that they could play ball.
I know Kung-Fu
WTAF??? Beats head on desk and wonders what’s left to go wrong… time to take control of the legendary alternatives magic once and for all. I first checked on emacs and the emacsclient links:
╰─$ sudo update-alternatives --config emacsclient There are 2 choices for the alternative emacsclient (providing /usr/bin/emacsclient). Selection Path Priority Status ------------------------------------------------------------ * 0 /usr/bin/emacsclient.emacs25 28 auto mode 1 /opt/emacs/bin/emacsclient 0 manual mode 2 /usr/bin/emacsclient.emacs25 28 manual mode Press <enter> to keep the current choice[*], or type selection number: 1 ╰─$ sudo update-alternatives --config emacsclient There are 2 choices for the alternative emacsclient (providing /usr/bin/emacsclient). Selection Path Priority Status ------------------------------------------------------------ 0 /usr/bin/emacsclient.emacs25 28 auto mode * 1 /opt/emacs/bin/emacsclient 0 manual mode 2 /usr/bin/emacsclient.emacs25 28 manual mode Press <enter> to keep the current choice[*], or type selection number:
OK NOW it looks like it might work!! It did…I typed
emacsclient a file and it opened way quicker this time… on my older PC this makes me feel like I have a faster PC…now just to reboot and make sure it works as expected.
A few minutes later… still working! Now I can enjoy the impression that my PC is faster than it is by having Emacs loaded and ready to roll in the background. All you need is perseverance and a clear head, once the flower of anger has grown from a seed and blossomed there’s no hope for the day!