Using systemctl edit via bash script?

You can override the $SYSTEMD_EDITOR environment variable to use a different command other than your editor when running systemctl edit.

For instance, using something like SYSTEMD_EDITOR='cp /path/to/source.file' seems to work OK (even though it's pretty ugly, expecting the last argument to be appended there by systemd!)

For your particular case, you could use:

$ { echo "[Service]"; 
    echo "ExecStartPre=/bin/sleep 5";
  } >~/tmp/sddm-override.conf
$ sudo env SYSTEMD_EDITOR="cp $HOME/tmp/sddm-override.conf" systemctl edit sddm

But all that systemctl edit really does is create an override file (in its case, named override.conf) under the /etc/systemd/system/<service>.service.d/ directory, which is created if it does not exist... So doing that directly is also a totally accepted approach. (See mentions of "drop-in" and "override" in the man page for systemd.unit for more details.)

So, in your case, this would be an appropriate solution:

$ sudo mkdir -p /etc/systemd/system/sddm.service.d/
$ { echo "[Service]"; 
    echo "ExecStartPre=/bin/sleep 5";
  } | sudo tee /etc/systemd/system/sddm.service.d/10-startup-delay.conf
$ sudo systemctl daemon-reload

Which drops a file with the expected contents in the "drop-in" directory for your unit, in which case you can also name it appropriately after what it tries to accomplish.

UPDATED: As @GracefulRestart points out, you need a systemctl daemon-reload after adding a drop-in directly.


Since I have not found how to use systemctl edit in a script yet, best practice would be to simulate the systemctl edit sddm command and place the override in the /etc/systemd/system directory, as service units in /usr/lib/systemd/system could be changed when packages are upgraded:

UNIT='sddm.service'
DIR="/etc/systemd/system/${UNIT}.d"
mkdir $DIR
echo -e "[Service]\nExecStartPre=/bin/sleep 5" > ${DIR}/override.conf
systemctl daemon-reload

That should be roughly equivalent to what systemctl edit sddm is doing.


You can change what editor systemctl(8) uses for its edit subcommand with the SYSTEMD_EDITOR variable. This essentially constructs a command whose final argument is always a systemctl(8) created temporary file that, once written to, is then moved to override.conf.

Because of this, we can use tee(1) as the SYSTEMD_EDITOR and then redirect any text we want from the shell to the entire systemctl(8) command on stdin. For example, redirecting a Here-Document:

SYSTEMD_EDITOR=tee systemctl edit sddm <<EOF
[Service]
ExecStartPre=/bin/sleep 5
EOF

This creates the drop-in file /etc/systemd/system/ssdm.service.d/override.conf with the contents between the "words" EOF.

Under-the-hood the edit subcommand looks something like this:

# Create drop-in directory for service
mkdir -p /etc/systemd/system/ssdm.service.d

# Create empty temporary file
touch /etc/systemd/system/ssdm.service.d/.

# Pass temporary file as last argument of SYSTEMD_EDITOR
tee /etc/systemd/system/sddm.service.d/.\#override.conf846580011dbe64db/.\#override.conf846580011dbe64db<<EOF
[Service]
ExecStartPre=/bin/sleep 5
EOF

# Rename temporary file
mv /etc/systemd/system/sddm.service.d/{.\#override.conf846580011dbe64db,override.conf}

After the unit has been edited, the systemd configuration is reloaded automatically (in a way that is equivalent to daemon-reload).