{"id":11564,"date":"2025-08-18T01:02:00","date_gmt":"2025-08-18T05:02:00","guid":{"rendered":"https:\/\/www.both.org\/?p=11564"},"modified":"2025-08-17T11:32:44","modified_gmt":"2025-08-17T15:32:44","slug":"manage-multiple-service-instances-with-systemctl","status":"publish","type":"post","link":"https:\/\/www.both.org\/?p=11564","title":{"rendered":"Manage multiple service instances with systemctl"},"content":{"rendered":"<div class=\"pld-like-dislike-wrap pld-template-1\">\r\n    <div class=\"pld-like-wrap  pld-common-wrap\">\r\n    <a href=\"javascript:void(0)\" class=\"pld-like-trigger pld-like-dislike-trigger  \" title=\"\" data-post-id=\"11564\" data-trigger-type=\"like\" data-restriction=\"cookie\" data-already-liked=\"0\">\r\n                        <i class=\"fas fa-thumbs-up\"><\/i>\r\n                <\/a>\r\n    <span class=\"pld-like-count-wrap pld-count-wrap\">2    <\/span>\r\n<\/div><\/div>\n<p>Services, services, services. A service is a huge part of computing. You&#8217;re reading this article on a service. Your computer is running services. The internet is filled with them.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">About systemctl<\/h2>\n\n\n\n<p>On Linux, the standard way of running and managing services is through the systemd utility and the command systemctl. Its usage is fairly simple: you just need to know the name of the service you want to manage, then you can use this command to start or stop the service, check its status, or do other functions:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># systemctl start httpd<br><br># systemctl stop httpd<br><br># systemctl status httpd<br><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Unit files<\/h2>\n\n\n\n<p>A service is defined in a file called a unit file. They are generally located in the directory \/usr\/lib\/systemd\/system. Here&#8217;s a sample list:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># ls \/usr\/lib\/systemd\/system<br> auditd.service                multi-user.target                    sys-kernel-debug.mount<br> autovt@.service               multi-user.target.wants              sys-kernel-tracing.mount<br> basic.target                  NetworkManager-dispatcher.service    syslog.socket<br> basic.target.wants            NetworkManager.service               syslog.target.wants<br> blk-availability.service      NetworkManager-wait-online.service<\/pre>\n\n\n\n<p>Sometimes you need to run more than one instance of a service on a single host. For example, if you are maintaining websites for several clients, security regulations demand that each client has its own individual instance. This means you need to run a new Apache HTTP service for each, but having a lot of services can be tough to manage. If you have 10 different customers, you would have to create 10 separate unit files to manage them. Fortunately, there is a better way to handle multiple instances of a service.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The @ symbol<\/h2>\n\n\n\n<p>Notice that some of the unit files have an <strong>@<\/strong> symbol in their name. This symbol has an interesting significance. As a matter of fact, after installing Apache HTTP Server, you may notice several service unit files, including one that has the <strong>@<\/strong> symbol in its name\u2014httpd@.service.<\/p>\n\n\n\n<p>I will show you how this can make a system administrator&#8217;s life a little easier, using the Apache HTTP Server for this example:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># dnf -y install httpd<br><br># cd \/usr\/lib\/systemd\/system<br># ls -d http*<br>httpd.service  httpd@.service  httpd.service.d  httpd.socket  httpd.socket.d<\/pre>\n\n\n\n<p>The <strong>@<\/strong> symbol indicates that a substitution will be made. systemd will take whatever you type after it and replace the variable <strong>%i<\/strong> inside the service unit file. The variable can be seen in this excerpt of the httpd@.service file:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[Unit]<br>Description=The Apache HTTP Server<br>After=network.target remote-fs.target nss-lookup.target<br>Documentation=man:httpd@.service(8)<br><br>[Service]<br>Type=notify<br>Environment=LANG=C<br>Environment=HTTPD_INSTANCE=%i<br>ExecStartPre=\/bin\/mkdir -m 710 -p \/run\/httpd\/instance-%i<br>ExecStartPre=\/bin\/chown root.apache \/run\/httpd\/instance-%i<br>ExecStartPre=\/bin\/mkdir -m 700 -p \/var\/lib\/httpd\/instance-%i<br>ExecStartPre=\/bin\/chown apache.apache \/var\/lib\/httpd\/instance-%i<br>ExecStart=\/usr\/sbin\/httpd $OPTIONS -DFOREGROUND -f conf\/%i.conf<br>ExecReload=\/usr\/sbin\/httpd $OPTIONS -k graceful -f conf\/%i.conf<\/pre>\n\n\n\n<p>Note that the default httpd unit file, httpd.service, does not have the @ symbol in its name and looks different. It is used for a single basic default instance of the Apache HTTP server.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Run multiple instances<\/h2>\n\n\n\n<p>To run multiple instances using this special unit file, each one needs a unique name. Suppose you have two clients, The Little Bank and The Big Bank. Name the instances <em>littlebank<\/em> and <em>bigbank<\/em>. To manage one, just append its name after the <strong>@<\/strong> symbol. Start each instance with the appropriate command:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>littlebank<\/strong>: systemctl start httpd@littlebank<\/li>\n\n\n\n<li><strong>bigbank<\/strong>: systemctl start httpd@bigbank<\/li>\n<\/ul>\n\n\n\n<p>Keep in mind that most services need certain configurations to avoid conflicts between different instances. I will not cover all of them here, but Apache needs several things, including unique listen port numbers, PID files, and document roots.<\/p>\n\n\n\n<p>I&#8217;ll demonstrate by trying to start the littlebank instance. I expect it to fail, but it will provide a useful status message:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># systemctl start httpd@littlebank<br><br># systemctl status httpd@littlebank<br>\u25cf httpd@littlebank.service - The Apache HTTP Server<br>     Loaded: loaded (\/usr\/lib\/systemd\/system\/httpd@.service; disabled; vendor preset: disabled)<br>     Active: failed (Result: exit-code) since Tue 2020-11-10 11:41:20 EST; 1min 58s ago<br>       Docs: man:httpd@.service(8)<br>    Process: 2205 ExecStartPre=\/bin\/mkdir -m 710 -p \/run\/httpd\/instance-littlebank (code=exited, status=0\/SUCCESS)<br>    Process: 2207 ExecStartPre=\/bin\/chown root.apache \/run\/httpd\/instance-littlebank (code=exited, status=0\/SUCCESS)<br>    Process: 2208 ExecStartPre=\/bin\/mkdir -m 700 -p \/var\/lib\/httpd\/instance-littlebank (code=exited, status=0\/SUCCESS)<br>    Process: 2209 ExecStartPre=\/bin\/chown apache.apache \/var\/lib\/httpd\/instance-littlebank (code=exited, status=0\/SUCCESS)<br>    Process: 2210 ExecStart=\/usr\/sbin\/httpd $OPTIONS -DFOREGROUND -f conf\/littlebank.conf (code=exited, status=1\/FAILURE)<br>   Main PID: 2210 (code=exited, status=1\/FAILURE)<br>        CPU: 26ms<br><br>Nov 10 11:41:20 localhost.localdomain systemd[1]: Starting The Apache HTTP Server...<br>Nov 10 11:41:20 localhost.localdomain httpd[2210]: httpd: Could not open configuration file \/etc\/httpd\/conf\/littlebank.conf&gt;<br>Nov 10 11:41:20 localhost.localdomain systemd[1]: httpd@littlebank.service: Main process exited, code=exited, status=1\/FAIL&gt;<br>Nov 10 11:41:20 localhost.localdomain systemd[1]: httpd@littlebank.service: Failed with result 'exit-code'.<br>Nov 10 11:41:20 localhost.localdomain systemd[1]: Failed to start The Apache HTTP Server.<\/pre>\n\n\n\n<p>You can see that systemd correctly substitutes the instance name in place of the <strong>%i<\/strong> variable in the unit file. However, Apache fails to start because it could not open a configuration file. So, now I&#8217;ll set up the instances to include creating the necessary configuration files (<em>littlebank.conf<\/em> and <em>bigbank.conf<\/em>) in \/etc\/httpd\/conf\/:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># ls \/etc\/httpd\/conf<br>bigbank.conf  httpd.conf  littlebank.conf<\/pre>\n\n\n\n<p>Now you can manage each instance with <strong>systemctl<\/strong>. Issue <strong>start<\/strong> and <strong>status<\/strong> commands to each. I&#8217;ve shortened the output to the most relevant details:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># systemctl start httpd@bigbank<br># systemctl start httpd@littlebank<br><br># systemctl status httpd@bigbank<br>\u25cf httpd@bigbank.service - The Apache HTTP Server<br>     Loaded: loaded (\/usr\/lib\/systemd\/system\/httpd@.service; disabled; vendor preset: disabled)<br>     Active: active (running) since Tue 2020-11-10 12:26:06 EST; 56min ago<br>     <br># systemctl status httpd@littlebank<br>\u25cf httpd@littlebank.service - The Apache HTTP Server<br>     Loaded: loaded (\/usr\/lib\/systemd\/system\/httpd@.service; disabled; vendor preset: disabled)<br>     Active: active (running) since Tue 2020-11-10 12:25:58 EST; 55min ago<\/pre>\n\n\n\n<p>Here is the process view of these instances. There is more than one because Apache is forking server processes, which it normally does:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"># pgrep -a httpd<br>2834 \/usr\/sbin\/httpd -DFOREGROUND -f conf\/littlebank.conf<br>2835 \/usr\/sbin\/httpd -DFOREGROUND -f conf\/littlebank.conf<br>2836 \/usr\/sbin\/httpd -DFOREGROUND -f conf\/littlebank.conf<br>3061 \/usr\/sbin\/httpd -DFOREGROUND -f conf\/bigbank.conf<br>3062 \/usr\/sbin\/httpd -DFOREGROUND -f conf\/bigbank.conf<br>3064 \/usr\/sbin\/httpd -DFOREGROUND -f conf\/bigbank.conf<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Put it to use<\/h2>\n\n\n\n<p>This small systemd feature is very useful when you need many instances of a service. I hope you will be able to put it to good use in your work.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>2 Services, services, services. A service is a huge part of computing. You&rsquo;re reading this article on a<\/p>\n","protected":false},"author":429,"featured_media":11572,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"no","_lmt_disable":"","footnotes":""},"categories":[482,100,5,89,160],"tags":[259,269,242],"class_list":["post-11564","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-advanced","category-command-line","category-linux","category-system-administration","category-systemd","tag-httpd","tag-service-unit","tag-systemctl"],"modified_by":"David Both","_links":{"self":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/11564","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/users\/429"}],"replies":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11564"}],"version-history":[{"count":4,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/11564\/revisions"}],"predecessor-version":[{"id":11576,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/posts\/11564\/revisions\/11576"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=\/wp\/v2\/media\/11572"}],"wp:attachment":[{"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11564"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11564"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.both.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11564"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}