Score:0

systemd not able to run some bash scripts

gb flag

(Update with more info May 16, see end of post for journalctl messages)

I've created a systemd timer and service with the purpose of running a handful of bash scripts. In particular I'm aimed at mounting an external hdd at a given time, then mounting an veracrypt volume, in order to run some offsite backup actions.

Each of the scripts works correctly when run by my own admin user e.g.

sudo /path/to/script.sh

However, some scripts work and some scripts fail when the systemd service runs. Namely, the mount scripts fail, but the unmount script succeeds.

I'm pretty sure this is either a permissions issue, or a run-as-user issue... but I'm new to systemd, and I can't seem to trace it down. I'd rather avoid using systemctl --user mechanisms, since that relies on a special "linger" type that I'm not familar with... but if that's the only solution, I'll take it.

The high level view of the functions is this...

mountup.timer --> mountup.service --> mountup.sh --> mountusb.sh

A similar workflow is in place for the reverse operation

Here's the code...

/etc/systemd.system/mountup.timer

[Unit]
Description=run the mountup.service on a given schedule

[Timer]
Unit=mountup.service
OnCalendar=*-*-* *:00,30:00
#this means any day, month, year any hour... each 00 and 30 minute
Persistent=true

[Install]
WantedBy=timers.target

/etc/systemd/system/mountup.service

[Unit]
Description = Runs the mountup.sh script

[Service]
Type = simple
User = adminuseraccount
ExecStartPre = /bin/bash -c 'echo "systemctl says...mountup service triggered at $(date)"  >> /usr/local/bin/mountlog.txt'
ExecStart = /usr/local/bin/mountup.sh

/usr/local/bin/mountup.sh

#! /bin/bash

# the fancy function below pipes the echo messages through a function that preprends the timestamp, then sends the output to the logfile

logit() {
    while read
    do
        printf "%(%Y-%m-%d %T)T %s\n" -1 "$REPLY"  >> /usr/local/bin/mountlog.txt
    done
}


#the line below redirects standard output to logfile, along with standard error to the same, 
#after routing them through the fancy function above
exec 3>&1 1>> >(logit) 2>&1

echo "mountup.sh says ... starting mountusb.sh..." &&
/usr/local/bin/mountusb.sh && 
echo "mountup.sh says ... mountusb.sh has been run" &&

/usr/local/bin/mountusb.sh

#! /bin/bash
usbuuid=9743y934y943

mount --uuid $usbuuid  /mnt/targetlocation

Many thanks, I've been at this for about 2 weeks, off and on, and it's finally time to throw in the towel and learn what I'm doing wrong.

Edit: relevant output from sudo journalctl for the mountup.service attempt...

Starting Runs the mountup.sh script...
mountup.service: Control process exited, code=exited, status=1/FAILURE
mountup.service: Failed with result 'exit-code'.
Failed to start Runs the mountup.sh script.

relevant output from sudo journalctl for the mountdown.service attempt...

Starting Runs the mountdown.sh script...
Started Runs the mountdown.sh script.
root : PWD=/ ; USER=root ; COMMAND=/usr/bin/umount /mnt/targetlocation
pam_unix(sudo:session): session opened for user root(uid=0) by (uid=0)
pam_unix(sudo:session): session closed for user root
mountdown.service: Main process exited, code=exited, status=32/n/a
mountdown.service: Failed with result 'exit-code'.

From what I gather, exit code 32 on a umount command simply indicates a failure to unmount a volume, nothing more specific than that.

pt flag
"some scripts fail when the systemd service runs": fail in what way? What is logged in the journal when you `systemctl start` the service? What distribution are you running?
Ginnungagap avatar
gu flag
Any particular reason you're running a script to mount a volume instead of using a mount unit or `/etc/fstab`?
David avatar
gb flag
Essentially I was aiming to have the flexibility to edit script actions without messing around in system configuration files. The plan at the moment is to have a nightly timer mount the usb, then mount the volume, and then trigger backup actions. I wanted to be able to edit all of that in one file, rather than having several files in system locations. But, I'm not exactly against using a mount unit... I'm just not familiar with them (haven't really used systemd much yet). But I'd certainly consider alternative suggestions.
Score:1
ng flag

First, you should set a one-shot service, because your scripts exits when it's done:

[Unit]
Description = Runs the mountup.sh script

[Service]
Type = oneshot
User = adminuseraccount
ExecStart = /usr/local/bin/mountup.sh
RemainAfterExit=true
StandardOutput=journal
StandardError=journal

You can then see the output with journalctl -u mountup.service

With the log in the journal, I would also forgo all the redirection of file handles. Plus, your /usr/local/bin/mountlog.txt needs root access to write to. Generally, it's bad practice to write there. But again, I would not use the redirection at all.

And, because you chain commands with &&, you can think about doing set -e. This way, the script aborts on error. There are caveats to that (mis-contructed if-greps could abort your program for instance), but in your case it looks like a good option.

This is not the solution per se, because we don't see the error, but it should help you on your way.

Also, I think I would put it all in one script. Put an 'exit trap' in it to do sync; umount /foo/bar afterwards, so you're sure that when it's done, you have at least flushed file system buffers and the drive is unmounted. This makes it safe to unplug. The reason I tend to call sync in these situations as well, is in case the umount fails.

About umount failure: if that's your/a problem, you may be keeping the location open, if you cd into it, for instance.

David avatar
gb flag
Thanks for your comment, I've edited the question to include the journalctl messages that I could find. I'm definitely open to learning more about the logging features that could help specify the exact problem.
David avatar
gb flag
Any chance you could take a look at my updates and point me towards a way of identifying the error? I've posted journalctl output that seems relevant, but perhaps there is another command output that would be helpful? @Halfgaar
ng flag
@David you haven't tried my suggestions yet, of not using `&&` and not using the output redirection. It's possible that is eating your error messages. Also, I updated my answer with some stuff. Press the 'activity' button to see my edits.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.