49

I have the following systemd unit file in /etc/systemd/system/emacs.service:

[Unit]
Description=Emacs: the extensible, self-documenting text editor
Documentatin=man:emacs(1) info:Emacs


[Service]
Type=forking
ExecStart=/usr/bin/emacs --daemon
ExecStop=/usr/bin/emacsclient --eval "(progn (setq kill-emacs-hook nil) (kill-emacs))"
Restart=always
Environment=DISPLAY=:%i
TimeoutStartSec=0

[Install]
WantedBy=default.target

I want this to start on boot, so I have entered systemctl enable emacs

However, each time my service reboots, systemctl status emacs shows:

● emacs.service - Emacs: the extensible, self-documenting text editor
   Loaded: loaded (/etc/systemd/system/emacs.service; disabled; vendor preset: enabled)
   Active: inactive (dead)

But then entering systemctl start emacs and checking the status returns:

● emacs.service - Emacs: the extensible, self-documenting text editor
   Loaded: loaded (/etc/systemd/system/emacs.service; disabled; vendor preset: enabled)
   Active: active (running) since Fri 2016-11-11 23:03:59 UTC; 4s ago
  Process: 3151 ExecStart=/usr/bin/emacs --daemon (code=exited, status=0/SUCCESS)
 Main PID: 3154 (emacs)
    Tasks: 2
   Memory: 7.6M
      CPU: 53ms
   CGroup: /system.slice/emacs.service
           └─3154 /usr/bin/emacs --daemon

How can I get this process to successfully start on boot?

Startec
  • 1,879

5 Answers5

29

I have no idea why but to get this to work I:

deleted Environment=DISPLAY=:%i

added a User= variable

Made sure the correct file was in /etc/systemd/system/emacs.service (earlier it had been a hard link)

and re-ran systemctl enable emacs

This made it work.

EDIT The real problem here is that I had a typo at line 3: Documentatin

I found this by checking journalctl. I suggest anyone who has issues with a systemd script do the same as there was no error sent to stderr.

Startec
  • 1,879
  • Does that also work on a reboot? I guess if the daemon mode does not require an X11 connection, then there is no need for the After=... I mentioned. – Alexis Wilke Nov 12 '16 at 01:20
  • 1
    Yes it works after reboot. This is not a graphical Emacs so no X11 is needed. That was just a line I copied from an example and didn't pay attention. – Startec Nov 12 '16 at 01:39
  • +1 for the real problem being a typo. My WantedBy was wrong (mult-user != multi-user) – Tarek Fadel May 21 '20 at 18:02
  • 3
    +1 on the journalctl comment. This is going to be your most powerful debugging tool moving forward. Helped me find the issue with my system, which was totally different. Although, journalctl will give you a lot of log vomit, so pass the -f flag for journalctl -f – Jeremy Jun 11 '20 at 17:16
  • 1
    I found systemctl list-dependencies to also be useful for diagnosing "won't start at boot" issues. The system I was working on wasn't actually starting network.target, so my script wasn't running because its "parent" wasn't part of the boot. – Compholio Oct 05 '21 at 20:32
4

You have a DISPLAY environment variable, that means you want X11 to be started. So you need to have a way to block your service until then.

This is done using the After=... option.

I haven't done it myself, so I cannot say that it would work, but it is likely something to do with graphical.target.

[Unit]
After=graphical.target

Another possibility, if the X server does not start immediately (i.e. you have a login screen with lightdm or such), then you may have to use WantedBy=... instead:

[Unit]
WantedBy=graphical.target

If you get tired of getting it to work with systemd, you may want to look into the usual way X-Windows managers make it work.

There is the ~/.xprofile file, which works like the ~/.bashrc file.

There is also the ~/.config/autostart/*.desktop files. It will automatically start all the applications defined in there.

These solutions are not system wide, though, in case you have multiple users, each one would have to have their own entry. Also, it does not start the application as root, but you, instead.


As a side note, the "loaded + inactive (dead)" message means that systemd had a hard time to start the process and as a result decided to abandon it. You can manually test that the name.service works once you rebooted using:

systemctl stop <service-name>
systemctl start <service-name>

This will refresh the status and start the service properly, assuming the info is correct. You can then check the status again to see additional details:

systemctl status <service-name>
Alexis Wilke
  • 2,857
  • 2
    Hm, I deleted that entire line and nothing changed. Also, (as I said in my question) it starts fine by running systemctl start emacs). – Startec Nov 11 '16 at 23:25
  • see my updated question. I had a typo in Documentatin . Your hint about journalctl helped me here. – Startec Dec 02 '16 at 06:33
3

Check where is your link after you enabled the service. Just to add what I had with this. When I execuded sudo systemctl enable myserevice.service it created the link in the folder multi-user.target.wants but not in the real multi-user.target.wants. It created in some new folder with the same name. I have had some extra character in line WantedBy=multi-user.target that my text editor didn't show. So, I don't know what it was. I just c/p from another .service file and after that I enabled again and now the link is in the correct folder

2

ooh this is interesting.

Picking a random service unit and staring at it, it depends on a specific target instead of default.target. The latter is symbolic... a configured link to a specific target, semantically it doesn't make sense. (See systemctl set-default)

That might explain why your service shows as disabled after you enable it. Try replacing default.target in your service file with multi-user.target, for example.

(Not reporting an error when failing to enable seems like a defect in systemd. I almost wonder if you now have a directory /etc/systemd/system/default.target.wants).

sourcejedi
  • 50,249
  • The journalctl command tells you what broke (why the enable failed, for example.) As for the link, it is not required if you create your own personal service. It does matter if you create a package that you want others to install/remove, etc. – Alexis Wilke Nov 12 '16 at 01:22
  • @AlexisWilke That would be even worse! Why would it be written to report some errors to stderr and others to the journal? – sourcejedi Nov 12 '16 at 09:26
  • It writes everything to the journal. From what I've seen, you only see a very basic, systemd specific, error if it could not start the daemon. – Alexis Wilke Nov 12 '16 at 20:46
  • 3
    user did not report even a basic error, they believed the operation had succeeded and therefore proceeded to reboot. at face value, there is a defect in systemd. Users also have failure modes, but it didn't sound to me like overlooking an error message completely was a very likely one in this question. – sourcejedi Nov 12 '16 at 21:45
  • 1
    @sourcejedi I have no idea how you knew this but yes, I now have a listing at /etc/systemd/system/default.target.wants Inside that is my service files. And yes, I had no idea there was any error. – Startec Dec 02 '16 at 06:24
2

It's a bug in several service files of Debian:

# systemctl enable watchdog
Synchronizing state of watchdog.service with SysV init with /lib/systemd/systemd-sysv-install...
Executing /lib/systemd/systemd-sysv-install enable watchdog
# find /etc/systemd/ | grep watch
# tail -n2 /lib/systemd/system/watchdog.service

[Install]

https://www.raspberrypi.org/forums/viewtopic.php?f=82&t=218609&p=1406567#p1406567 https://forum.armbian.com/topic/9115-still-dont-know-where-to-report-bugs-watchdogservice-refuses-to-start-due-to-broken-service-file/

The distribution level fix is to

echo "WantedBy=default.target" >> /lib/systemd/system/watchdog.service
systemctl daemon-reexec
systemctl enable watchdog
systemctl stop watchdog.service
systemctl start watchdog.service

There are many manual alternatives to this.