<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Xi Group Ltd. Company Blog &#187; Xi Group Ltd. Company Blog &#187; supervisor</title>
	<atom:link href="http://blog.xi-group.com/tag/supervisor/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.xi-group.com</link>
	<description>High-quality DevOps Services</description>
	<lastBuildDate>Tue, 09 Jun 2015 11:38:46 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.2.2</generator>
	<item>
		<title>Small Tip: How to run non-deamon()-ized processes in the background with SupervisorD</title>
		<link>http://blog.xi-group.com/2014/06/small-tip-how-to-run-non-deamon-ized-processes-in-the-background-with-supervisord/</link>
		<comments>http://blog.xi-group.com/2014/06/small-tip-how-to-run-non-deamon-ized-processes-in-the-background-with-supervisord/#comments</comments>
		<pubDate>Thu, 26 Jun 2014 11:18:23 +0000</pubDate>
		<dc:creator><![CDATA[Ivo Vachkov]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Operations]]></category>
		<category><![CDATA[Small Tip]]></category>
		<category><![CDATA[background process]]></category>
		<category><![CDATA[daemon]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[long-running]]></category>
		<category><![CDATA[lts]]></category>
		<category><![CDATA[supervisor]]></category>
		<category><![CDATA[supervisord]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://blog.xi-group.com/?p=156</guid>
		<description><![CDATA[The following article will demonstrate how to use Ubuntu 14.04 LTS and SupervisorD to manage the not-so-uncommon case of long running services that expect to be running in active console / terminal. Those are usually quickly / badly written pieces of code that do not use daemon(), or equivalent function, to properly go into background [&#8230;]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;">The following article will demonstrate how to use Ubuntu 14.04 LTS and <a href="http://supervisord.org">SupervisorD</a> to manage the not-so-uncommon case of long running services that expect to be running in active console / terminal. Those are usually quickly / badly written pieces of code that do not use daemon(), or equivalent function, to properly go into background but instead run forever in the foreground. Over the years multiple solutions emerged, including quite the ugly ones (<strong>nohup &#8230; 2>&#038;1 logfile &#038;</strong>). Luckily, there is a better one, and it&#8217;s called SupervisorD. With Ubuntu 14.04 LTS it even comes as a package and it should be part of your DevOps arsenal of tools!</p>
<p style="text-align: justify;">In a typical Python / Web-scale environment multiple components will be implemented in a de-coupled, micro-services, REST-based architecture. One of the popular frameworks for REST is <a href="http://bottlepy.org">Bottle</a>. And there are multiple approaches to build services with Bottle when full-blown HTTP Server is available (Apache, NginX, etc.) or if performance matters. All of those are valid and somewhat documented. But still, there is the case (and it more common than one would think) when developer will create Bottle server to handle simple task and it will propagate into production, using ugly solution like <strong>Screen/TMUX</strong> or even <strong>nohup</strong>. Here is a way to put this under proper control.</p>
<p>Test Server code: test-server.py</p><pre class="crayon-plain-tag">#!/usr/bin/env python

# Description: Demo Bottle Server to demonstrate use of SupervisorD
#
# How to run:
#       test-server.py -c test-server.conf
#
# Exepects the following configuration file:
#
#       server:
#               bind_ip: 0.0.0.0
#               bind_port: 8080
#
#       configuration_variable: true
#

import argparse
import time
import yaml
import sys

from bottle import route, run, template

# GET: /
@route('/')
def index():
        static_page = """
<html>
<head>
        <title>Test Server</title>
</head>
<body>
        <center><h2>Test Server is working!</h2></center>
</body>
</html>
        """
        return static_page

# Return the server->bind_ip value from the parsed configuration
def get_bind_ip(config):
        if config:
                return config['server']['bind_ip']
        else:
                return None

# Return the server->bind_port value from the parsed configuation
def get_bind_port(config):
        if config:
                return config['server']['bind_port']
        else:
                return None

# Return sample configuration variable
def get_config_data(config):
        if config:
                return config['configuration_variable']
        else:
                return None

# Main entry point for the application
def main():
        """ Main Entry Point for the appliation """

        # Parse command line arguments
        parser = argparse.ArgumentParser(description='Demo Server using Bottle')
        parser.add_argument('-c', '--config', type=str, required=True, dest='config', help='Configuration File Location')

        args = parser.parse_args()
        conf_file = args.config

        # Check config file accessibility
        try:
                conf_fd = open(conf_file, 'r')
        except IOError as e:
                if e.errno == errno.EACCES or e.errno == errno.ENOENT:
                        print("{progname}: Unable to read the configuration file ({config})!".format(progname=sys.argv[0], config=conf_file))
                        sys.exit(1)
        else:
                with conf_fd:
                        config = yaml.load(conf_fd)
                        conf_fd.close()

        # Get configuration data
        bind_ip = get_bind_ip(config)
        bind_port = get_bind_port(config)

        if bind_ip == None or bind_port == None:
                print("{progname}: Required configuration variable is unavailable!".format(progname=sys.argv[0]))
                sys.exit(1)

        config_data = get_config_data(config)

        # Run the web-server
        if config_data == True:
                run(host=bind_ip, port=bind_port)

if __name__ == '__main__':
    main()</pre><p></p>
<p>Test server configuration file: test-server.conf</p><pre class="crayon-plain-tag"># Sample configuration file in YAML format for test-server.py

server:
    bind_ip: 0.0.0.0
    bind_port: 8080

configuration_variable: true</pre><p></p>
<p>Manual execution of the server code will looks like this:</p><pre class="crayon-plain-tag">ubuntu@ip-10-67-161-137:~/test-server$ ./test-server.py -c test-server.conf
Bottle v0.12.0 server starting up (using WSGIRefServer())...
Listening on http://0.0.0.0:8080/
Hit Ctrl-C to quit.

94.155.194.28 - - [23/Jun/2014 12:34:39] "GET / HTTP/1.1" 200 126
^C
ubuntu@ip-10-67-161-137:~/test-server$</pre><p></p>
<p style="text-align: justify;">When the controlling terminal is lost the server will be terminated. Obviously, this is neither acceptable, nor desirable behavior.</p>
<p>With SupervisorD (<strong>sudo aptitude install supervisor</strong>) the service can be properly managed using simple configuration file.</p>
<p>Example SupervisorD configuration file: /etc/supervisor/conf.d/test-server.conf</p><pre class="crayon-plain-tag">[program:test-server]
command=/home/ubuntu/test-server/test-server.py -c /home/ubuntu/test-server/test-server.conf
user=ubuntu
redirect_stderr=true</pre><p></p>
<p>To start the service, execute:</p><pre class="crayon-plain-tag">ubuntu@ip-10-67-161-137:~$ sudo supervisorctl start test-server
test-server: started
ubuntu@ip-10-67-161-137:~$</pre><p></p>
<p>To verify successful service start:</p><pre class="crayon-plain-tag">ubuntu@ip-10-67-161-137:~$ ps ax
. . . 
 4353 ?        Ss     0:00 /usr/bin/python /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
 4355 ?        S      0:00 python /home/ubuntu/test-server/test-server.py -c /home/ubuntu/test-server/test-server.conf
. . .
ubuntu@ip-10-67-161-137:~$</pre><p></p>
<p>SupervisorD will redirect stdout and stderr to properly named log files:</p><pre class="crayon-plain-tag">ubuntu@ip-10-67-161-137:~$ sudo cat /var/log/supervisor/test-server-stdout---supervisor-ssaGXP.log
Bottle v0.12.0 server starting up (using WSGIRefServer())...
Listening on http://0.0.0.0:8080/
Hit Ctrl-C to quit.

94.155.194.28 - - [23/Jun/2014 13:31:19] "GET / HTTP/1.1" 200 126
ubuntu@ip-10-67-161-137:~$</pre><p>Those log files can be integrated with a centralized logging architecture or processed for error / anomaly detection separately.</p>
<p>SupervisorD also comes with handy, command-line control utility, <strong>supervisorctl</strong>:</p><pre class="crayon-plain-tag">ubuntu@ip-10-67-161-137:~$ sudo supervisorctl status test-server
test-server                      RUNNING    pid 4355, uptime 0:11:40
ubuntu@ip-10-67-161-137:~$</pre><p></p>
<p style="text-align: justify;">With some additional effort SupervisorD can react to various types of events (<a href="http://supervisord.org/events.html">http://supervisord.org/events.html</a>) which bring it one step closer to full process monitoring &#038; notification solution!</p>
<p>References</p>
<ul>
<li>SupervisorD Homepage: <a href="http://supervisord.org">http://supervisord.org</a></li>
<li>Bottle Web Framework: <a href="http://bottlepy.org/docs/dev/index.html">http://bottlepy.org/docs/dev/index.html</a></li>
</ul>
<div class="rpbt_shortcode">
<h3>Related Posts</h3>
<ul>
					
			<li><a href="http://blog.xi-group.com/2014/11/small-tip-how-to-use-block-device-mappings-to-manage-instance-volumes-with-aws-cli/">Small Tip: How to use &#8211;block-device-mappings to manage instance volumes with AWS CLI</a></li>
					
			<li><a href="http://blog.xi-group.com/2014/07/small-tip-aws-announces-t2-instance-types/">Small Tip: AWS announces T2 instance types</a></li>
					
			<li><a href="http://blog.xi-group.com/2014/07/devops-shell-script-template/">DevOps Shell Script Template</a></li>
					
			<li><a href="http://blog.xi-group.com/2015/02/how-to-deploy-single-node-hadoop-setup-in-aws/">How to deploy single-node Hadoop setup in AWS</a></li>
					
			<li><a href="http://blog.xi-group.com/2015/01/userdata-teplate-for-ubuntu-14-04-ec2-instances-in-aws/">UserData Template for Ubuntu 14.04 EC2 Instances in AWS</a></li>
			</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.xi-group.com/2014/06/small-tip-how-to-run-non-deamon-ized-processes-in-the-background-with-supervisord/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
