Friday, 14 December 2018

Why has emacs stopped running in a window?

I use several editors (and also Eclipse, which has its own) and manage to be reasonably productive with all of them, but all other things being equal emacs is my favourite.I have it installed as an icon on the Linux Mint start bar.

Imagine my annoyance and distress when yesterday clicking on the emacs icon did nothing; no error message, no window display, just a momentary blink and then nothing.  emacs would run in a terminal window, but not in its own emacs window on the desktop.  Reinstalling the "emacs" package didn't help.

I traced the problem to a mistake I made yesterday.  I have a list of packages to install on a remote Ubuntu server, which has no X windows installed and which runs headless.  In error I typed the "apt install" command into a window which was not ssh-ed into the local machine, thus installing all those packages on my local laptop (the one where emacs was failing to run).  I do my development and testing locally so in fact installing those packages was a no-op, with one important exception: I use emacs on the Ubuntu Server system, but to avoid problems install only the terminal-only version, called emacs-nox.  So of course I had installed emacs-nox on my laptop, which had faithfully done what was required of it: stop emacs running in an X Window.  I purged it, reinstalled emacs and all was well. 

Saturday, 6 January 2018

A run-once system for linux

Current development of the Linux image for the community centre I'm involved with requires me to be able to carry out tasks just once (a "run once" capability). Moreover, I have need to run such tasks at three different stages in the overall process:
  1. At start up before the network is active (to manipulate network definitions)
  2. At start up after the network is active but before users log in (in my case to incorporate the IP address into a workspace wallpaper)
  3. At shut down, after the users are logged off but while the filesystems are still mounted.

The run-once script

I have a run-once script /usr/local/bin/runonce, based on one I found here.
RUNONCE_DIR=$1
[ -z $RUNONCE_DIR ] && RUNONCE_DIR=/etc/local/runonce.d

[ ! -d $RUNONCE_DIR/ran ] && mkdir -p $RUNONCE_DIR/ran

for FILE in $RUNONCE_DIR/*; do
    [ -d "$FILE" ] && continue
    COMMAND_NAME=$(basename $FILE)
    logger -it runonce -p local3.info "Running: $FILE"
    "$FILE"
    mv "$FILE" "$RUNONCE_DIR/ran/$COMMAND_NAME-$$-$(date +%Y%m%d-%H%M%S)"
    logger -it runonce -p local3.info "Ran: $FILE"
done


I use it in all three places, with three directories /etc/local/runonce-a.d, /etc/local/runonce-b.d and so on.  The parameter to the runonce job specifies which one to use.

The three jobs are then controlled by systemd unit files (I'm just getting used to systemd ..), as follows:

runonce-a.service

# Run-once service; runs any executable in /etc/local/runonce-a.d
# Ensuring that it runs before the network is active
[Unit]
Description=Run once programs (pre network)

Before=network-pre.target
Wants=network-pre.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/runonce /etc/local/runonce-a.d

[Install]
WantedBy=network.target

runonce-b.service

# Run-once service; runs any executable in /etc/local/runonce-b.d
# Ensuring that it runs after the network is active
[Unit]
Description=Run once programs (post-network)

After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/runonce /etc/local/runonce-b.d

[Install]
WantedBy=multi-user.target

runonce-c.service

# Run-once service; runs any executable in /etc/local/runonce-c.d
# before the system is shut down or rebooted.
[Unit]
Description=Run once programs (before shutdown)
RequiresMountsFor=/home

[Service]
Type=oneshot
ExecStop=/usr/local/bin/runonce /etc/local/runonce-c.d
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target


It took quite a while to assemble the various bits of this from around the web; hope it helps someone else.