Skip to content

Commit 9fb6ecd

Browse files
committed
Initial commit, including first packaged version
Changes committed: new file: README.md new file: rpmbuild/BUILD/sysmotd/LICENSE.txt new file: rpmbuild/BUILD/sysmotd/README.txt new file: rpmbuild/BUILD/sysmotd/sysmotd new file: rpmbuild/BUILD/sysmotd/sysmotd.service new file: rpmbuild/BUILD/sysmotd/sysmotd.timer new file: rpmbuild/RPMS/noarch/sysmotd-0.0.1-1.fc37.noarch.rpm new file: rpmbuild/SOURCES/sysmotd-0.0.1.tar.gz new file: rpmbuild/SPECS/sysmotd.spec new file: rpmbuild/SRPMS/sysmotd-0.0.1-1.fc37.src.rpm new file: sysmotd/LICENSE.txt new file: sysmotd/README.txt new file: sysmotd/sysmotd new file: sysmotd/sysmotd.preset new file: sysmotd/sysmotd.service new file: sysmotd/sysmotd.timer
0 parents  commit 9fb6ecd

File tree

16 files changed

+945
-0
lines changed

16 files changed

+945
-0
lines changed

README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Summary
2+
3+
sysmotd is essentially a shell script that produces a Message Of The Day (MOTD) which includes system information and statistics.
4+
5+
It has been developed and tested on Fedora Linux and it might work on other Red Hat-based distributions with very small tweaks. It should also be relatively simple to port to other distributions that do not have their own dynamic MOTD generator.
6+
7+
As of time of writting, Fedora only uses pam_motd.so for ssh log ins.
8+
9+
# How it looks like
10+
11+
A picture is worth a thousand words.
12+
13+
14+
15+
# Background
16+
17+
I am a long term Fedora user. Having worked with some Ubuntu servers lately, I found myself missing the system information and statistics that you get when you log in. When I installed Fedora 37 on a Raspberry Pi4, I saw that cockpit would generate a MOTD, and I decided to research a bit to find out if I could add my own with some system statistics on it.
18+
19+
Out of the various sources I found, I would like to give credit to a couple that helped me a lot in getting the information that I wanted and what tools to use.
20+
21+
[1] https://github.com/angela-d/motd-for-centos
22+
23+
[2] https://gist.github.com/cha55son/6042560
24+
25+
While these sources gave me a good start, I wanted to reduce the number of dependencies to a minimum and make the dynamic part of the MOTD as efficient as possible, so I soon re-wrote most of the stuff and started looking into how to avoid using the user's profile to trigger the script. That leads us to the next section.
26+
27+
# Structure and how it works
28+
29+
My understanding is that Debian and Ubuntu distribute a patched version of pam_motd.so. Theirs runs scripts in /etc/update-motd.d. Also, their PAM configuration includes lines for static and dyanamic MOTDs.
30+
31+
[3] https://wiki.debian.org/motd
32+
33+
Using a patched version of pam_motd.so would have been the preferred approach, since the script updating the dynamic part of the MOTD only runs when a user logs in. However, I didn't know how difficult it would be to get a change like that approved for Fedora. My assumption was, and still is, that the people behind Fedora or Red Hat know that Debian and Ubuntu are using this dynamic MOTD approach and if they have not implemented it yet, it is because they have some valid reasons.
34+
35+
In that context, I resorted to use a systemd service to call the script and a timer to call the service, every minute. However, not all the parts of the script that generate the corresponding part of the MOTD run every minute.
36+
37+
So, sysmotd is comprised of:
38+
39+
### `/usr/libexec/sysmotd`
40+
41+
The shell script. It produces 3 files which are saved under `/run/motd.d`
42+
43+
- 00-sysmotd-header.motd: colorful header that changes every 60 minutes.
44+
- 01-sysmotd-sysinfo.motd: system information which is updated every 60 seconds.
45+
- 02-sysmotd-updates.motd: updates available which is updated every 60 minutes. It uses Fedora's own dnf cache which runs whenever it runs.
46+
47+
### `/usr/lib/systemd/system/sysmotd.service`
48+
49+
A systemd service to run the script. It is disabled and it should stay like that.
50+
51+
### `/usr/lib/systemd/system/sysmotd.timer`
52+
53+
A systemd timer to run the service every 60 seconds. The script works out which parts of the MOTD to update.
54+
It is enabled and started when the dnf package is installed.
55+
56+
### `/usr/lib/systemd/system-preset/50-sysmotd.preset`
57+
58+
A systemd preset file to disable sysmotd.service and enable sysmotd.timer by default.
59+
60+
In summary, what you get when you install sysmotd is a systemd timer that every 60 seconds runs a service, that runs a script, which in turn updates the header every 60 minutes, system's information every 60 seconds, and the updates available every 60 minutes too.
61+
62+
# How to install sysmotd and dependencies
63+
64+
These are the Fedora packages that you need to have installed for sysmotd to work:
65+
66+
```bash
67+
coreutils
68+
dnf
69+
figlet
70+
findutils
71+
gawk
72+
lolcat
73+
procps-ng
74+
systemd
75+
```
76+
77+
Most systems will have all of them installed apart from `figlet` and `lolcat`.
78+
79+
To install sysmotd and its dependencies, my recommendation is to download the rpm package under `rpmbuild/RPMS/noarch` in this repo, and install it with dnf.
80+
81+
```
82+
sudo dnf install sysmotd-0.0.1-1.fc37.noarch.rpm
83+
```
84+
85+
If you rather not install a package from an unknown source, and I wouldn't blame you for that, you can clone this repo and, after inspecting the files listed under the structure section, copy them to their respective folders. Please note that if you do this, and you are running selinux enforced, you will have to fix the context of the files.

