EBC Exercise 21b systemd
Embedded Linux Class by Mark A. Yoder
Traditionally user space initialization has been done using init.d, however recently many distributions have been switching to systemd
systemd is a system and service manager for Linux, compatible with SysV and LSB init scripts. systemd provides aggressive parallelization capabilities, uses socket and D-Bus activation for starting services, offers on-demand starting of daemons, keeps track of processes using Linux control groups, supports snapshotting and restoring of the system state, maintains mount and automount points and implements an elaborate transactional dependency-based service control logic.
Here we'll see how to use systemd as an administration and how to create a simple service.
Contents
Administration
There are a few simple commands that show what's running under systemd and how to stop and start them. The examples here were inspired by the twenty part series on systemd administration and the three part intro by Carla Schroder
To see what's running, run
bone$ systemctl UNIT > proc-sys-fs-binfmt_misc.automount > sys-devices-platform-ocp-44c00000.interconnect-44c00000.interconnect:seg> sys-devices-platform-ocp-44c00000.interconnect-44c00000.interconnect:seg> sys-devices-platform-ocp-47400000.target\x2dmodule-47401400.usb-musb\x2d> sys-devices-platform-ocp-47400000.target\x2dmodule-47401400.usb-musb\x2d> sys-devices-platform-ocp-47400000.target\x2dmodule-47401c00.usb-musb\x2d> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg> sys-devices-platform-ocp-4a000000.interconnect-4a000000.interconnect:seg> sys-devices-virtual-misc-rfkill.device > sys-devices-virtual-net-docker0.device > sys-devices-virtual-tty-ttyGS0.device > sys-module-configfs.device > sys-module-fuse.device > sys-subsystem-net-devices-can0.device > sys-subsystem-net-devices-can1.device > sys-subsystem-net-devices-docker0.device > sys-subsystem-net-devices-eth0.device > sys-subsystem-net-devices-usb0.device > sys-subsystem-net-devices-usb1.device > sys-subsystem-net-devices-wlan0.device > -.mount > dev-mqueue.mount > run-docker-netns-default.mount > run-user-1000.mount > sys-fs-fuse-connections.mount
and so on. Look through the list and see what you recognize. If you make your window bigger you will see more information. Here's how to find more details about a given process.
bone$ systemctl status nginx.service ● nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enab> Active: active (running) since Wed 2023-01-11 15:25:04 EST; 1 weeks 5 days ago Docs: man:nginx(8) Main PID: 750 (nginx) Tasks: 2 (limit: 1024) Memory: 3.7M CPU: 2.018s CGroup: /system.slice/nginx.service ├─750 nginx: master process /usr/sbin/nginx -g daemon on; master_proces> └─751 nginx: worker process Jan 11 15:25:01 ece434 systemd[1]: Starting A high performance web server and a reve> Jan 11 15:25:04 ece434 systemd[1]: Started A high performance web server and a rever>
Stopping and Starting
You can stop a process with
bone$ sudo systemctl stop nginx.service
Now try accessing the web server (192.168.7.2). It isn't there. You can start it with
bone$ systemctl start nginx.service bone$ systemctl status nginx.service ● nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2023-01-24 10:07:23 EST; 38s ago Docs: man:nginx(8) Process: 16409 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS) Process: 16410 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS) Main PID: 16411 (nginx) Tasks: 2 (limit: 1024) Memory: 5.7M CPU: 392ms CGroup: /system.slice/nginx.service ├─16411 nginx: master process /usr/sbin/nginx -g daemon on; master_process on; └─16412 nginx: worker process Jan 24 10:07:12 ece434 systemd[1]: Starting A high performance web server and a reverse proxy server... Jan 24 10:07:23 ece434 systemd[1]: Started A high performance web server and a reverse proxy server.
Notice the log messages have changed.
Now, when you browse to 192.168.7.2 you will get an answer.
Autostart at boot time
You can use enable and disable to make a service start (or not start) at boot time.
bone$ sudo systemctl disable nginx.service Synchronizing state of nginx.service with SysV service script with /lib/systemd/system-sysv-install. Executing: /lib/system/systemd-sysv-install disable nginx Removed /etc/system/system/multi-user.target.wants/nginx.service.
bone$ sudo systemctl enable nginx.service Synchronizing state of nginx.service with SysV service script with /lib/systemd/system-sysv-install. Executing: /lib/system/systemd-sysv-install enable nginx Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /lib/systemd/system/nginx.service.
Watch out though, if some other service needs the service you disabled, it will start anyway.
Stopping no matter what
If you want to stop a service NO MATTER WHAT.
beagle$ ln -s /dev/null /etc/systemd/system/servicename.service beagle$ systemctl daemon-reload
systemd first looks in /etc/systemd/system
and then looks in /lib/systemd/system
. The command above places an empty file in /etc/systemd/system, so the real file in /lib/systemd/system is never seen.
Running your own service
If you check in exercises/flask/server you find app4.py a server for some flask demos. You run it with:
beagle$ cd exercises/flask/server beagle$ ./app4.py * Serving Flask app "app4" (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: on * Running on http://0.0.0.0:8081/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 103-331-254
Now point a browser to 192.168.7.2:8081. You'll see the demo served up by flask. Suppose you want the app4.py to automatically start every time the Beagle boots. Here is how to do it.
We need to create a service file and the quickest way is to find one that does similar things.
bone$ systemctl | grep nginx nginx.service loaded active running A high performance web server and a reverse proxy server
Check its status.
bone$ systemctl status nginx.service ● nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2023-01-24 10:07:23 EST; 3h 13min ago ...
Looks like the file is in /lib/systemd/system/nginx.service copy it to a handy place and take a look.
beagle$ cp /lib/systemd/system/nginx.service flask.service beagle$ cat flask.service [Unit] Description=A high performance web server and a reverse proxy server Documentation=man:nginx(8) After=network. Target nss-lookup.target [Service] Type=forking PIDFile=/run/nginx.pid ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;' ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;' ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid TimeoutStopSec=5 KillMode=mixed [Install] WantedBy=multi-user. Target
Modify the file so it will work for your server. Make sure to modify 'Description' as well or your service will confuse itself with the original nginx.service. Here's what mine looks like:
[Unit] Description=flask server [Service] WorkingDirectory=/home/debian/exercises/flask/server ExecStart=/home/debian/exercises/flask/server/app4.py SyslogIdentifier=flask [Install] WantedBy=multi-user. Target
Once your flask. Service file is ready, copy it to the right place
bone$ cp flask.service /lib/system/system
and start the server
beagle$ systemctl start flask
Point your browser to 192.168.7.2:8081 and see if it works.
To make it work after rebooting
bone$ systemctl enable flask ln -s '/lib/systemd/system/flask.service' '/etc/systemd/system/multi-user.target.wants/boneServer.service'
Notice it copies your file to another place. Try rebooting and see if it works.
Embedded Linux Class by Mark A. Yoder