LFCS — Linux Foundation System Administrator
Writing Unit Files and Scheduling Configuration
Goal
You write systemd unit files and timers, cron files, log rotation settings, and drop-in overrides yourself, following the syntax and section rules.
Why it matters
In this lab environment systemctl is blocked, so you cannot start services. So all grading is done on file contents. At first glance it seems like a loss, but in practice it lets you concentrate exactly on the spot where people get the most wrong on the exam — the reason you miss a unit problem on the LFCS is not that the service failed to start, but that you put a directive in the wrong section or got the format wrong. If you write WantedBy in [Service], it will not be enabled; a timer's WantedBy is timers.target, not multi-user.target; and a file in /etc/cron.d has one more user field. When you change ExecStart in a drop-in, if you do not clear it once with an empty line, there become two commands and startup fails. All of these are errors you can catch from the file alone.
Steps
- Create
/root/lfcs-svc/lfcs-api.serviceand put the three sections[Unit],[Service], and[Install]in this order. Put a non-emptyDescription=in[Unit]. - In the same file, fill in
After=network-online.target,Wants=network-online.target,Type=simple,ExecStart=/usr/local/bin/lfcs-api --port 8080,Restart=on-failure,RestartSec=5,User=lfcsapi, andWantedBy=multi-user.target, each in the appropriate section. - In
/root/lfcs-svc/lfcs-backup.timer, put a[Timer]section withOnCalendar=*-*-* 03:30:00,Persistent=true, andUnit=lfcs-backup.service, and enable it withWantedBy=timers.target. In the paired/root/lfcs-svc/lfcs-backup.service, putType=oneshotandExecStart=/usr/local/bin/lfcs-backup.sh. - Create
/etc/cron.d/lfcs-reportand put in a line beginning with*/15 * * * * root /usr/local/bin/lfcs-report.sh, but send the output to/var/log/lfcs-report.log. - In
/root/lfcs-svc/lfcsops.crontab, put30 2 * * 1-5 /usr/local/bin/lfcs-rotate.shin user crontab format. This format has no user field. - In
/etc/cron.d/lfcs-report, put the two linesSHELL=/bin/bashandPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binbefore the schedule line. - In
/root/lfcs-svc/lfcs-report.logrotate, create a block for/var/log/lfcs-report.logand put indaily,rotate 14,compress,delaycompress,missingok,notifempty, andcreate 0640 root adm. - Create
/root/lfcs-svc/lfcs-api.service.d/override.conf, put an empty-valuedExecStart=first under[Service], and then addExecStart=/usr/local/bin/lfcs-api --port 9090andMemoryMax=512M.
Notes
- In this environment
systemctldoes not work. Grading is done on file contents only. On a real server you would check the syntax withsystemd-analyze verifyand apply it withsystemctl daemon-reload. StartLimitIntervalSecandStartLimitBurstare directives of the[Unit]section, not[Service].- Pipes and redirection do not work in
ExecStart=. That is because systemd runs it without going through a shell. - A common mistake: a file under
/etc/cron.dis ignored if its name contains a dot. Do not add an extension.
Build the unit file skeleton
Create /root/lfcs-svc/lfcs-api.service and put the three sections [Unit], [Service], and [Install] in this order. Put a non-empty Description= in [Unit].
A unit file is in INI format and section names are wrapped in square brackets. Get the order and capitalization of the three sections exactly right.
Execution, restart, and enable directives
In the same file, fill in After=network-online.target, Wants=network-online.target, Type=simple, ExecStart=/usr/local/bin/lfcs-api --port 8080, Restart=on-failure, RestartSec=5, User=lfcsapi, and WantedBy=multi-user.target, each in the appropriate section.
Which section each directive belongs to is fixed. The enable target goes in [Install], the way it runs goes in [Service], and ordering dependencies go in [Unit].
Timer unit and its paired service
In /root/lfcs-svc/lfcs-backup.timer, put a [Timer] section with OnCalendar=*-*-* 03:30:00, Persistent=true, and Unit=lfcs-backup.service, and enable it with WantedBy=timers.target. In the paired /root/lfcs-svc/lfcs-backup.service, put Type=oneshot and ExecStart=/usr/local/bin/lfcs-backup.sh.
A timer does not do work itself; it wakes the unit with the same name. There is a separate directive that makes it catch up on runs that passed while it was off.
Writing a /etc/cron.d file
Create /etc/cron.d/lfcs-report and put in a line beginning with */15 * * * * root /usr/local/bin/lfcs-report.sh, but send the output to /var/log/lfcs-report.log.
A system cron file has one more field, the user to run as, after the 5 time fields. If you do not keep the output, cron tries to send it by mail.
User crontab format
In /root/lfcs-svc/lfcsops.crontab, put 30 2 * * 1-5 /usr/local/bin/lfcs-rotate.sh in user crontab format. This format has no user field.
A user crontab has no user field. In the day-of-week field, a range is written with a hyphen.
cron's PATH problem
In /etc/cron.d/lfcs-report, put the two lines SHELL=/bin/bash and PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin before the schedule line.
Environment variable lines take effect only if they come before the schedule line. The reason for this step is that the PATH cron gives by default is much shorter than that of a login shell.
Log rotation settings
In /root/lfcs-svc/lfcs-report.logrotate, create a block for /var/log/lfcs-report.log and put in daily, rotate 14, compress, delaycompress, missingok, notifempty, and create 0640 root adm.
After the target path, open a brace block and put in one directive per line. There is a directive that specifies the permissions and ownership of the new file to be created right after rotation.
Drop-in override
Create /root/lfcs-svc/lfcs-api.service.d/override.conf, put an empty-valued ExecStart= first under [Service], and then add ExecStart=/usr/local/bin/lfcs-api --port 9090 and MemoryMax=512M.
The drop-in directory name is the unit file name with a suffix attached. A list-type directive appends to the existing value unless you first put a line that clears its value.