rpmbuild/BUILD/sysmotd/LICENSE.txt

Lines changed: 208 additions & 0 deletions
Large diffs are not rendered by default.

rpmbuild/BUILD/sysmotd/README.txt

Whitespace-only changes.

rpmbuild/BUILD/sysmotd/sysmotd

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/sh
2+
#
3+
# sysmotd - generates a MOTD (Message Of The Day) including system
4+
# information on Fedora Linux, and possibly other Red Hat-based distributions.
5+
#
6+
# Copyright (C) 2022 Manuel Fombuena <mfombuena@innovara.co.uk>
7+
#
8+
# This program is free software: you can redistribute it and/or modify
9+
# it under the terms of the GNU General Public License as published by
10+
# the Free Software Foundation, either version 3 of the License, or
11+
# (at your option) any later version.
12+
#
13+
# This program is distributed in the hope that it will be useful,
14+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
# GNU General Public License for more details.
17+
#
18+
# You should have received a copy of the GNU General Public License
19+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
#
21+
22+
# directory where the motd files will live
23+
rundir="/run/motd.d"
24+
header="$rundir/00-header.motd"
25+
sysinfo="$rundir/01-sysinfo.motd"
26+
updates="$rundir/02-updates.motd"
27+
28+
# some variables
29+
. /etc/os-release
30+
31+
# hostname
32+
hostname=$(uname -n)
33+
34+
# uptime
35+
uptime=$(awk '{print int($1)}' /proc/uptime)
36+
upDays=$((uptime/60/60/24))
37+
upHours=$((uptime/60/60%24))
38+
upMins=$((uptime/60%60))
39+
upSecs=$((uptime%60))
40+
41+
# avg load
42+
load1=$(awk '{print $1}' /proc/loadavg)
43+
load5=$(awk '{print $2}' /proc/loadavg)
44+
load15=$(awk '{print $3}' /proc/loadavg)
45+
46+
# memory
47+
mem_total=$(awk '/MemTotal/ {print $2;}' /proc/meminfo)
48+
mem_used=$(($mem_total-$(awk '/MemFree/ {print $2;}' /proc/meminfo)-$(awk '/Buffers/ {print $2;}' /proc/meminfo)-$(awk '/\yCached\y/ {print $2;}' /proc/meminfo)))
49+
mem_perc=$(($mem_used*100/$mem_total))
50+
swap_total=$(awk '/SwapTotal/ {print $2;}' /proc/meminfo)
51+
swap_used=$((${swap_total} - $(awk '/SwapFree/ {print $2;}' /proc/meminfo)-$(awk '/SwapCached/ {print $2;}' /proc/meminfo)))
52+
swap_perc=$((swap_used*100/swap_total))
53+
54+
# filesystem info
55+
root_used=$(df -h --output=used / | awk '{if (NR!=1) print $1}')
56+
root_total=$(df -h --output=size / | awk '{if (NR!=1) print $1}')
57+
root_perc=$(df -h --output=pcent / | awk '{if (NR!=1) print $1}')
58+
59+
# users
60+
users=$(users | wc -w)
61+
62+
# processes
63+
processes=$(ps aux --no-headers | wc -l)
64+
65+
### MOTD ###
66+
67+
# colourful header. Updated every 60 minutes only but no real performance gain
68+
NEED_UPDATE="FALSE"
69+
[ -z "$(find "$header" -newermt 'now-60 minutes' 2> /dev/null)" ] && NEED_UPDATE="TRUE"
70+
71+
if [[ "$NEED_UPDATE" = "TRUE" ]]; then
72+
echo "$(figlet ${REDHAT_SUPPORT_PRODUCT} ${REDHAT_SUPPORT_PRODUCT_VERSION} -c | lolcat -r -f)" > $header
73+
fi
74+
75+
# sysinfo update
76+
echo -e "Welcome to ${PRETTY_NAME} ($(uname -o) $(uname -r))
77+
78+
System information as of $(date)
79+
80+
Hostname:\t${hostname}\t\tMemory usage:\t$((${mem_used}/1024))/$((${mem_total}/1024))M (${mem_perc}%)
81+
Uptime:\t\t${upDays}d ${upHours}h ${upMins}m ${upSecs}s\t\t\tSwap usage:\t$((${swap_used}/1024))/$((${swap_total}/1024))M (${swap_perc}%)
82+
Load 1-5-15min:\t${load1}-${load5}-${load15}\t\t\tUsage of /:\t${root_used}/${root_total} (${root_perc})
83+
Processes:\t${processes}\t\t\t\tUsers:\t\t${users}
84+
" > $sysinfo
85+
86+
# updates available updated every 60 minutes using CACHE.
87+
# dnf's cache is updated by the system using its own service and timer. The conservative
88+
# approach is to not to change this.
89+
NEED_UPDATE="FALSE"
90+
[ -z "$(find "$updates" -newermt 'now-60 minutes' 2> /dev/null)" ] && NEED_UPDATE="TRUE"
91+
92+
if [[ "$NEED_UPDATE" = "TRUE" ]]; then
93+
n_updates=$(dnf update --assumeno --cacheonly --noplugins | awk '/^Upgrade/ {print $2;}')
94+
if [[ $n_updates -eq 0 ]]; then
95+
echo -e "There were no updates available when last checked.\n" > $updates
96+
elif [[ $n_updates -eq 1 ]]; then
97+
echo -e "There was 1 update available when last checked.\n" > $updates
98+
else
99+
echo -e "There were ${n_updates} updates available when last checked.\n" > $updates
100+
fi
101+
fi
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[Unit]
2+
Description=sysmotd service to update MOTD
3+
4+
[Service]
5+
Type=oneshot
6+
User=root
7+
Group=root
8+
RemainAfterExit=no
9+
ExecStart=/usr/libexec/sysmotd
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[Unit]
2+
Description=Timer for sysmotd service
3+
Requires=sysmotd.service
4+
5+
[Timer]
6+
Unit=sysmotd.service
7+
OnBootSec=15s
8+
OnUnitActiveSec=1m
9+
10+
[Install]
11+
WantedBy=timers.target
20.5 KB
Binary file not shown.
12.6 KB
Binary file not shown.

