Lately, there comes a need where needed to configure a sysemctl startup script for stop and start of services on Linux servers. Usually, oracle services come with high availability and cluster-based services which provides this similar capability but in cases where we don’t have this capability, we as an administrator may need to understand how to perform such operations. Now systemctl services can be created easily but if one wants to package that as an rpm and deploy on the various services we can use the following steps.
RPM stands for Red Hat Package Manager. It was developed by Red Hat and is primarily used on Red Hat-based Linux operating systems. These packages come up with a .rpm extension and use the following format:
<name>-<version>-<release>.<arch>.rpm
Each of these components is critical and will be tied up together as we create the package in the coming section of this blog.
To build an RPM we first need to create the following directory structure where every directory has its significance.
rpmbuild/
├── BUILD
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS
Let’s discuss in more detail the directory structure
BUILD directory is used during the build process of the RPM package. This is where the temporary files are stored, moved around, etc.
RPMS directory holds RPM packages built for different architectures and noarch if specified in .spec file or during the build. This will hold the resultant package created and to be used for consumption.
SOURCES directory, as the name implies, holds sources. This can be a simple script, a complex C project that needs to be compiled, a pre-compiled program, etc. Usually, the sources are compressed as .tar.gz or .tgz files.
SPEC directory contains the .spec files. The .spec file defines how a package is built. More details in coming sections on this.
SRPMS directory holds the .src.rpm packages. A Source RPM package doesn’t belong to architecture or distribution. The actual .rpm package build is based on the .src.rpm package.
There is a utility named rpmdev-setuptree which can be made available by installing rpmdevtools. This will create the directory structure needed to build RPM and we have to place the necessary files in SPEC and SOURCES folder.
To create a systemd startup script we need to first create a unit file of that component which will be used to stop and start the component. One sample unit file is shown below:
[Unit]
Description=Component System D
After=network.target local-fs.target sssd.service
[Service]
Type=forking
User=oracle
Group=oinstall
LimitNOFILE=131072
LimitNPROD=131072
LimitCORE=infinity
ExecStart=<path>/<startup_script>.sh start
ExecStop=<path>/<stop_script>.sh stop
TimeoutStartSec=200
TimeoutStopSec=100
[Install]
WantedBy=multi-user.target
Kindly note startup_script.sh and stop_script.sh are two shell scripts that will be used by this systemd service for stopping and starting the services respectively. They must also be available at the specified path. This stop/start script can also be packaged into the same rpm along with the unit file.
The next step is to create a file and place that into the SOURCES directory which as we mentioned earlier in the source code of this RPM.
Now here is one catch we have to create a tar file with the same as specified in the specification file like
<Name>-<Version>-<Release>.tar.gz
Here <Name> is the name of the package specified in a specification file
<Version> is the version of the package specified in a specification file
<Release> is the release version of the package-specific in the specification file.
Also, make sure within this tar file directory structure remains the same as that you want to unpack on the server. For example, let’s say here
Name: oraclestartup
Version: 0.0.1
Release: 1
Two scripts needs to be unpacked like component.service in directory /user/lib/systemd/system and startup.sh to be copied under /opt. In this case tar file must look like
oraclestartup-0.0.1-1/opt/startup.sh
oraclestartup-0.0.1-1/user/lib/systemd/system/component.service
tar -zcvf oraclestartup-0.0.1-1.tar.gz oraclestartup-0.0.1-1
cp raclestartup-0.0.1-1.tar.gz ~/SOURCES/
The above source code will unpack the unit service file in systemd and startup shell script under /opt which is needed for the systemctl service to run properly.
Now since our source code is ready now it’s time to build the specification file.
The specification file comes up with .spec extension and it is better to create with the same name as the name used in the specification file for the rpm. For example in this case it’s oraclestartup.spec. Specification file template can also be created using utility rpmdev-newspec <file_name>.
BuildArch: noarch
Name: oraclestartup
Version: 0.0.1
Release: 1
License: None
Group: None
Summary: Prerequisites for oracle startup installation
Source0: %{name}-%{version}-%{release}.tar.gz
%description
Package to deploy oraclestartup script
%prep
%setup -n ccc
%install
rm -rf $RPM_BUILD_ROOT
install -d -m 755 $RPM_BUILD_ROOT/%{name}-%{version}-%{release}
cp -R %{_builddir}/%{name}-%{version}-%{release}/* $RPM_BUILD_ROOT
%files
%attr(0700, oracle, oinstall) “/opt/startup.sh”
%attr(0644, root, root) “/usr/lib/systemd/system/component.service”
%pre -p /bin/sh
if [[ ! -d /opt ]]; then
echo “Directory /opt does not exists can not install rpm” >&2
return 1
fi
%post -d /bin/sh
if [[ $1 = 1 ]]; then
systemctl enable pmcd
systemctl enable pmlogger
systemctl start pmcd
systemctl start pmlogger
fi
systemctl daemon-reload
%preun -p /bin/sh
%postun -p /bin/sh
systemctl daemon-reload
%changelog
* Thu Apr 15 2022 Arpit Agrawal <example.co.in>
– Initial release
Now it’s time to build the package as our source code and specification files are ready. For this, we will use rpmbuild.
rpmbuild -bb ~rpmbuild/SPECS/oraclestartup.spec
This will create the RPM file named <name>-<version>-<release>.<arch>.rpm and can be used for consumption. In order to install the RPM package we can use:
sudo rpm -ivh ~rpmbuild/RPMS/noarch/<name>-<version>-<release>.<arch>.rpm
In some organizations where we may need to sign the RPM and it can be done using the following command.
rpm –addsign <name>-<version>-<release>.<arch>.rpm
If someone wants to check whether packages is already signed
rpm –checksig <name>-<version>-<release>.<arch>.rpm
In some cases where you have to build another rpm, a yum repository may still show the old version. In this case, we may need to clean metadata.
yum –enablerepo-<reponame> clean metadata
yum clean all
Great blog here. Enjoy your blogging journey. I think you’re gonna love it. There may be no more fun, freeing way to help people on virtually any topic.