Skip to main content

Helpful custom Systemd Timers and services

Intro

I thought I'd share some useful scripts for systemd that replace a cron daemon, and that I use on many of my Gentoo machines.  Since moving away from openrc, I had to relearn a bit, especially the daily cron jobs that I was so used to.  But I will trade crontab -e for journalctl functionality any day-- so useful.  Anyways, I no longer have any crons installed.  What to do?  I have 1 Gentoo headless file server that needs to run all of these services, 1 desktop (the "bulldozer") and a couple laptops that need to run a subset of these services.

1. Eix-sync Service and Timer

I have the excellent eix program installed, and use the wrapper eix-sync for portage and overlay syncing and eix database updating in one shot.  Naturally, I want to run this daily for all my machines, and I have my server as a local portage mirror (just a matter of changing the make.conf SYNC setting on the clients: SYNC="rsync://jwilly/gentoo-portage").  Thus, the service need for systemd.  Putting this is crontab was super easy.  Here's how to do it for systemd.  Soon you'll see it's almost as easy, just a few things to understand and watch out for.

I give credit to solpeth for the idea and simple howto.  It's basically a copy of his/hers.

The idea is that a timer file is running (started and enabled by user), which will trigger a service file (not enabled by user) to run at a specific time of day, or week, or whatever, and repeat.  Hence why it's called a timer.  The service file that's triggered will run whatever script or program you want once, repeating as dictated by the timer file.  I have my timer setup to trigger once a day, everyday.

My /etc/systemd/system/eix-sync-daily.service, which is not enabled nor started, but is triggered by the timer file:

[Unit]
Description=eix-sync

[Service]
Nice=19
IOSchedulingClass=2
IOSchedulingPriority=7
ExecStart=/usr/bin/eix-sync

The timer file, /etc/systemd/system/eix-sync-daily.timer, is what triggers the service.  The timer is enabled and started, and you can see that it is setup to run daily:

[Unit]
Description=Run eix-sync daily

[Timer]
OnCalendar=daily
Persistent=true
Unit=eix-sync-daily.service

[Install]
WantedBy=timers.target

OnCalendar=daily will run at about midnight every night.  It isn't exact timing, but it's usually within a minute or two.  More timing info can be found on freedesktop.org's man pages: systemd.timer and systemd.time.

I think you can see how to modify these two simple files to run almost any program, script you want.  In fact, that's exactly what I've done in the next section.

2. Blogger Post Daily Service and Timer

I help manage a blog which needs to post everyday.  I also didn't want to do this everyday, manually, so of course I figured out a way to let a script do this!  The script was written in python, of which I am no expert.  I expanded the systemd service+timer duo to make the script run everyday at midnight.  Actually, I post at 11pm so I can verify it before I sleep.  It's very similar to the eix-sync service+timer.

Here's the service file, /etc/systemd/system/post-tomorrows-daily-bible.service:  (Again, this is neither enabled nor started).

[Unit]
Description=post-tomorrows-daily-bible.service

[Service]
Type=simple
ExecStart=/usr/local/bin/post-tomorrows-daily-bible.sh
WorkingDirectory=/mnt/huge/share/Podcasts/RochDailyBible