rpmbuild/SPECS/sysmotd.spec

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
Name: sysmotd
2+
Version: 0.0.1
3+
Release: 1%{?dist}
4+
Summary: Generates a MOTD (Message Of The Day) including system information on Fedora Linux
5+
BuildArch: noarch
6+
7+
License: GPLv3+
8+
URL: https://github.com/innovara/sysmotd
9+
Source0: %{name}-%{version}.tar.gz
10+
11+
Requires: bash
12+
Requires: coreutils
13+
Requires: dnf
14+
Requires: figlet
15+
Requires: findutils
16+
Requires: gawk
17+
Requires: lolcat
18+
Requires: procps-ng
19+
Requires: systemd
20+
21+
%description
22+
23+
Sysmotd produces a MOTD that includes system information being collected
24+
on a regular basis. Users will see the MOTD when logging in via ssh.
25+
26+
%prep
27+
%autosetup
28+
29+
30+
%build
31+
32+
33+
%install
34+
35+
mkdir -p %{buildroot}/%{_libexecdir}
36+
%{__install} -Dm744 %{name} %{buildroot}/%{_libexecdir}/%{name}
37+
38+
mkdir -p %{buildroot}/%{_unitdir}
39+
%{__install} -Dm644 %{name}.service %{buildroot}/%{_unitdir}/%{name}.service
40+
%{__install} -Dm644 %{name}.timer %{buildroot}/%{_unitdir}/%{name}.timer
41+
42+
43+
%{__install} -Dm644 %{name}.preset %{buildroot}/%{_presetdir}/50-%{name}.preset
44+
45+
%files
46+
%license LICENSE.txt
47+
%doc README.txt
48+
%{_libexecdir}/%{name}
49+
%{_unitdir}/%{name}.service
50+
%{_unitdir}/%{name}.timer
51+
%{_presetdir}/50-%{name}.preset
52+
53+
54+
%post
55+
56+
%systemd_post %{name}.timer
57+
systemctl start %{name}.timer > /dev/null 2>&1
58+
59+
%preun
60+
61+
%systemd_preun %{name}.timer
62+
%systemd_preun %{name}.service
63+
64+
%postun
65+
66+
rm -f /run/motd.d/*%{name}*
67+
68+
69+
%changelog
70+
* Mon Dec 26 2022 Manuel Fombuena <mfombuena@innovara.co.uk>
71+
- First version being packaged
22.5 KB
Binary file not shown.

0 commit comments

Comments
 (0)