Adding Custom Services With systemd

systemd is a system and service manager for Linux similar to SysV init. Several Linux distributions, notably Red Hat Enterprise Linux, SuSE, CentOS, Fedora, Debian and Ubuntu, are adopting it for their current or future releases. You can now experience systemd on Fedora and Red Hat Enterprise Linux 7 Beta.

We decided to install customized versions of Apache httpd and Percona Server, both of which must be started on boot.  systemd configurations had to be created for these.  We based our configuration files on existing ones for Apache httpd and MySQL. Furthermore, we made sure that necessary directories for these software are created at boot time.

The procedures described below were done on a VMware installation of Red Hat Enterprise Linux 7 Beta. These procedures should work on Fedora 20 as well (we’ll verify this in the future).

First, we compile and install Apache httpd version 2.4.9 (we’ll write an article about this in the future). Our installation of Apache httpd is in /opt/apache. The configuration files are in /etc/opt/apache while the logs are in /var/opt/apache.  Note that this layout of the installation is the opt layout for Apache httpd which is specified during configuration of the source.

Let us take a look at the systemd configuration file for the built-in Red Hat httpd daemon:

[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/httpd
ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND
ExecReload=/usr/sbin/httpd $OPTIONS -k graceful
ExecStop=/bin/kill -WINCH ${MAINPID}
# We want systemd to give httpd some time to finish gracefully, but still want
# it to kill httpd after TimeoutStopSec if something went wrong during the
# graceful stop. Normally, Systemd sends SIGTERM signal right after the
# ExecStop, which would kill httpd. We are sending useless SIGCONT here to give
# httpd time to finish.
KillSignal=SIGCONT
PrivateTmp=true

[Install]
WantedBy=multi-user.target

The above file, named httpd.service, is found in /usr/lib/systemd/system.

We now create another file which we name as apache-httpd.service and place in /usr/lib/systemd/system. Note that we must make sure that httpd.service is disabled. Let us disable it using the command:

sudo systemctl disable httpd.service

To check the status of a service, we can type the following command:

sudo systemctl status httpd.service

Now, our apache-httpd.service file for the custom Apache httpd installation contains the following:

[Unit]
Description=The Apache HTTP Server (akumubuild)
After=network.target remote-fs.target nss-lookup.target percona-server.service

[Service]
#Type=notify
Type=forking
#Type=dbus
#BusName=com.redhat.apache-httpd
EnvironmentFile=/etc/sysconfig/apache-httpd
#ExecStart=/opt/apache/sbin/httpd $OPTIONS -DFOREGROUND
ExecStart=/opt/apache/sbin/httpd $OPTIONS 
ExecReload=/opt/apache/sbin/httpd $OPTIONS -k graceful
ExecStop=/bin/kill -WINCH ${MAINPID}
# We want systemd to give httpd some time to finish gracefully, but still want
# it to kill httpd after TimeoutStopSec if something went wrong during the
# graceful stop. Normally, Systemd sends SIGTERM signal right after the
# ExecStop, which would kill httpd. We are sending useless SIGCONT here to give
# httpd time to finish.
KillSignal=SIGCONT
PrivateTmp=true
PIDFile=/var/opt/apache/run/httpd.pid

[Install]
WantedBy=multi-user.target

The original httpd.service was used as a template. Note the differences. For apache-httpd.service, we allow httpd to fork. The Reload command does not use a kill command. Instead, '-k graceful' is passed to httpd.  Note that we also refer to the percona-server.service which we will discuss later.

We enable apache-httpd.service using ‘sudo systemctl enable apache-httpd.service‘.  Again, use the status command of systemctl to check on the service.  If it isn’t started, try using ‘sudo systemctl start apache-httpd.service‘.  The ‘enable‘ command makes sure that the service is started at boot time while ‘start‘ simply runs the service.

We should see the following by checking the status (‘sudo systemctl status apache-httpd’) of our custom installation of Apache httpd:

apache-httpd.service - The Apache HTTP Server (akumubuild)
   Loaded: loaded (/usr/lib/systemd/system/apache-httpd.service; enabled)
   Active: active (running) since Thu 2014-04-03 00:44:31 EDT; 1 day 17h ago
 Main PID: 1942 (httpd)
   CGroup: /system.slice/apache-httpd.service
           ├─1942 /opt/apache/sbin/httpd
           ├─1998 /opt/apache/sbin/httpd
           ├─1999 /opt/apache/sbin/httpd
           ├─2048 /opt/apache/sbin/httpd
           ├─2049 /opt/apache/sbin/httpd
           ├─2050 /opt/apache/sbin/httpd
           └─3237 /opt/apache/sbin/httpd

Apr 03 00:44:30 akumu.hq.linuxunbound.com systemd[1]: PID file /var/opt/apache/run/httpd.pid not re...rt.
Apr 03 00:44:31 akumu.hq.linuxunbound.com systemd[1]: Started The Apache HTTP Server (akumubuild).
Hint: Some lines were ellipsized, use -l to show in full.

Some things to consider:

  • Make sure the file /etc/sysconfig/apache-httpd exists.  This doesn’t have to contain anything though you can add some optional parameters to httpd by assigning them to the shell variable OPTIONS.
  • The directories /var/opt/apache/logs and /var/opt/apache/run must exist.

Percona Server

The MySQL-compatible Percona Server should have the following configuration file in /usr/lib/systemd/system named percona-server.service:

[Unit]
Description=The Percona Server (MySQL)
# See https://bugzilla.redhat.com/show_bug.cgi?id=714426
After=network.target remote-fs.target nss-lookup.target
Before=apache-httpd.service

[Service]
#Type=notify
#Type=forking
#Type=dbus
Type=simple
EnvironmentFile=/etc/sysconfig/percona-server
ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --user=mysql $OPTIONS 
#ExecStop=/usr/local/mysql/bin/mysqladmin -u root -p shutdown
ExecStop=/bin/kill -TERM ${MAINPID}
ExecReload=/bin/kill -HUP ${MAINPID}

PrivateTmp=true
PIDFile=/var/run/mysqld/mysqld.pid

[Install]
WantedBy=multi-user.target

Again, we must make sure that certain files and directories exist:

  • the file /etc/sysconfig/percona-server
  • the directory /var/log/mysqld (or whatever is specified in /etc/my.cnf)
  • the directory /var/run/mysqld

Take note that /var/run/mysqld is a temporary directory that is created at boot time and deleted at shutdown.  We need to create a file called /etc/tmpfiles.d/percona.conf which contains the following:

d /run/mysqld 0755 mysql mysql -

This configuration file creates the directory /run/mysqld with mode 0755 and ownership by user ‘mysql‘ and group ‘mysql‘.

Enable the Percona Server service using systemctl as you did for Apache httpd.  Once it is running, you should see something like this status:

percona-server.service - The Percona Server (MySQL)
   Loaded: loaded (/usr/lib/systemd/system/percona-server.service; enabled)
   Active: active (running) since Thu 2014-04-03 00:44:28 EDT; 1 day 17h ago
 Main PID: 1842 (mysqld)
   CGroup: /system.slice/percona-server.service
           └─1842 /usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --user=mysql

Apr 03 00:44:28 akumu.hq.linuxunbound.com systemd[1]: Started The Percona Server (MySQL).

More information on systemd can be found on their wiki.

Tagged with: , , , , , , ,

Installing Fedora 20 As A Virtual Machine

We have installed Fedora 20 on a VMware virtual machine using the standard DVD image.  Below is a sequence of screenshots from the install.

First, we turn on the VM with the Fedora 20 DVD image attached to the virtual DVD device.  We then choose the Fedora Live boot sequence:

fedora-01

Once we have finished booting the Fedora Live image, we select “Install to Hard Drive”:

fedora-02

We then proceed through the installation dialog windows:

fedora-03

fedora-04

We then specify the fully qualified domain name (FQDN) for hostname.  Note that we usually do this for Red Hat derived distributions like CentOS and Fedora.

fedora-05

fedora-06

Here, we set the root password and create a user account:

fedora-07

Note that we appoint the user to be an administrator, causing the installation to add the user to the wheel group.  Note that the installation runs while you set the root password and create a user.

After the software installation is finished, we get the screen below:

fedora-08

It’s time to reboot….

The login screen show up and displays the username created earlier.  Click on this and the screen will prompt for the user’s password.

fedora-09

After logging in, the installation and configuration continues….

fedora-10

fedora-11

fedora-12

Once it’s ready to use, we can now use the operating system.

fedora-13

Below is a preview of the Gnome 3 shell.  Clicking on “Activities” brings up the screen below.  Note that there is a search box where you can type in the name of an application that you would want to run.

fedora-14

Here again is a typical session with a web browser (Firefox) running:

fedora-15

Let us now reboot.  The GRUB screen is seen below:

fedora-16

We log in as usual and go to settings in order to change networking parameters:

fedora-17

The networking configuration panel looks like this:

fedora-18

We specify new parameters…..

fedora-19

Here is a typical package update session using yum:

fedora-21

If you’re looking for the upcoming CentOS 7, it is still under development.  You can, however, sign up at Red Hat and try the Red Hat Enterprise Linux 7 Beta.  RHEL 7 Beta is based on latter versions of Fedora (i.e. Fedora 18, 19, 20).

Like Fedora 20, RHEL 7 Beta uses systemd in place of SysV init. It feels faster, though not necessarily optimally fast.  When creating start-up “scripts”, you need to learn how to write systemd configuration files which reside in /usr/lib/systemd.

We’ll talk about systemd in a future article.

Tagged with: , , , , ,

PHP 5.5.0 and Apache 2.4.4 on CentOS 6.4

In June of 2013, PHP 5.5.0 was released as suitable for production use.  Our internal site used Apache httpd and MediaWiki to test PHP 5.5.0.  Our OS was CentOS 6.4 (64-bit).

We compiled PHP 5.5.0 from scratch, with all the prerequisite packages downloaded and installed, using the following configuration:

#! /bin/sh
#
# Created by configure

'./configure' \
'--enable-intl' \
'--enable-cgi' \
'--with-apxs2=/opt/apache/bin/apxs' \
'--with-pear' \
'--with-libdir=lib64' \
'--with-curl=shared' \
'--with-openssl=shared' \
'--prefix=/opt/php5' \
'--with-gdbm=shared' \
'--enable-dba=shared' \
'--with-db4=shared' \
'--enable-ftp' \
'--with-gd=shared' \
'--with-imap=shared' \
'--with-kerberos=/usr' \
'--with-imap-ssl=shared' \
'--enable-sockets' \
'--enable-zip' \
'--with-jpeg-dir=/usr' \
'--with-png-dir=/usr' \
'--with-xpm-dir=/usr' \
'--with-zlib' \
'--with-zlib-dir=/usr' \
'--with-bz2=shared' \
'--enable-exif' \
'--enable-soap' \
'--with-gmp' \
'--with-mcrypt=/usr/local' \
'--with-mhash' \
'--enable-mbstring' \
'--with-mysql=mysqlnd' \
'--with-mysqli=mysqlnd' \
'--with-pdo-mysql=mysqlnd' \
'--with-snmp=shared' \
'--enable-wddx' \
'--enable-pcntl' \
'--with-xmlrpc=shared' \
'--with-xsl=shared' \
'--with-ldap=shared' \
'--with-ldap-sasl' \
'--with-libedit' \
'--with-readline' \
'--with-pgsql=/usr/local/pgsql/bin/pg_config' \
'--with-pdo-pgsql=/usr/local/pgsql/bin/pg_config' \
"$@"

The configuration above assumed the following:

Other packages which were required by PHP were installed from either the official CentOS yum repository or from each package’s respective official source.

The above configure script was saved as config-php.sh and placed above the PHP source directory.  The following commands were issued to start compiling and testing PHP:

cd php-5.5.0
../config-php.sh
make
make test

After the PHP tests were completed, the results were installed in /opt/php5:

sudo make install

In our setup, we used mod_fcgid to execute PHP scripts. See the previous article on installing PHP 5.4 for more information.

To verify that PHP is configured correctly, create a PHP script that contains the following:

<?php

phpinfo();

?>

The above script should generate something similar to this:
PHP Info

As you scroll down, you’ll see more information about the features of your particular PHP installation.

Remember to edit /opt/php/lib/php.ini to set certain variables properly. Here’s a sample php.ini file:

; Choose your preferred time zone and set it here
date.timezone = UTC

; Load extensions (see /opt/php5/lib/php/extensions)
; that you need.
extension = bz2.so
extension = curl.so
extension = dba.so
extension = gd.so
extension = imap.so
extension = ldap.so
extension = openssl.so
extension = snmp.so
extension = xmlrpc.so
extension = xsl.so

You should see information about these extensions in the phpinfo() output.

Tagged with: , , , ,
Top