How can I delete the contents of a directory with systemd service file? - systemd

I have a systemd service that stores files in a directory. I need to ensure that the directory is empty each time the service starts. I thought that adding ExecStartPre=+/bin/rm path/to/the/directory/* to the .service file would get the job done but after restarting the service, the files in the directory remain. Does anyone know how I can accomplish emptying the directory at service startup?

I used - instead of + and used the full path (more on official docs). I added -f to rm in case you have both files and folders.
[Service]
ExecStartPre=-/usr/bin/rm -f /path/to/the/directory/*
I tested with the following file (/etc/systemd/system/mydaemon.service):
[Unit]
Description=MyDaemon Simple Service
After=network.target
[Service]
Type=simple
ExecStartPre=-/usr/bin/rm /tmp/mydaemon
ExecStart=/usr/bin/ls /tmp
Restart=on-abort
[Install]
WantedBy=multi-user.target
And tested my service file with:
# systemctl start mydaemon
# systemctl status mydaemon
# systemctl restart mydaemon
Tested your particular scenario with:
# touch /tmp/mydaemon
# ls -al /tmp/mydaemon
-rw-r--r--. 1 root root 0 Sep 28 12:38 /tmp/mydaemon
# systemctl restart mydaemon
# ls -al /tmp/mydaemon
ls: cannot access /tmp/mydaemon: No such file or directory

Related

Auto Start Script

So I am making a script that can run these commands whenever a server boot/reboot:
sudo bash
su - erp
cd frappe-bench/
bench start >/tmp/bench_log &
I found guides here and there about how can I change user in script I came out with the following script:
#! /bin/sh
sudo -u erp bash
cd /home/erp/frappe-bench/
bench start >/tmp/bench_log &
And, I have created a service at /etc/systemd/system/ and set it to run automatically when the server boots up.
The problem is, whenever I run sudo systemctl start erpnextd.service and checked the status, it came up with this
May 24 17:10:05 appbsystem2 systemd[1]: Started ERPNext | Auto Restart.
May 24 17:10:05 appbsystem2 sudo[18814]: root : TTY=unknown ; PWD=/ ; USER=>erp ; COMMAND=/bin/bash
May 24 17:10:05 appbsystem2 systemd[1]: erpnextd.service: Succeeded.
But it still doesn't start up ERPNext.
All I wanted to do is make a script that will start erpnext automatically everytime a server reboot.
Note: I only install frappe-bench on user erp only
Because you are using systemd, you already have all the features from your script available, and better. So you don't even need the script anymore:
[Unit]
Description=...
[Service]
# Run as user erp.
User=erp
# You probably also want to run as group erp, if it exists.
Group=erp
# Change to this directory before executing.
WorkingDirectory=/home/erp/frappe-bench
# Redirect standard output to the given log file.
StandardOutput=file:/tmp/bench_log
# Redirect standard error to the same log file.
StandardError=file:/tmp/bench_log
# Command line for starting the program. Make sure to use an absolute path!
ExecStart=/full/path/to/bench start
[Install]
WantedBy=multi-user.target
Using crontab (the script will start after every reboot/startup)
#crontab -e
#reboot sh /full/path/to/bench start >/tmp/bench_log
The answer provide by Thomas is very helpful.
However, I found another workaround by adding the path of my script file into the bottom of /etc/rc.local file.
Both method works, just a matter of preference ;)

RaspberryPi - error when trying to reference a user directory on boot service?

I am trying to reference a user directory on boot for my raspberry pi 4 32 bit bullseye desktop with a service setup on systemctl. This service maps my ip address to an .env file. The process is as follows:
setup.service attempts to create a .env file using setup.sh with my current ip address
setup.timer fires off the service 1 minute after boot
This works flawlessly when my setup.sh looks like this:
...
destdir=/home/me/my_directory/.env
echo "REACT_APP_MACHINE_HOST_IP=$REACT_APP_MACHINE_HOST_IP" > "$destdir"
But when I try to replace the value of "me" with the machine user in order to make this more transferrable I get this error on boot:
...
destdir=/home/"$USER"/my_directory/.env
echo "REACT_APP_MACHINE_HOST_IP=$REACT_APP_MACHINE_HOST_IP" > "$destdir"
/home//my_directory/.env does not exist...
Not sure where I'm off because I made a quick test.sh script and the following echoed the directory correctly:
#!/bin/bash
mydir=/home/"$USER"/my_directory/
echo $mydir
It seems like no user is recognized. I am assuming this has something to do with system running on root? Or is my syntax off?
EDIT:
My setup.service below:
[Unit]
Description=setup mcw
After=multi-user.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/setup.sh
[Install]
WantedBy=multi-user.target
And what I run to automate aka automate.sh:
# copy ip file to task and authorize
sudo cp /home/${USER}/my_directory/setup.sh /usr/local/bin/setup.sh
sudo chmod 744 /usr/local/bin/setup.sh
# create setup files
sudo cp /home/${USER}/my_directory/setup.service /etc/systemd/system/setup.service
sudo cp /home/${USER}/my_directory/setup.timer /etc/systemd/system/setup.timer
# add permissions for the service
sudo chmod 644 /etc/systemd/system/setup.service
# setup and reload systemctl
sudo systemctl daemon-reload
sudo systemctl enable setup.timer
sudo systemctl start setup.timer

setsockopt for systemd unit - error: "Operation not permited"

I'm trying to run BindToInterface in a script as part of a systemd service that runs under its own separate user.
The service file looks like this:
[Unit]
Description=Deluge Bittorrent Client Daemon
Documentation=man:deluged
After=network-online.target mnt-storage.mount
Requires=mnt-storage.mount
BindsTo=mnt-storage.mount
[Service]
Type=simple
UMask=000
ExecStart=/bin/bash /media/bti/deluged.sh
Restart=on-failure
# Time to wait before forcefully stopped.
TimeoutStopSec=300
[Install]
WantedBy=multi-user.target
The script is as follows:
#!/bin/bash
BIND_INTERFACE=eno2 DNS_OVERRIDE_IP=8.8.8.8 BIND_EXCLUDE=127.0.0.1,192.168. LD_PRELOAD=/media/bti/bindToInterface.so /usr/bin/deluged -d -l /var/log/deluge/daemon.log -L warning
when executing:
systemctl status deluged
I get the following output:
bash[503711]: setsockopt: Operation not permitted
Is there a way to run your tool without elevated privileges? How would "setsockopt" be run for a systemd unit without elevated privileges
Thanks
Linux as a strict limitation: Only root can open ports below 1024. If your daemon is doing this, you can only do it by root.

Run Bash script as root in startup on ubuntu 18.04

I wanted to run a bash script as root in startup. First I started using RC.Local and Crontab but nothing works.
Create the service file as in the template below and add the file in the location /etc/systemd/system/
And the Template as
[Unit]
Description = ~Name of the service~
[Service]
WorkingDirectory= ~directory of working file~
ExecStart= ~directory~/filename.sh
[Install]
WantedBy=multi-user.target
Start the service file by the name using
systemctl start servicefile.service
To enable on startup
systemctl enable servicefile.service
To check the status
systemctl status servicefile.service
To stop
systemctl stop servicefile.service
Create a systemd unit file in /etc/systemd/system/ and use it to execute your script. (i.e. hello-world.service).
[Unit]
Description=Hello world
After=sysinit.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=no
RemainAfterExit=yes
User=root
ExecStart=/bin/echo hello world
ExecStop=/bin/echo goodby world
[Install]
WantedBy=multi-user.target
Now you can use it through systemctl as you would with other services.
$ systemctl enable hello-world
$ systemctl start hello-world
$ systemctl stop hello-world
$ systemctl status hello-world
● hello-world.service - Hello world
Loaded: loaded (/etc/systemd/system/hello-world.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Wed 2019-10-09 13:54:58 CEST; 1min 47s ago
Process: 11864 ExecStop=/bin/echo goodby world (code=exited, status=0/SUCCESS)
Main PID: 11842 (code=exited, status=0/SUCCESS)
Oct 09 13:54:38 lnxclnt1705 systemd[1]: Started Hello world.
Oct 09 13:54:38 lnxclnt1705 echo[11842]: hello world
Oct 09 13:54:57 lnxclnt1705 systemd[1]: Stopping Hello world...
Oct 09 13:54:57 lnxclnt1705 echo[11864]: goodby world
Oct 09 13:54:58 lnxclnt1705 systemd[1]: Stopped Hello world.
Make sure that you use the full path to your script in the unit file (i.e. /bin/echo). Check out the documentation about keys used in hello-world.service:
[Unit]
[Service]
Place the script inside /etc/init.d
Ensure that it has the extension '.sh'
For the crontab,
there is difference in if you set up user crontab or root crontab:
$ crontab -e
#reboot sudo ...
^^ This is user's cron tab and wont work as it is.
$ sudo crontab -e
#reboot ...
^^ This is root's cron tab and will run comand as root.
The #reboot should do the trick for you of running scripts after startup.

systemd: start service after the previous one have finished

I have installed certbot, and certbot makes it's own systemd service file "certbot.service" for auto cert renew, which is started trough a .timer file once a day.
After this "certbot.service" is sucessfully executed I like to execute a second one ("cert-copy-after-certbot.service") that copys the certificate to another place.
Currently my setting looks like this:
"certbot.service" (gernerated by certbot):
pi#raspberrypi:/lib/systemd/system $ cat certbot.service
[Unit]
Description=Certbot
Documentation=file:///usr/share/doc/python-certbot-doc/html/index.html
Documentation=https://letsencrypt.readthedocs.io/en/latest/
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot -q renew
PrivateTmp=true
"cert-copy-after-certbot.service":
pi#raspberrypi:/etc/systemd/system $ cat cert-copy-after-certbot.service
[Unit]
Description=crt update after certbot has run
Wants=certbot.service
After=certbot.service
[Service]
Type=simple
ExecStart=/bin/sh -c "cat /etc/letsencrypt/live/<mydomain>/privkey.pem /etc/letsencrypt/live/<mydomain>/fullchain.pem > /etc/ejabberd/ejabberd.pem"
If i run this files with:
systemctl start <unitname>
Both services are working.
But when I start certbot with "systemctl start certbot" and check
systemctl status cert-copy-after-certbot
the cert-copy-after-certbot.service didn't run.
Did i configured something wrong?
I found the solution, so here the answer just if someone has the same issue.
The problem is that the "certbot.service" unit don't know about "cert-copy-after-certbot.service". So if "certbot.service" is called no one calls the inactive "cert-copy-after-certbot.service" because the "Wants=" is never executed.
So if you don't wan't to alter the "certbot.service" unit (with "Wants=cert-copy-after-certbot.service", you can do the following.
Add an additional [Install] section in "cert-copy-after-certbot.service", with a line "WantedBy=cerbot.service". So that the file look like this:
pi#raspberrypi:/etc/systemd/system $ cat cert-copy-after-certbot.service
[Unit]
Description=crt update after certbot has run
After=certbot.service
[Service]
Type=simple
ExecStart=/bin/sh -c "cat /etc/letsencrypt/live/<mydomain>/privkey.pem/etc/letsencrypt/live/<mydomain>/fullchain.pem > /etc/ejabberd/ejabberd.pem"
[Install]
WantedBy=certbot.service
An install section requires an enable or disable call by systemctl (or start or stop for temporary testing).
systemctl enable cert-copy-after-certbot
This [Install] section will create a symbolic link as soon as you enable the unit that informs the systemd deamon if "certbot.service" is called, he have to call "cert-copy-after-certbot.service" to. (And the "After=" in the unit section tells systemd the row in which the sould called, without it, both units would run simultaneously)
You might find that cert-copy-after-certbot.service is started before cerbot.service is complete unless you also set RemainAfterExit=yes in cerbot.service

Resources