I actually have a bash script that then runs the python script (I couldn't get the python script to run from the service file, not sure why).  

The bash script is simple:

#!/bin/bash
# Run Python script
(cd /mnt/huge/share/Podcasts/RochDailyBible && python blogger_setup_daily2.py)


The timer file, /etc/systemd/system/post-tomorrows-daily-bible.timer: (This one is enabled and started, of course)

[Unit]
Description=post-tomorrows-daily-bible.timer

[Timer]
OnCalendar=23:00
Unit=post-tomorrows-daily-bible.service

[Install]
WantedBy=timers.target

Notice the OnCalendar is literal, at 11pm.  It can take much more complicated, powerful timing parameters, but this works for what I need.

The scripts in order, in summary: timer triggers at 11pm calls the service, which then calls the bash.sh, which then calls the python.py.  

3. Delete Old Distfiles Daily Service and Timer

I was starting to fill up my harddrive with old distribution source files, and with Gentoo they reside in /usr/portage/distfiles.  There's only so much room for old libreoffice, ibm-jdk, and kernel sources!  Those are yesterday's duckies.  Ha, I think I had at one time 8 or 9 gigs and I needed storage for a few audiobooks.  Weeding those out looks like deleting anything that hasn't been accessed in 180 days. I figure that's plenty of time to keep things around.  Herein lies my service+timer and the cleaning script I run.

The service file, /etc/systemd/system/delete-old-distfiles.service:

[Unit]
Description=delete-old-distfiles-180

[Service]
#Type=simple
Nice=19
IOSchedulingClass=2
IOSchedulingPriority=7
ExecStart=/usr/local/bin/delete-old-distfiles.sh
WorkingDirectory=/usr/portage/distfiles

The bash script, /usr/local/bin/delete-old-distfiles.sh, to clean my distfiles not accessed in 180 days:

#!/bin/bash
echo ""
echo "Current Root filesystem usage:"
df -h | grep Filesystem
df -h | grep /dev/sda3
echo ""
echo ""
echo "Deleting distfiles older than 180 days..."
find /usr/portage/distfiles -maxdepth 1 -type f -atime +180 -delete
echo ""
echo "New Root filesystem usage:"
df -h | grep Filesystem
df -h | grep /dev/sda3
echo ""

 
The interesting part of the clean script is the "find" line, where I only go 1 level deep in the directory, look for only files that have an access time older than 180 days and delete them.

The timer file, /etc/systemd/system/delete-old-distfiles.timer:

[Unit]
Description=Run delete-old-distfiles daily

[Timer]
OnCalendar=daily
Persistent=true
Unit=delete-old-distfiles.service

[Install]
WantedBy=timers.target

Again, this one runs at midnight, like my first one.  


That's it for now.  Hope these examples help anyone who's trying to schedule tasks in systemd!

~JWilly

Comments

Popular posts from this blog

Atmega328PB Dev on Linux x64

The Atmega328PB is the greatest thing to come to the Arduino platform since the UNO.  Who wouldn't want more 16-bit PWMs and double all 3 serial protocols? The new unofficial Arduino Mini PB Pro! To get the IDE to support it, follow this guide: https://github.com/watterott/ATmega328PB-Testing Since the JSON file is incomplete for Linux, do the manual toolchain replacement.  This was a little tricky, and there isn't much on the internet on where the toolchain resides inside the Arduino base folder.  Here's what I did to make it work. I downloaded the latest Arduino build, and I will refer to the extracted base directory as "arduino-1.6.9".  Also download the "hardware.zip" and the "Arduino Toolchain (4.9.2)" Linux x64 version from the github links. 1. Replace the toolchain The builtin toolchain resides in "arduino-1.6.9/hardware/tools/avr/".  Rename the avr folder to "avr.old".  Extract the "Arduino Toolc...

PB Pro Mini

No, it isn't Lead, nor is it Peanut Butter.  It is the 'B' version of the prolific ATmega328P microcontroller which started all this maker craziness off! Top view of PB Pro Mini Description This is a minimal microcontroller board with only a voltage reg, crystal, I2C pull-ups, LEDs and the chip itself.  The goal here is to reduce costs while hosting the beefy 328PB! This is based on, and pin compatible with, the Arduino Pro Mini 5v/16MHz from  Sparkfun . Notable, not-so-minor improvements for the 'B' version: 2 UARTs 2 I2Cs (TWI) 2 SPI Qtouch 5 Timers (with OC, IC, and PWM) Everything else is about the same.  You should be aware the clock driver on the chip is a low-power version, but this board and crystal operate at 16MHz just fine at 5V.  The Arduino library I've been using for the PB has been working without a problem! Getting Started You'll need a FTDI Friend  or FTDI Cable  to program this as there is no seconda...

Update to USBmicroISP: 6pin and 10pin headers

Actually using my USBmicroISP with microcontrollers other than Arduino Uno's led me to fix a udev rule issue with my Gentoo Linux laptop.  I was getting Permission Denied when I was trying to use avrdude as a normal user.  Yes, my user is part of the 'uucp' group... Background Some background on the Arduino ISP connector.  It is much different than the 10-pin AVR connector... 6-pin ICSP cable pinout.  NOTE: Numbers refer to ATtiny45/85 pins, not ICSP! Arduino ISP pinout. Notice the vertical line next to pin 1, which appears in silkscreen on the PCBs. Redboard ISP pinout.  Obviously the same as UNO.  Notice pin 1 location on upper-left, with horizontal white silk. My USBmicroISP has the cables coming off the IDC differently, but the key is in the correct orientation to the pinout in the top picture! (Please disregard numbering on first picture for ICSP purposes)  Usually the key and wires are facing inward (left side on 2nd and 3rd ...