<?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>Another Geek Blog &#187; djb</title>
	<atom:link href="http://geek.linuxman.pro.br/tag/djb/feed" rel="self" type="application/rss+xml" />
	<link>http://geek.linuxman.pro.br</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Fri, 16 Dec 2011 01:55:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Não reinvente a roda você também</title>
		<link>http://geek.linuxman.pro.br/geek/nao-reinvente-a-roda-voce-tambem</link>
		<comments>http://geek.linuxman.pro.br/geek/nao-reinvente-a-roda-voce-tambem#comments</comments>
		<pubDate>Wed, 01 Jul 2009 02:01:06 +0000</pubDate>
		<dc:creator>Eri</dc:creator>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[Geek]]></category>
		<category><![CDATA[daemontools]]></category>
		<category><![CDATA[djb]]></category>
		<category><![CDATA[FollowUpTime]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://geek.linuxman.pro.br/?p=1152</guid>
		<description><![CDATA[Preâmbulo: Recentemente coloquei no ar o FollowUpTime, que como já disse em outros posts é um sistema de monitoração para redes e servidores. Como podem imaginar, um bocado de linhas de código está envolvida num sistema assim e a conta só do engine principal passa das 90 mil linhas. Isso sem incluir templates, javascripts, etc. [...]]]></description>
			<content:encoded><![CDATA[<h2>Preâmbulo:</h2>
<p>Recentemente coloquei no ar o <a href="http://www.followuptime.com">FollowUpTime</a>, que como já disse em outros posts é um sistema de monitoração para redes e servidores.</p>
<p>Como podem imaginar, um bocado de linhas de código está envolvida num sistema assim e a conta só do engine principal passa das 90 mil linhas. Isso sem incluir templates, javascripts, etc.</p>
<p>O sistema é composto de duas partes: Uma que roda num servidor principal gerenciando a maior parte das tarefas e as &#8220;probes&#8221;. As probes são pequenos scripts que recebem instruções sobre hosts a serem testados e respondem para o servidor principal com o tempo de resposta, um OK ou um FAIL. Simples assim.</p>
<p>São essas probes que temos espalhados por vários cantos do planeta.</p>
<p>Porém quando recebi a probe dos desenvolvedores me vi com um pequeno, mas incoveniente problema. Os desenvolvedores realmente optaram pelo <a href="http://en.wikipedia.org/wiki/KISS_principle">princípio KISS</a>. Eles me entregaram uma excelente probe que fazia o que era necessário. E nada mais. Eu tinha nas mãos um daemon que rodava em foreground e jogava mensagens para stdout e stderr e nada mais.</p>
<p>Eu não me demorei e ataquei o problema da forma errada, pensando como um programador e não como um administrador Unix. E acabei reinventado a roda.</p>
<h2>Introdução &#8211; O problema</h2>
<p>Quando percebi o que eu tinha nas mãos logo pensei nos problemas que eu precisava resolver:</p>
<ul>
<li>Preciso iniciar o daemon sempre que der boot na máquina</li>
<li>Preciso ser capaz de rodar em daemon em background, ou vai me zoar a seqüencia de boot</li>
<li>Posso precisar parar/reiniciar/iniciar manualmente este daemon</li>
<li>Se o processo morrer eu tenho que ser notificado e que, de preferência, ele seja reiniciado automaticamente</li>
<li>E sim, esse processo não deve rodar como root</li>
</ul>
<p>Já velhaco de Linux logo pensei num script para ser colocado em /etc/init.d/ que ia resolver boa parte dos meus problemas. Com uma combinação bonita de bash scripting, várias ferramentas e comandos Linux que só se conhece depois de muito tempo de casa (como nohup, pidof, &amp;) e gambiarras na crontab eu consegui. Consegui reinventar a roda. Não vou entrar em detalhes da solução que fiz, pois apesar de 100% funcional não era nem de perto tão bonita quanto:</p>
<h2>A solução &#8211; Daemontools</h2>
<p>Nosso caro amigo <a href="http://cr.yp.to/">D.J.B</a>, autor do famoso Qmail também já passou por um problema parecido com o meu, mas ao invés de criar um solução simples para resolver um problema pontual ele foi mais longe. Ele criou uma solução global que atende o problema dele, o meu e provavelmente também o seu.</p>
<p>Na <a href="http://cr.yp.to/daemontools.html">página oficial do daemontools</a> tem uma tabela, que traduzo abaixo, comparando a ferramenta dele com outras abordagens (incluindo a minha, que utilizava init.d):</p>
<table border="0" cellspacing="0" frame="void" rules="none">
<colgroup>
<col width="242"></col>
<col width="86"></col>
<col width="86"></col>
<col width="86"></col>
<col width="86"></col>
<col width="86"></col>
</colgroup>
<tbody>
<tr>
<td style="border-left: 1px solid #000000;" width="242" height="18" align="center" bgcolor="#2300dc"><strong><em><span style="font-family: Verdana; color: #ffffff;">Funcionalidade</span></em></strong></td>
<td width="86" align="center" bgcolor="#2300dc"><strong><em><span style="font-family: Verdana; color: #ffffff;">inittab</span></em></strong></td>
<td width="86" align="center" bgcolor="#2300dc"><strong><em><span style="font-family: Verdana; color: #ffffff;">ttys</span></em></strong></td>
<td width="86" align="center" bgcolor="#2300dc"><strong><em><span style="font-family: Verdana; color: #ffffff;">init.d</span></em></strong></td>
<td width="86" align="center" bgcolor="#2300dc"><strong><em><span style="font-family: Verdana; color: #ffffff;">rc.local</span></em></strong></td>
<td style="border-right: 1px solid #000000;" width="86" align="center" bgcolor="#2300dc"><strong><em><span style="font-family: Verdana; color: #ffffff;">/service</span></em></strong></td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="34" align="left"><strong><span style="font-family: Verdana;">Fácil instalação e remoção de serviços</span></strong></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Sim</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Sim</span></td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="18" align="left"><strong><span style="font-family: Verdana;">Simples startup inicial</span></strong></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Sim</span></td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="18" align="left"><strong><span style="font-family: Verdana;">Reinicializações confiáveis</span></strong></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Sim</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Sim</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Sim</span></td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="18" align="left"><strong><span style="font-family: Verdana;">Sinalização simples e confiável</span></strong></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Sim</span></td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="18" align="left"><strong><span style="font-family: Verdana;">Estado de processo limpo</span></strong></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Sim</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Sim</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Sim</span></td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="18" align="left"><strong><span style="font-family: Verdana;">Portabilidade</span></strong></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Não</span></td>
<td style="border: 1px solid #000000;" align="center"><span style="font-family: Verdana;">Sim</span></td>
</tr>
</tbody>
</table>
<p>Dá para perceber que o cara pensou em tudo e não tem porquê reinventar a roda. Vamos utilizar o daemontools!</p>
<h2>Instalando o Daemontools no Debian 5.0 (Lenny):</h2>
<p>Quem já instalou o daemontools no Debian no passado lembra que pentelhação que era, pois devido a licenciamento era apenas um pseudo-pacote que roda um script para realmente baixar/instalar o daemontools. Isso foi resolvido quando o D.J.B mudou a licença e agora o pacote é um .deb &#8220;de primeira linha&#8221;.</p>
<pre># apt-get install daemontools daemontools-run</pre>
<p>Pronto. Só isso. Próximo passo&#8230;</p>
<h2>Criando um serviço</h2>
<p>Para fins didáticos vamos criar um serviço simples, chamado homer.sh cujo conteúdo é:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #007800;">progname</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">basename</span> <span style="color: #007800;">$0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #007800;">LOG</span>=<span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$progname</span>.log
<span style="color: #007800;">AVISO</span>=<span style="color: #ff0000;">&quot;Hummm... rosquinha...&quot;</span>
<span style="color: #007800;">SONECA</span>=<span style="color: #000000;">2</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">date</span><span style="color: #000000; font-weight: bold;">`</span>: <span style="color: #ff0000;">&quot;starting <span style="color: #007800;">$progname</span>...&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;&gt;</span> <span style="color: #007800;">$LOG</span>
<span style="color: #000000; font-weight: bold;">while</span> <span style="color: #c20cb9; font-weight: bold;">true</span>
<span style="color: #000000; font-weight: bold;">do</span>
    <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">date</span><span style="color: #000000; font-weight: bold;">`</span>: <span style="color: #ff0000;">&quot;<span style="color: #007800;">$progname</span>: <span style="color: #007800;">$AVISO</span>&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;&gt;</span> <span style="color: #007800;">$LOG</span>
    <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">date</span><span style="color: #000000; font-weight: bold;">`</span>: <span style="color: #ff0000;">&quot;<span style="color: #007800;">$progname</span>: tirando uma soneca de <span style="color: #007800;">$SONECA</span> segundos...&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;&gt;</span> <span style="color: #007800;">$LOG</span>
    <span style="color: #c20cb9; font-weight: bold;">sleep</span> <span style="color: #007800;">$SONECA</span>
<span style="color: #000000; font-weight: bold;">done</span></pre></div></div>

<p>Não faz muito, mas funciona. E tem exatamente as mesmas características do meu serviço da probe, inclusive rodando em foregroud. E agora? Como &#8220;daemonizar&#8221; isso atendendo todos aqueles meus requisitos iniciais?</p>
<h2>Juntando no daemontools</h2>
<p>Crie um diretório qualquer onde vai guardar seus serviços de forma organizada. Recomendo algo como /opt/services por exemplo. Lá vamos criar um subdiretório homer e moveremos nosso script para lá:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># mkdir -p /opt/services/homer</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># mv homer.sh /opt/services/homer/</span></pre></div></div>

<p>Para controlar a inicialização dele precisamos de um script dentro do mesmo diretório chamado run. Simples assim:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #7a0874; font-weight: bold;">exec</span> .<span style="color: #000000; font-weight: bold;">/</span>homer.sh</pre></div></div>

<p>E estamos 50% prontos. Não esqueça que tanto o homer.sh como o run precisam ser executáveis!</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># chmod 755 /opt/services/homer/*</span></pre></div></div>

<p>Agora para ativar o serviço vem a parte realmente fácil:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># ln -s /opt/services/homer /etc/service/</span></pre></div></div>

<p>Conte até 5 e dê um ps auxw no prompt. Sim&#8230; o seu serviço está no ar.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># ps aux|grep homer</span>
root      <span style="color: #000000;">3250</span>  <span style="color: #000000;">0.0</span>  <span style="color: #000000;">0.1</span>   <span style="color: #000000;">1620</span>   <span style="color: #000000;">324</span> ?        S    <span style="color: #000000;">19</span>:<span style="color: #000000;">28</span>   <span style="color: #000000;">0</span>:00 supervise homer
root      <span style="color: #000000;">3450</span>  <span style="color: #000000;">1.2</span>  <span style="color: #000000;">0.4</span>   <span style="color: #000000;">2792</span>  <span style="color: #000000;">1220</span> ?        S    <span style="color: #000000;">19</span>:<span style="color: #000000;">31</span>   <span style="color: #000000;">0</span>:00 <span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">bash</span> <span style="color: #000000; font-weight: bold;">/</span>opt<span style="color: #000000; font-weight: bold;">/</span>services<span style="color: #000000; font-weight: bold;">/</span>homer<span style="color: #000000; font-weight: bold;">/</span>homer.sh</pre></div></div>

<p>Observem que além do serviço ainda existe um supervisor que manterá os olhos nele e, caso o mesmo morra, será automaticamente reiniciado. Observem que o PID do processo é 3450, certo?</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># kill -9 3450</span>
<span style="color: #666666; font-style: italic;"># ps aux|grep homer</span>
root      <span style="color: #000000;">3250</span>  <span style="color: #000000;">0.0</span>  <span style="color: #000000;">0.1</span>   <span style="color: #000000;">1620</span>   <span style="color: #000000;">324</span> ?        S    <span style="color: #000000;">19</span>:<span style="color: #000000;">28</span>   <span style="color: #000000;">0</span>:00 supervise homer
root      <span style="color: #000000;">3660</span>  <span style="color: #000000;">8.0</span>  <span style="color: #000000;">0.4</span>   <span style="color: #000000;">2788</span>  <span style="color: #000000;">1212</span> ?        S    <span style="color: #000000;">19</span>:<span style="color: #000000;">33</span>   <span style="color: #000000;">0</span>:00 <span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">bash</span> <span style="color: #000000; font-weight: bold;">/</span>opt<span style="color: #000000; font-weight: bold;">/</span>services<span style="color: #000000; font-weight: bold;">/</span>homer<span style="color: #000000; font-weight: bold;">/</span>homer.sh</pre></div></div>

<p>Menos de um segundo depois de matar o processo um novo (3660) já assume o lugar. Pra que mesmo que perdi todo aquele tempo desenvolvendo um script de inicialização e depois com outro que ficava vendo se o processo estava vivo?</p>
<h2>Indo mais adiante</h2>
<p>OK, mas um dos requisitos também era rodar o processo como usuário não privilegiado, certo? E, como podem ver ali em cima, tá rodando como root. Vamos modificar um pouco nosso serviço então, criando um usuário, mudando as permissões do arquivo de log e editando o run:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># useradd  -s /bin/false -d /dev/null simpson</span>
<span style="color: #666666; font-style: italic;"># chown simpson:simpson /tmp/homer.sh.log</span></pre></div></div>

<p>E agora o conteúdo do /opt/services/homer/run passa a ser:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #7a0874; font-weight: bold;">exec</span> setuidgid simpson .<span style="color: #000000; font-weight: bold;">/</span>homer.sh</pre></div></div>

<p>Feito. Vamos reiniciar o processo:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># svc -t /etc/service/homer</span>
<span style="color: #666666; font-style: italic;"># ps aux|grep homer</span>
root      <span style="color: #000000;">3250</span>  <span style="color: #000000;">0.0</span>  <span style="color: #000000;">0.1</span>   <span style="color: #000000;">1620</span>   <span style="color: #000000;">324</span> ?        S    <span style="color: #000000;">19</span>:<span style="color: #000000;">28</span>   <span style="color: #000000;">0</span>:00 supervise homer
simpson   <span style="color: #000000;">4004</span>  <span style="color: #000000;">1.0</span>  <span style="color: #000000;">0.5</span>   <span style="color: #000000;">3304</span>  <span style="color: #000000;">1484</span> ?        S    <span style="color: #000000;">19</span>:<span style="color: #000000;">39</span>   <span style="color: #000000;">0</span>:02 <span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">bash</span> .<span style="color: #000000; font-weight: bold;">/</span>homer.sh</pre></div></div>

<p>Olha que coisa linda. Tudo que precisamos fazer foi falar pro daemontools: Executa esse cara usando esse id aqui. E pronto.</p>
<h2>Comandos que você precisa saber:</h2>
<h3>Parar um serviço:</h3>
<pre># svc -d /etc/service/serviço</pre>
<h3>Reiniciar um serviço parado manualmente:</h3>
<pre># svc -u /etc/service/serviço</pre>
<h3>Enviando um sinal TERM (comportamento equivalente a restart):</h3>
<pre># svc -t /etc/service/serviço</pre>
<h3>Colocando um serviço em pausa:</h3>
<pre># svc -p /etc/service/serviço</pre>
<h3>Continuando um serviço pausado:</h3>
<pre># svc -c /etc/service/serviço</pre>
<h2>Ainda mais</h2>
<p>Tem muito mais que pode ser feito em cima do daemontools, combinando com ferramentas como multilog e ucspi-tcp. Dê uma olhada na página<a href="http://thedjbway.org/"> the djb way</a>, que foi <span style="text-decoration: line-through;">ostensivamente copiada</span> extensivamente utilizada como referência para este artigo.</p>
<p>E não vamos esquecer do jabá: Conheça o <a href="http://www.followuptime.com">FollowUpTime</a>! Em 5 minutos ou menos você pode se cadastrar e monitorar um site ou serviço gratuitamente!</p>

	Tags: <a href="http://geek.linuxman.pro.br/tag/daemontools" title="daemontools" rel="tag">daemontools</a>, <a href="http://geek.linuxman.pro.br/tag/djb" title="djb" rel="tag">djb</a>, <a href="http://geek.linuxman.pro.br/tag/followuptime" title="FollowUpTime" rel="tag">FollowUpTime</a>, <a href="http://geek.linuxman.pro.br/tag/linux" title="linux" rel="tag">linux</a>, <a href="http://geek.linuxman.pro.br/tag/sysadmin" title="sysadmin" rel="tag">sysadmin</a>, <a href="http://geek.linuxman.pro.br/tag/unix" title="unix" rel="tag">unix</a><br />
]]></content:encoded>
			<wfw:commentRss>http://geek.linuxman.pro.br/geek/nao-reinvente-a-roda-voce-tambem/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

