[译] runit 快速入门

JerriVAUO 8年前
   <p>译自: <a href="/misc/goto?guid=4959676959090217955" rel="nofollow,noindex">runit quick start</a></p>    <h3>概要</h3>    <p>通过这篇教程,我们可以快速了解runit并搭建起相应服务。</p>    <p>runit是一个用于服务监控的UNIX软件,它提供以下两种服务:</p>    <ul>     <li> <p>当服务器启动的时候启动定义好的服务。</p> </li>     <li> <p>监控运行的服务,当服务发生意外中断的时候,自动重启服务。</p> </li>    </ul>    <p>这篇教程将通过一个简单的示例来讲解如何创建新的runit服务。如果你想了解更多信息,可以查看runit的 <a href="/misc/goto?guid=4958861610754520200" rel="nofollow,noindex">官方文档</a> 。</p>    <p>本篇教程包括以下三部分:</p>    <ol>     <li> <p>创建一个runit模板</p> </li>     <li> <p>创建第一个服务</p> </li>     <li> <p>如何自动管理服务</p> </li>    </ol>    <h3>搭建环境</h3>    <p>首先确保系统安装了runit,大多数Linux版本的软件仓库里都包哈了runit包。例如,如果你的系统是基于Debian的,则可以使用下面的命令进行安装:</p>    <pre>  <code class="language-bash"># apt-get install runit</code></pre>    <p>如果是centos,则可以使用yum进行安装,但是默认情况下centos软件仓库里并没有runit,所以需要先配置相应的仓库:</p>    <pre>  <code class="language-bash"># curl -s https://packagecloud.io/install/repositories/imeyer/runit/script.rpm.sh | sudo bash  # sudo yum install runit-2.1.1-7.el7.centos.x86_64</code></pre>    <p>运行以下命令来检查是否已经安装了runit并且系统已经运行了runit。</p>    <pre>  <code class="language-bash"># ps -ef | grep runsvdir</code></pre>    <p>输出结果如下:</p>    <pre>  <code class="language-bash">root  2783   1  0 15:34 ? 00:00:00 runsvdir -P /etc/service log:</code></pre>    <p>runsvdir其实是一套组件,这些组件可以满足用户的各种需求,核心组件包括了runsvdir,runsv, chpst,svlogd以及sv。</p>    <h3>创建模板</h3>    <p>注意输出结果中的 runsvdir -P /etc/service log:....... , 它的意思是runsvdir会监控 /etc/service/ 目录下的文件,这些文件用于配置被监控的服务。</p>    <p>被监控的服务是通过在 /etc/service 目录下创建子目录,并添加可执行脚本run来实现的。</p>    <p>当runsvdir发现新的配置文件时,它就会自动启动一个runsv进程来管理这个配置的服务。</p>    <p>runit的设计思想就是每个组件的功能是完全独立的,以便管理。可以使用 man 命令查看具体组件的用法:</p>    <pre>  <code class="language-bash"># man runsvdir</code></pre>    <p>确保存在 /etc/service ,如果不存在,则使用mkdir创建相应目录:</p>    <pre>  <code class="language-bash"># mkdir /etc/service</code></pre>    <p>为了便于开发与测试,这里我们不直接在 /etc/service/ 目录中添加配置文件,而是创建一个暂存的目录来放置配置文件。</p>    <p>当我们满意自己的测试之后,再使用软链接,将暂存目录链接到 /etc/service 。</p>    <p>创建 /etc/runit 作为暂存目录。</p>    <pre>  <code class="language-bash"># mkdir  /etc/runit</code></pre>    <p>在创建一个真正的runit服务之前,我们先创建一个模板。这个模板将展示runit的基本用法,以后可以直接使用这个模板创建新的服务。</p>    <p>首先创建template目录:</p>    <pre>  <code class="language-bash"># mkdir /etc/runit/template</code></pre>    <p>接下来,创建run脚本:</p>    <pre>  <code class="language-bash">#!/bin/sh -e  exec 2>&1  exec chpst -u USER COMMAND</code></pre>    <p>给run添加可执行权限:</p>    <pre>  <code class="language-bash"># chmod +x /etc/runit/template/run</code></pre>    <p>这个脚本首先将标准错误输出流输出到标准输出流,然后执行chpst命令。chpst命令用来指定使用哪个用户执行命令。由于run脚本默认被root用户执行,通过chpst可以将run配置为普通用户来执行。通过man命令可以查看chpst的更多信息。</p>    <pre>  <code class="language-bash"># man chpst</code></pre>    <p>当runsvdir检查到 /etc/service 目录下包含一个新的目录时,runsvdir会启动一个runsv进程来执行和监控run脚本。通过man命令查看runsv的更多信息:</p>    <pre>  <code class="language-bash">#man runsv</code></pre>    <p>你可能注意runsv还可以监控日志服务,日志在应用中非常的重要。下面创建一个日志模板。</p>    <p>首先创建log目录:</p>    <pre>  <code class="language-bash"># mkdir /etc/runit/template/log</code></pre>    <p>然后创建run脚本:</p>    <pre>  <code class="language-bash">#!/bin/sh  exec chpst -u USER svlogd -tt LOGDIR</code></pre>    <p>给run脚本添加可执行权限:</p>    <pre>  <code class="language-bash"># chmod +x /etc/runit/template/log/run</code></pre>    <p>上面的脚本使用chpst启动一个svlogd守护进程,该进程将日志信息写到LOGDIR目录中。</p>    <p>使用man命令获取更多关于svlodg的信息:</p>    <pre>  <code class="language-bash"># man svlogd</code></pre>    <p>当runsvdir在 /etc/service/ 目录中发现新的配置时,它会继续查找子目录log,如果找到了则启动runsv进程来执行和监控log目录下的run脚本。</p>    <h3>服务示例</h3>    <p>接下来,我们使用上面创建的模板来创建一个简单的服务配置。首先创建需要再run脚本中被chpst使用的用户:</p>    <pre>  <code class="language-bash"># adduser foo</code></pre>    <p>接下来创建放置服务配置的目录,并将它的所属用户与用户组设置为foo。</p>    <pre>  <code class="language-bash"># mkdir /opt/example  # chown foo:foo /opt/example</code></pre>    <p>接下来切换到foo用户:</p>    <pre>  <code class="language-bash"># su foo</code></pre>    <p>在 /opt/example 目录中添加脚本foo-service.sh:</p>    <pre>  <code class="language-bash">#!/bin/bash    echo "Started service..."    for i in {1..30}  do      echo "Doing stuff..."      sleep 1  done    echo "Oh no I crashed..." >&2  exit 1</code></pre>    <p>给脚本赋予执行权限:</p>    <pre>  <code class="language-bash"># chmod +x /opt/example/foo-service.sh</code></pre>    <p>上面的脚本模拟了一个真实的应用,每隔1秒打印一次日志信息,最后打印一次错误信息。可以尝试执行这个脚本:</p>    <pre>  <code class="language-bash"># /opt/example/foo-service.sh</code></pre>    <p>接下来创建包含日志服务的目录:</p>    <pre>  <code class="language-bash"># mkdir /opt/example/logs</code></pre>    <p>再切换回root用户。</p>    <pre>  <code class="language-bash"># exit</code></pre>    <p>接下来使用之前创建的模板来监控这个示例服务,将暂存目录中的模板文件拷贝至新的目录example:</p>    <pre>  <code class="language-bash"># cp -R /etc/runit/template /etc/runit/example</code></pre>    <p>更新 /etc/runit/example/run 脚本的内容,使用foo用户来执行foo-service.sh脚本。</p>    <pre>  <code class="language-bash">#!/bin/sh -e  exec 2>&1  exec chpst -u foo /opt/example/foo-service.sh</code></pre>    <p>同样的,更新 /etc/runit/example/log/run 脚本内容:</p>    <pre>  <code class="language-bash">#!/bin/sh  exec chpst -u foo svlogd -tt /opt/example/logs</code></pre>    <p>在将服务部署到 /etc/service 前,首先测试下配置是否正确:</p>    <pre>  <code class="language-bash"># /etc/runit/example/run</code></pre>    <p>如果脚本运行正常,就可以部署服务了,创建一个软链接:</p>    <pre>  <code class="language-bash"># ln -s /etc/runit/example /etc/service/example</code></pre>    <p>不出意外的话,runsvdir会检测到我们配置的两个服务,然后启动两个runsv进程来执行并监控服务。通过下面的命令可以检测服务是否正常运行。</p>    <pre>  <code class="language-bash"># sv status example</code></pre>    <p>输出结果如下所示:</p>    <pre>  <code class="language-bash">run: example: (pid 3483) 3s; run: log: (pid 3324) 154s</code></pre>    <p>使用tail命令可以查看日志信息:</p>    <pre>  <code class="language-bash"># tail -f /opt/example/logs/current</code></pre>    <p>你会看到日志信息以及异常信息,接着服务重启。</p>    <h3>管理服务</h3>    <p>最后,我们再来学习下sv用法,sv用来手动管理我们的服务。</p>    <ol>     <li> <p>检查服务的状态</p> <pre>  <code class="language-bash">sv status example</code></pre> </li>     <li> <p>停止服务</p> <pre>  <code class="language-bash">sv stop example</code></pre> <p>停止服务之后不会再输出日志信息,也不会再自动重启。</p> </li>     <li> <p>重启服务</p> <pre>  <code class="language-bash">sv restart example</code></pre> </li>     <li> <p>更多用法</p> <pre>  <code class="language-bash">man sv</code></pre> </li>    </ol>    <p> </p>    <p>来自:https://segmentfault.com/a/1190000006644578</p>    <p> </p>