This is an Emacs mode to give you a UI for managing init system daemons (services). I wrote this after getting tired of typing out sudo service my_thing reload
all the time. It’s also nice to have a consistent UI over different init systems.
N.B. This package was briefly known as services-mode
.
There is support for the following init systems and service managers:
- systemd (RHEL7, Fedora, openSUSE, Debian, Ubuntu, Arch, etc.)
- SysVinit (RHEL6)
- brew services (macOS)
- GNU Shepherd (GuixSD)
- OpenRC (Gentoo)
It’s designed to be easily extensible (see below) so if your system isn’t supported please consider contributing.
Managing daemons on local and remote systems is supported.
You can open the daemons list with M-x daemons
. If started from a TRAMP buffer then the daemons for that remote system will be listed and manageable, otherwise it will be all the daemons on your local system.
Navigate the list with n
and p
. Refresh the list with g
(it’s just a tabulated-list-mode
buffer). You can sort the buffer with tabulated-list-sort
or by clicking a header.
The following commands are available for each daemon:
Command | Key in *daemons* buffer |
---|---|
daemons-status | RET |
daemons-start | s |
daemons-stop | S |
daemons-reload | r |
daemons-restart | R |
daemons-enable | e |
daemons-disable | d |
Sorry I’ve only implemented =enable= and =disable= for systemd so far - raise an issue if you want support for your system!
Results of commands are displayed in a special-mode
buffer, in which the same commands are available for the selected daemon. So you can (for example) keep reloading the same daemon with r
without having to re-select it.
You can dismiss either buffer with q
.
Of course you can also call the commands interactively, e.g. M-x daemons-start
and enter the daemon’s name at the prompt. The prompt has completion, so (for example) you can type do
to narrow it down to docker
, or sys
to narrow it down to any of the 193 systemd
services.
It looks something like this for systemd:
and something like this for SysVinit:
You can install this from MELPA with M-x package-install daemons
. See here for how to get started with MELPA.
If for some reason you are unable or prefer not to use MELPA, you can also do this:
- Download the latest release distribution and extract.
- Install with
M-x package-install-file
- at the prompt, pass the path to the extracted directory, e.g.~/Downloads/daemons.el-VERSION/
.
Please see M-x customize-mode
.
For eldoc
support (currently systemd
only), you can use (add-hook 'daemons-mode-hook eldoc-mode)
.
Note that the MELPA Stable release is updated very conservatively, so if you have any problem that can’t be solved by the below advice, please try reverting the stable version, e.g.:
(use-package daemons :pin melpa-stable)
Of course also feel free to raise an issue or submit a PR. :-)
If you are having trouble with permissions for SysV or GNU Shepherd then setting the daemons-always-sudo
custom variable may be what you need.
Alternatively you can navigate to a TRAMP path as a sudoer such as by doing M-x cd /sudo::
and then call M-x daemons
. This method also works for remote systems e.g. visit /ssh:me@remotehost|sudo:remotehost:
then run M-x daemons
. The buffer name will show what user and host you are on.
Please drink use sudo responsibly.
Have a look at M-x customize-group password
for this. You could also use the sudo tricks above.
This package requires Emacs 25.1 or higher. Users are successfully using it with Emacs 26 and 27, but things may yet get broken by ongoing development. If you spot such a thing please raise an issue.
To extend daemons
to support another init system, there are two steps:
- Add your extension name (e.g.
daemons-example
) to thedaemons-init-system-submodules
custom variable. - Write a package that defines the extension using the
daemons-define-submodule
macro:
(daemons-define-submodule daemons-example "Daemons submodule for Example system, where 'ex-sys' is the daemons manager (like 'systemctl' or 'service')." ;; This is an expression to evaluate that will return true if this submodule works on this system: :test (and (eq system-type 'gnu/linux) (equal 0 (daemons--shell-command "which ex-sys"))) ;; This is a map of user commands (see `daemons--commands-alist'): :commands '((status . (lambda (name) (format "ex-sys status %s" name))) (start . (lambda (name) (format "ex-sys start %s" name))) (stop . (lambda (name) (format "ex-sys stop %s" name))) (reload . (lambda (name) (format "ex-sys reload %s" name))) (restart . (lambda (name) (format "ex-sys restart %s" name))) (enable . (lambda (name) (format "ex-sys enable %s" name))) (disable . (lambda (name) (format "ex-sys disable %s" name)))) ;; This is expression to get the daemons list (see `daemons--list'): :list (daemons-example--list) ;; This is an expression to get the list headers (see `daemons--list-headers'): :headers (daemons-example--list-headers))
Have a look at any of the existing submodules for inspiration. The submodule for GNU Shepherd is a short and sweet example - there’s a definition at the top, a couple of helper functions for parsing command output and that’s it.