Pages

Tuesday, 29 May 2018

进程监控的更好解决方案-god

God是一个用Ruby写成的,容易配置,容易扩展的服务器监控框架。
保持你的服务器的程序和任务运行应该是你部署过程中简单的一部分。God的目标:做最简单、功能最强的监控应用程序
Tom Preston-Werner tom@mojombo.com
Google Group:http://groups.google.com/group/god-rb

系统特性

  • 配置文件为Ruby程序
  • 可以容易地用Ruby自定义条件
  • 支持基于条件的poll和event
  • 不同的poll条件可以有不同的间隔
  • 集成事件通知系统(可扩展)
  • 容易地控制非守护脚本

安装

最好的方法是通过rubygems安装:
$[sudo] gem install god

系统需求

God目前仅仅在Linux(Kernel 2.6.15+),BSD, 和Darwin系统上运行。暂时没有支持Windows系统的计划。在Linux系统上基于条件的事件监控需要加载cn(connector)核心模块或者编译进核心,god需要以root权限运行。
以下系统已经测试过。欢迎帮忙测试其他系统!
  • Darwin 10.4.10
  • RedHat Fedora 6-15
  • Ubuntu Dapper(no events)
  • Ubuntu Feisty
  • CentOS 4.5(no events), 5, 6

快速开始

备注: 这个快速向导需要0.12.0以后的版本。你可以检查你的版本:
$ god --version
最简单的理解god怎么运行的方法是测试一个简单的例子。为了让你快速上手,我将给你展示怎么保持一个很小的服务运行。
新建一个目录,然后写一个简单的服务器脚本。让我们给它命名为simple.rb:
loop do
  puts 'Hello'
  sleep 1
end
现在我们将写一个god配置文件,告诉god关于我们的进程。把它和simple.rb放在同一个文件夹,命名为simple.god:
God.watch do |w|
  w.name = "simple"
  w.start = "ruby /full/path/to/simple.rb"
  w.keepalive
end
这是最简单的god配置文件。我们以宣布一个God.watch块开始。一个watch在god里代表一个我们想要watch和控制的进程。每个watch必须有一个唯一的名字和一个告诉god怎么启动进程的命令。keepalive的声明告诉god保持这个进程alive。假如god启动时这个进程没有运行,god将会启动它。假如进程不响应,god就会重新启动它。
在这个例子里,simple进程在前端运行,所以god会照看该进程,保持跟踪这个进程的PID。如果可能,最好要god为我们启动进程,这样我们就不必担心指定和保持跟踪PID的文件。后面我们将看见不能在前景运行或者需要指定进程PID的情况下怎样管理。
为了运行god,我们使用参数-c给它提供一个参数。通过参数-D就可以让god在前端运行,能让我们看见发生了什么。
$ god -c path/to/simple.god -D
god可以通过两种方式来监控你的进程。第一个和最好的一个是方法是用event。不是每个系统都支持,但是如果系统支持的话会自动使用event。通过event,god会立即知道一个进程是否存在。对那些系统没有event支持的,god使用polling机制。这个部分的整个输出如下:
启动god后,你回看见一些例如以下的输出:
# Events

I [2011-12-10 15:24:34]  INFO: Loading simple.god
I [2011-12-10 15:24:34]  INFO: Syslog enabled.
I [2011-12-10 15:24:34]  INFO: Using pid file directory: /Users/tom/.god/pids
I [2011-12-10 15:24:34]  INFO: Started on drbunix:///tmp/god.17165.sock
I [2011-12-10 15:24:34]  INFO: simple move 'unmonitored' to 'init'
I [2011-12-10 15:24:34]  INFO: simple moved 'unmonitored' to 'init'
I [2011-12-10 15:24:34]  INFO: simple [trigger] process is not running (ProcessRunning)
I [2011-12-10 15:24:34]  INFO: simple move 'init' to 'start'
I [2011-12-10 15:24:34]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-10 15:24:34]  INFO: simple moved 'init' to 'start'
I [2011-12-10 15:24:34]  INFO: simple [trigger] process is running (ProcessRunning)
I [2011-12-10 15:24:34]  INFO: simple move 'start' to 'up'
I [2011-12-10 15:24:34]  INFO: simple registered 'proc_exit' event for pid 23298
I [2011-12-10 15:24:34]  INFO: simple moved 'start' to 'up'

# Polls

I [2011-12-07 09:40:18]  INFO: Loading simple.god
I [2011-12-07 09:40:18]  INFO: Syslog enabled.
I [2011-12-07 09:40:18]  INFO: Using pid file directory: /Users/tom/.god/pids
I [2011-12-07 09:40:18]  INFO: Started on drbunix:///tmp/god.17165.sock
I [2011-12-07 09:40:18]  INFO: simple move 'unmonitored' to 'up'
I [2011-12-07 09:40:18]  INFO: simple moved 'unmonitored' to 'up'
I [2011-12-07 09:40:18]  INFO: simple [trigger] process is not running (ProcessRunning)
I [2011-12-07 09:40:18]  INFO: simple move 'up' to 'start'
I [2011-12-07 09:40:18]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-07 09:40:19]  INFO: simple moved 'up' to 'up'
I [2011-12-07 09:40:19]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:40:24]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:40:29]  INFO: simple [ok] process is running (ProcessRunning)
你可以看见god启动了,注意到simple没有在运行,启动它,然后每隔5分钟检查一下确保simple运行正常。假如你想看见god的魔力,kill simple的进程。你会发现类似如下的输出:
# Events

I [2011-12-10 15:33:38]  INFO: simple [trigger] process 23416 exited (ProcessExits)
I [2011-12-10 15:33:38]  INFO: simple move 'up' to 'start'
I [2011-12-10 15:33:38]  INFO: simple deregistered 'proc_exit' event for pid 23416
I [2011-12-10 15:33:38]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-10 15:33:38]  INFO: simple moved 'up' to 'start'
I [2011-12-10 15:33:38]  INFO: simple [trigger] process is running (ProcessRunning)
I [2011-12-10 15:33:38]  INFO: simple move 'start' to 'up'
I [2011-12-10 15:33:38]  INFO: simple registered 'proc_exit' event for pid 23601
I [2011-12-10 15:33:38]  INFO: simple moved 'start' to 'up'

# Polls

I [2011-12-07 09:54:59]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:55:04]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:55:09]  INFO: simple [trigger] process is not running (ProcessRunning)
I [2011-12-07 09:55:09]  INFO: simple move 'up' to 'start'
I [2011-12-07 09:55:09]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-07 09:55:09]  INFO: simple moved 'up' to 'up'
I [2011-12-07 09:55:09]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:55:14]  INFO: simple [ok] process is running (ProcessRunning)
保持进程启动是好的,但是假如能够保证我们的进程表现良好,当资源超过我们的设置,重新启动进程将更好。通过添加一点条件,当内存或者CPU超过我们设定的限制,我们能够容易地让我们的进程重启。编辑simple.god配置文件如下:
God.watch do |w|
  w.name = 'simple'
  w.start = "ruby /full/path/to/simple.rb"
  w.keepalive( :memory_max => 150.megabytes,
               :cpu_max => 50.percent)
end
这里我在keepalive命令中使用了 :memory_max 选项。 现在,假如进程的内存用量超过150M, god就会重启他。相似地,通过设置 :cpu_max, 假如CPU的使用超过50%,god也会重启它。 默认这些属性每隔30秒检查一次,假如五个条件中满足三个,则会执行。这防止了进程因为暂时的资源峰值导致重启。
为了测试这个特性,修改你的simple.rb服务器脚本使得引起内存泄露:
data = ''
loop do
  puts 'Hello'
  100000.times { data << 'x' }
end
按Ctrl-C结束god。注意到你的simple进程依然在运行。用刚才的方式再次启动god。现在代替了启动simple进程,god监测到simple运行,简单的切换到up状态。
# Events

I [2011-12-10 15:36:00]  INFO: Loading simple.god
I [2011-12-10 15:36:00]  INFO: Syslog enabled.
I [2011-12-10 15:36:00]  INFO: Using pid file directory: /Users/tom/.god/pids
I [2011-12-10 15:36:00]  INFO: Started on drbunix:///tmp/god.17165.sock
I [2011-12-10 15:36:00]  INFO: simple move 'unmonitored' to 'init'
I [2011-12-10 15:36:00]  INFO: simple moved 'unmonitored' to 'init'
I [2011-12-10 15:36:00]  INFO: simple [trigger] process is running (ProcessRunning)
I [2011-12-10 15:36:00]  INFO: simple move 'init' to 'up'
I [2011-12-10 15:36:00]  INFO: simple registered 'proc_exit' event for pid 23601
I [2011-12-10 15:36:00]  INFO: simple moved 'init' to 'up'

# Polls

I [2011-12-07 14:50:46]  INFO: Loading simple.god
I [2011-12-07 14:50:46]  INFO: Syslog enabled.
I [2011-12-07 14:50:46]  INFO: Using pid file directory: /Users/tom/.god/pids
I [2011-12-07 14:50:47]  INFO: Started on drbunix:///tmp/god.17165.sock
I [2011-12-07 14:50:47]  INFO: simple move 'unmonitored' to 'up'
I [2011-12-07 14:50:47]  INFO: simple moved 'unmonitored' to 'up'
I [2011-12-07 14:50:47]  INFO: simple [ok] process is running (ProcessRunning)

为了让我们的simple服务运行,我们重新启动simple:
$ god restart simple 
通过日志你可以看见god结束了simple进程并重新启动了:
# Events

I [2011-12-10 15:38:13]  INFO: simple move 'up' to 'restart'
I [2011-12-10 15:38:13]  INFO: simple deregistered 'proc_exit' event for pid 23601
I [2011-12-10 15:38:13]  INFO: simple stop: default lambda killer
I [2011-12-10 15:38:13]  INFO: simple sent SIGTERM
I [2011-12-10 15:38:14]  INFO: simple process stopped
I [2011-12-10 15:38:14]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-10 15:38:14]  INFO: simple moved 'up' to 'restart'
I [2011-12-10 15:38:14]  INFO: simple [trigger] process is running (ProcessRunning)
I [2011-12-10 15:38:14]  INFO: simple move 'restart' to 'up'
I [2011-12-10 15:38:14]  INFO: simple registered 'proc_exit' event for pid 23707
I [2011-12-10 15:38:14]  INFO: simple moved 'restart' to 'up'

# Polls

I [2011-12-07 14:51:13]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:51:13]  INFO: simple move 'up' to 'restart'
I [2011-12-07 14:51:13]  INFO: simple stop: default lambda killer
I [2011-12-07 14:51:13]  INFO: simple sent SIGTERM
I [2011-12-07 14:51:14]  INFO: simple process stopped
I [2011-12-07 14:51:14]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-07 14:51:14]  INFO: simple moved 'up' to 'up'
I [2011-12-07 14:51:14]  INFO: simple [ok] process is running (ProcessRunning)

God现在开始报告内存和CPU的使用情况
# Events and Polls

I [2011-12-07 14:54:37]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:54:37]  INFO: simple [ok] memory within bounds [2032kb] (MemoryUsage)
I [2011-12-07 14:54:37]  INFO: simple [ok] cpu within bounds [0.0%%] (CpuUsage)
I [2011-12-07 14:54:42]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:54:42]  INFO: simple [ok] memory within bounds [2032kb, 13492kb] (MemoryUsage)
I [2011-12-07 14:54:42]  INFO: simple [ok] cpu within bounds [0.0%%, *99.7%%] (CpuUsage)
I [2011-12-07 14:54:47]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:54:47]  INFO: simple [ok] memory within bounds [2032kb, 13492kb, 25568kb] (MemoryUsage)
I [2011-12-07 14:54:47]  INFO: simple [ok] cpu within bounds [0.0%%, *99.7%%, *100.0%%] (CpuUsage)
I [2011-12-07 14:54:52]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:54:52]  INFO: simple [ok] memory within bounds [2032kb, 13492kb, 25568kb, 37556kb] (MemoryUsage)
I [2011-12-07 14:54:52]  INFO: simple [trigger] cpu out of bounds [0.0%%, *99.7%%, *100.0%%, *98.4%%] (CpuUsage)
I [2011-12-07 14:54:52]  INFO: simple move 'up' to 'restart
在最后的一行,你能看见CPU的用量已经超过了50%三次了,god重新启动了进程。god会持续地监测simple进程,只要god在运行,进程就会被一直监控。
现在,你结束god之前,让我们先通过god结束simple服务。在一个新的终端,输入以下命令:
$ god stop simple 
你应该看见如下输出:
Sending 'stop' command

The following watches were affected:
   simple

在god运行的终端,你会看见发生了什么:
# Events

I [2011-12-10 15:41:04]  INFO: simple stop: default lambda killer
I [2011-12-10 15:41:04]  INFO: simple sent SIGTERM
I [2011-12-10 15:41:05]  INFO: simple process stopped
I [2011-12-10 15:41:05]  INFO: simple move 'up' to 'unmonitored'
I [2011-12-10 15:41:05]  INFO: simple deregistered 'proc_exit' event for pid 23707
I [2011-12-10 15:41:05]  INFO: simple moved 'up' to 'unmonitored'

# Polls

I [2011-12-07 09:59:59]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 10:00:04]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 10:00:07]  INFO: simple stop: default lambda killer
I [2011-12-07 10:00:07]  INFO: simple sent SIGTERM
I [2011-12-07 10:00:08]  INFO: simple process stopped
I [2011-12-07 10:00:08]  INFO: simple move 'up' to 'unmonitored'
I [2011-12-07 10:00:08]  INFO: simple moved 'up' to 'unmonitored'

现在,你可以自由的按Ctrl—C退出god了。热烈祝贺!你已经测试了一遍god,也已经看见god是多么容易的让你的进程一直运行了。
不过这只是个开始。在实际应用中,keepalive 命令是一个方便的方法,使用了可以直接使用的更高级的事务和条件构造。你可以配置许多不同的条件,当CPU或者内存使用太多,磁盘超过下限,当一个指定的URL返回错误代码,等等。另外,你可以写自己的自定义条件,然后在配置文件里使用它。伴随着复杂的和可扩展的通知体系,可以控制许多不同的生命周期。
继续阅读找出god不同于其他监测系统的地方,以及它怎么能帮助你解决许多进程监控和控制问题。
###用Ruby写配置文件 既然你已经知道怎么使用god,让我们看看god更强大的一面吧。

god的官网:https://github.com/mojombo/god
---------------

God教程

一、什么是God

God 是用 Ruby 写的进程监控框架,具有易配置易扩展的优点。用它可以很方便的监控一个软件的运行状态,并在特定的条件下杀死或重启进程,以保证任务的持久性和高可用性。
常见场景
  • 监控一个进程,当它因意味错误退出或失去响应时重新启动它。
  • 监控一个进程,当它耗费的CPU或内存超过特定值时杀死或重新启动它。

二、God的优缺点

优点:
  • 启动和控制都使用一个命令: god
  • 可以管理daemon和非daemon进程
  • 可以设置进程的uid、env、dir、log等参数
  • 进程配置文件和supervisord类似,但使用ruby的语法。支持类似monit的,对进程使用资源和各种条件的控制
  • 支持进程配置动态加载功能
  • 支持把多个进程配置拆分成单独的配置文件,类似include功能
  • 支持通知功能,包括:Webhook、Email、Twitter、Jabber、Campfire等多个接口
  • 根据PID的方式进行监控,GOD可以随便升级和重启
缺点
  • 不提供web端和rpc接口
  • log查看stdrr/stdout 功能似乎不能正常work,不过我基本上用不到这个功能
  • linux下采用2种方式检测进程poll和event。root默认启用event模式,如果启动的进程错误,它会注册一个proc_exit事件,但无法响应。

三、安装

最好的方法是通过rubygems安装:
 $[sudo] gem install god

四、快速开始

新建一个目录,然后写一个简单的服务器脚本。让我们给它命名为simple.rb:
新建一个目录,然后写一个简单的服务器脚本。让我们给它命名为simple.rb:
loop do
  puts 'Hello'
  sleep 1
end
现在我们将写一个god配置文件,告诉god关于我们的进程。把它和simple.rb放在同一个文件夹,命名为simple.god:
God.watch do |w|
  w.name = "simple"
  w.start = "ruby /full/path/to/simple.rb"
  w.keepalive
end
这是最简单的god配置文件。
我们以宣布一个God.watch块开始。
一个watch在god里代表一个我们想要watch和控制的进程。
每个watch必须有一个唯一的名字和一个告诉god怎么启动进程的命令。
keepalive的声明告诉god保持这个进程alive。
假如god启动时这个进程没有运行,god将会启动它。假如进程不响应,god就会重新启动它。
在这个例子里,simple进程在前端运行,所以god会照看该进程,保持跟踪这个进程的PID。
如果可能,最好要god为我们启动进程,这样我们就不必担心指定和保持跟踪PID的文件。
后面我们将看见不能在前景运行或者需要指定进程PID的情况下怎样管理。
为了运行god,我们使用参数-c给它提供一个参数。通过参数-D就可以让god在前端运行,能让我们看见发生了什么。
$ god -c path/to/simple.god -D
god可以通过两种方式来监控你的进程。
第一个和最好的一个是方法是用event。
不是每个系统都支持,但是如果系统支持的话会自动使用event。
通过event,god会立即知道一个进程是否存在。
对那些系统没有event支持的,god使用polling机制。这个部分的整个输出如下:
# Events
I [2011-12-10 15:24:34]  INFO: Loading simple.god
I [2011-12-10 15:24:34]  INFO: Syslog enabled.
I [2011-12-10 15:24:34]  INFO: Using pid file directory: /Users/tom/.god/pids
I [2011-12-10 15:24:34]  INFO: Started on drbunix:///tmp/god.17165.sock
I [2011-12-10 15:24:34]  INFO: simple move 'unmonitored' to 'init'
I [2011-12-10 15:24:34]  INFO: simple moved 'unmonitored' to 'init'
I [2011-12-10 15:24:34]  INFO: simple [trigger] process is not running (ProcessRunning)
I [2011-12-10 15:24:34]  INFO: simple move 'init' to 'start'
I [2011-12-10 15:24:34]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-10 15:24:34]  INFO: simple moved 'init' to 'start'
I [2011-12-10 15:24:34]  INFO: simple [trigger] process is running (ProcessRunning)
I [2011-12-10 15:24:34]  INFO: simple move 'start' to 'up'
I [2011-12-10 15:24:34]  INFO: simple registered 'proc_exit' event for pid 23298
I [2011-12-10 15:24:34]  INFO: simple moved 'start' to 'up'

# Polls

I [2011-12-07 09:40:18]  INFO: Loading simple.god
I [2011-12-07 09:40:18]  INFO: Syslog enabled.
I [2011-12-07 09:40:18]  INFO: Using pid file directory: /Users/tom/.god/pids
I [2011-12-07 09:40:18]  INFO: Started on drbunix:///tmp/god.17165.sock
I [2011-12-07 09:40:18]  INFO: simple move 'unmonitored' to 'up'
I [2011-12-07 09:40:18]  INFO: simple moved 'unmonitored' to 'up'
I [2011-12-07 09:40:18]  INFO: simple [trigger] process is not running (ProcessRunning)
I [2011-12-07 09:40:18]  INFO: simple move 'up' to 'start'
I [2011-12-07 09:40:18]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-07 09:40:19]  INFO: simple moved 'up' to 'up'
I [2011-12-07 09:40:19]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:40:24]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:40:29]  INFO: simple [ok] process is running (ProcessRunning)
你可以看见god启动了,注意到simple没有在运行,启动它,然后每隔5分钟检查一下确保simple运行正常。
假如你想看见god的魔力,kill simple的进程。你会发现类似如下的输出:
# Events
I [2011-12-10 15:33:38]  INFO: simple [trigger] process 23416 exited (ProcessExits)
I [2011-12-10 15:33:38]  INFO: simple move 'up' to 'start'
I [2011-12-10 15:33:38]  INFO: simple deregistered 'proc_exit' event for pid 23416
I [2011-12-10 15:33:38]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-10 15:33:38]  INFO: simple moved 'up' to 'start'
I [2011-12-10 15:33:38]  INFO: simple [trigger] process is running (ProcessRunning)
I [2011-12-10 15:33:38]  INFO: simple move 'start' to 'up'
I [2011-12-10 15:33:38]  INFO: simple registered 'proc_exit' event for pid 23601
I [2011-12-10 15:33:38]  INFO: simple moved 'start' to 'up'

# Polls

I [2011-12-07 09:54:59]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:55:04]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:55:09]  INFO: simple [trigger] process is not running (ProcessRunning)
I [2011-12-07 09:55:09]  INFO: simple move 'up' to 'start'
I [2011-12-07 09:55:09]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-07 09:55:09]  INFO: simple moved 'up' to 'up'
I [2011-12-07 09:55:09]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:55:14]  INFO: simple [ok] process is running (ProcessRunning)
保持进程启动是好的,但是假如能够保证我们的进程表现良好,当资源超过我们的设置,重新启动进程将更好。通过添加一点条件,当内存或者CPU超过我们设定的限制,我们能够容易地让我们的进程重启。编辑simple.god配置文件如下:
God.watch do |w|
  w.name = 'simple'
  w.start = "ruby /full/path/to/simple.rb"
  w.keepalive( :memory_max => 150.megabytes,
               :cpu_max => 50.percent)
end
这里我在keepalive命令中使用了 :memory_max 选项。
现在,假如进程的内存用量超过150M, god就会重启他。
相似地,通过设置 :cpu_max, 假如CPU的使用超过50%,god也会重启它。
默认这些属性每隔30秒检查一次,假如五个条件中满足三个,则会执行。这防止了进程因为暂时的资源峰值导致重启。
为了测试这个特性,修改你的simple.rb服务器脚本使得引起内存泄露:
data = ''
loop do
  puts 'Hello'
  100000.times { data << 'x' }
end
按Ctrl-C结束god。注意到你的simple进程依然在运行。
用刚才的方式再次启动god。
现在代替了启动simple进程,god监测到simple运行,简单的切换到up状态。
# Events
I [2011-12-10 15:36:00]  INFO: Loading simple.god
I [2011-12-10 15:36:00]  INFO: Syslog enabled.
I [2011-12-10 15:36:00]  INFO: Using pid file directory: /Users/tom/.god/pids
I [2011-12-10 15:36:00]  INFO: Started on drbunix:///tmp/god.17165.sock
I [2011-12-10 15:36:00]  INFO: simple move 'unmonitored' to 'init'
I [2011-12-10 15:36:00]  INFO: simple moved 'unmonitored' to 'init'
I [2011-12-10 15:36:00]  INFO: simple [trigger] process is running (ProcessRunning)
I [2011-12-10 15:36:00]  INFO: simple move 'init' to 'up'
I [2011-12-10 15:36:00]  INFO: simple registered 'proc_exit' event for pid 23601
I [2011-12-10 15:36:00]  INFO: simple moved 'init' to 'up'

# Polls

I [2011-12-07 14:50:46]  INFO: Loading simple.god
I [2011-12-07 14:50:46]  INFO: Syslog enabled.
I [2011-12-07 14:50:46]  INFO: Using pid file directory: /Users/tom/.god/pids
I [2011-12-07 14:50:47]  INFO: Started on drbunix:///tmp/god.17165.sock
I [2011-12-07 14:50:47]  INFO: simple move 'unmonitored' to 'up'
I [2011-12-07 14:50:47]  INFO: simple moved 'unmonitored' to 'up'
I [2011-12-07 14:50:47]  INFO: simple [ok] process is running (ProcessRunning)
为了让我们的simple服务运行,我们重新启动simple,这里必须强烈地要求重启否则新添加的配置不会生效
god restart simple 
通过日志你可以看见god结束了simple进程并重新启动了:
# Events

I [2011-12-10 15:38:13]  INFO: simple move 'up' to 'restart'
I [2011-12-10 15:38:13]  INFO: simple deregistered 'proc_exit' event for pid 23601
I [2011-12-10 15:38:13]  INFO: simple stop: default lambda killer
I [2011-12-10 15:38:13]  INFO: simple sent SIGTERM
I [2011-12-10 15:38:14]  INFO: simple process stopped
I [2011-12-10 15:38:14]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-10 15:38:14]  INFO: simple moved 'up' to 'restart'
I [2011-12-10 15:38:14]  INFO: simple [trigger] process is running (ProcessRunning)
I [2011-12-10 15:38:14]  INFO: simple move 'restart' to 'up'
I [2011-12-10 15:38:14]  INFO: simple registered 'proc_exit' event for pid 23707
I [2011-12-10 15:38:14]  INFO: simple moved 'restart' to 'up'

# Polls

I [2011-12-07 14:51:13]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:51:13]  INFO: simple move 'up' to 'restart'
I [2011-12-07 14:51:13]  INFO: simple stop: default lambda killer
I [2011-12-07 14:51:13]  INFO: simple sent SIGTERM
I [2011-12-07 14:51:14]  INFO: simple process stopped
I [2011-12-07 14:51:14]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-07 14:51:14]  INFO: simple moved 'up' to 'up'
I [2011-12-07 14:51:14]  INFO: simple [ok] process is running (ProcessRunning)
God现在开始报告内存和CPU的使用情况
# Events and Polls

I [2011-12-07 14:54:37]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:54:37]  INFO: simple [ok] memory within bounds [2032kb] (MemoryUsage)
I [2011-12-07 14:54:37]  INFO: simple [ok] cpu within bounds [0.0%%] (CpuUsage)
I [2011-12-07 14:54:42]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:54:42]  INFO: simple [ok] memory within bounds [2032kb, 13492kb] (MemoryUsage)
I [2011-12-07 14:54:42]  INFO: simple [ok] cpu within bounds [0.0%%, *99.7%%] (CpuUsage)
I [2011-12-07 14:54:47]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:54:47]  INFO: simple [ok] memory within bounds [2032kb, 13492kb, 25568kb] (MemoryUsage)
I [2011-12-07 14:54:47]  INFO: simple [ok] cpu within bounds [0.0%%, *99.7%%, *100.0%%] (CpuUsage)
I [2011-12-07 14:54:52]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:54:52]  INFO: simple [ok] memory within bounds [2032kb, 13492kb, 25568kb, 37556kb] (MemoryUsage)
I [2011-12-07 14:54:52]  INFO: simple [trigger] cpu out of bounds [0.0%%, *99.7%%, *100.0%%, *98.4%%] (CpuUsage)
I [2011-12-07 14:54:52]  INFO: simple move 'up' to 'restart
在最后的一行,你能看见CPU的用量已经超过了50%三次了,
god重新启动了进程。god会持续地监测simple进程,只要god在运行,进程就会被一直监控。
现在,你结束god之前,让我们先通过god结束simple服务。在一个新的终端,输入以下命令:
god stop simple 
如果想停止god,你可以自由地Ctrl-C 退出god 了。
不过这只是个开始。在实际应用中,keepalive 命令是一个方便的方法,使用了可以直接使用的更高级的事务和条件构造。你可以配置许多不同的条件,当CPU或者内存使用太多,磁盘超过下限,当一个指定的URL返回错误代码,等等。另外,你可以写自己的自定义条件,然后在配置文件里使用它。伴随着复杂的和可扩展的通知体系,可以控制许多不同的生命周期。
既然你已经知道怎么使用god,让我们看看god更强大的一面吧。再说一次,最好的学习方法是通过示例。下面这个配置文件是我在gravatar.com保证mongrels运行使用的配置文件。
## 在这里我设置了一个常量,用于整个文件。保持RAILS_ROOT的值是一个常量使得脚本很容易适合其他应用
RAILS_ROOT = "/Users/tom/dev/gravatar2"


## 循环监控  8200 8210 8202 端口
%w{8200 8201 8202}.each do |port|
  God.watch do |w|
    w.name = "gravatar2-mongrel-#{port}"

    ## 使用 mogrel_rails 命令启动
    w.start = "mogrel_rails start -c #{RAILS_ROOT} -p #{port} \
      -P #{RAILS_ROOT}/log.mogrel.#{port}.pid -d"

    ## 使用 mogrel_rails 命令停止
    w.stop = "morgrel_rails stop -P #{RAILS_ROOT}/log/mogrel.#{port}.pid"
    ##  重启
    w.restart = "mongrel_rails restart -P #{RAILS_ROOT}/log/mogrel.#{port}.pid"

    w.pid_file = File.join(RAILS_ROOT, "log/mogrel.#{port}.pid")

    ## 假如你正监视的进程是一个后天进程(我的也是),你需要设置pid_file属性。????
    ## behavio允许你伴随着start/stop/restart执行额外的命令。
    ## 在我们的例子里,假如进程死了,它会留下PID文件。
    ## 假如下次重新启动这个程序,就会启动失败,提示PID文件已经存在。
    ## 所以启动程序时,我们想先清除PID文件。内建的clean_pid_file就会清除
    w.behavior(:clean_pid_file)


    ## watch包含由可执行的动作组成的条件应该返回true
    w.start_if do |start|
      start.condition(:process_running) do |c|
        ## 通过用一个识别字符调用condition条件来描述condition,这个例子中是:process_running. 每个条件描述一个poll间隔,这个间隔将覆盖默认的间隔。这个例子中,我想要每个5秒钟检查一次进程,而不是像其他condition一样用30秒间隔
        c.inteval = 5.seconds
        c.running = false
      end
    end

    ## 和start_if类似,restart_if命令组合condition,
    ## 然后触发restart。memory_usage条件将会失败,
    ## 假如指定的进程使用了太多的内存。
    ## 最大允许的内存通过above属性来指定(你可以用kilobytes, megabytes, 或者gibabytes助手)。
    ## 为了触发restart需要触发的次数通过times设置。
    ## 这个可以是一个整数,也可以是一个数组。
    ## 整数意味着它必须连续失败许多次而数组[x, y]意味着必须y次中失败x次。
    w.restart_if do |restart|
      restart.condition(:memory_usage) do |c|
       c.above = 150.megabytes
       c.times = [3, 5] # 3 out of 5 intevals
      end

      restart.condition(:cpu_usage) do |c|
        c.above = 50.percent
        c.times = 5
      end
    end

    #lifecycle
    ## 在lifecycle部分中的condition只要进程被监视就一直活动(它们通过状态的改变活动)。
    ## :flapping condition守护除了god快速开始和重启你的应用的这些边缘的状态的其他情况。
    ## 比如服务器配置变化或者外部服务的不可用都可能造成我得进程不能启动。
    ## 那样的话,god将会一直重试启动我的进程。
    ## :flapping condition提供了两个水平的放弃不稳定进程。
    ## 假如我翻译以上的option代码,那就是:
    ## 假如watch在5分钟里被启动或者重启了5次,然后不再监视它。。。
    ## 然后10分钟后,再次监视他看看是否只是一个临时的问题;
    ## 假如进程在两小时里依然不稳定,然后彻底放弃监视
    ## lifecycle 是一个非常重要的配置,之前听过架构师说过,God 进程怎么一直在重启
    ## 肯定就是这里的坑!!!!!!!
    w.lifecycle do |on|
     on.condition(:flapping) do |c|
       c.to_state = [:start, :restart]
       c.times = 5
       c.within = 5.minute
       c.transition = :unmonitored
       c.retry_in = 10.minutes
       c.retry_times = 5
       c.retry_within = 2.hours
     end
    end
   end
  end

五、动态加载文件进入一个已经运行的god

God允许你加载或者重新加载配置文件进入一个已经运行的实例。当你准备这样做得时候,有几件事情需要考虑:
  • 已经存在的watch会被新配置文件里的同名的watch覆盖
  • 所有的路径必须是绝对路径或者god运行的相对路径
将配置文件加载至一个正在运行的god,运行以下命令:
sudo god load path/to/config.god
动态加载的配置文件可以包含任何一个普通的配置文件,然而,全局变量例如God.pid_file_directory块将可能会被忽视(会在日志里产生一个警告)。
如果把god作为一个后台进程,只需要把配置文件的路径传递给god(你需要使用sudo假如你在linux使用event或者想要使用setuid/setgid)
sudo god -c /path/to/config.god
当你写配置文件的时候,在前台运行god这样你能看见log消息,可能会很有帮助。你可以:
sudo god -c /path/to/config.god -D
你能启动、重启、停止、监测、不监测你的watch用同样的工具像这样:
sudo god stop gravatar2-mongrel-8200

六、God 的其他功能

+ 重定向你进程的STDOUT和STDERR
+ 改变进程的UID/GID
+ 设置工作目录
+ 设置环境变量
+ 使用CHROOT改变文件系统的根目录
+ Lambda命令
+ 自定义默认的停止运行lambda
+ 加载其他配置文件
+ 为单个watch得到日志文件
+ 通知
转载,有修改。原文God 使用手册

参考

God(进程监控)
God进程监控框架
God 使用手册

链接:https://www.jianshu.com/p/c948585ef41e
-------------------
god有一个强大的集成系统通知,对于每一个notofication都有其详尽的描述;而且对于非守护进程,god同 样能编写命令对其有一个很好的控制。god的最终目的就是为了让后台进程服务管理监控更加简便和自动化,安装god也 十分简单,因为god是使用ruby编写的,即也可以使用ruby gem来安装。
$ sudo gem install god

god的使用方法也很简单,网上有许多资源可以参考,这里便不再赘述。以下是一些参考,对于大家了解和使用god很有帮助:

① 关于god的本质和基础教程:http://godrb.com/

② god的实际运用:http://www.synbioz.com/blog/monitoring_server_processes_with_god

③ god在github上的开源项目:https://github.com/mojombo/god/

------------------------------------ 

God使用手册

服务器监控的更好解决方案

God 是一个用 Ruby 写成的,容易配置,容易扩展的服务器监控框架。

保持你的服务器的程序和任务运行应该是你部署过程中简单的一部分。God 的目标做最简单、功能最强的监控应用程序。

Tom Preston-Werner tom@mojombo.com

Google Group:http://groups.google.com/group/god-rb

系统特性

  • 配置文件为 Ruby 程序
  • 可以容易地用 Ruby 自定义条件
  • 支持基于条件的 poll 和 event
  • 不同的 poll 条件可以有不同的间隔
  • 集成事件通知系统(可扩展)
  • 容易地控制非守护脚本

安装

最好的方法是通过 rubygems 安装:

$[sudo] gem install god

系统需求

God 目前仅仅在 Linux(Kernel 2.6.15+),BSD, 和 Darwin 系统上运行。暂时没有支持 Windows 系统的计划。在 Linux 系统上基于条件的事件监控需要加载 cn(connector)核心模块或者编译进核心,god 需要以root权限运行。

以下系统已经测试过。欢迎帮忙测试其他系统!

  • Darwin 10.4.10
  • RedHat Fedora 6-15
  • Ubuntu Dapper (no events)
  • Ubuntu Feisty
  • CentOS 4.5 (no events), 5, 6

快速开始

备注:这个快速向导需要 0.12.0 以后的版本。你可以检查你的版本:

$ god --version

最简单的理解 god 怎么运行的方法是测试一个简单的例子。为了让你快速上手,我将给你展示怎么保持一个很小的服务运行。

新建一个目录,然后写一个简单的服务器脚本。让我们给它命名为 simple.rb:

loop do
  puts 'Hello'
  sleep 1
end

现在我们将写一个 god 配置文件,告诉 god 关于我们的进程。把它和 simple.rb 放在同一个文件夹,命名为 simple.god:

God.watch do |w|
  w.name = "simple"
  w.start = "ruby /full/path/to/simple.rb"
  w.keepalive
end

这是最简单的 god 配置文件。我们以宣布一个 God.watch 块开始。一个 watch 在 god 里代表一个我们想要 watch 和控制的进程。每个 watch 必须有一个唯一的名字和一个告诉 god 怎么启动进程的命令。keepalive的声明告诉 god 保持这个进程 alive。假如 god 启动时这个进程没有运行,god 将会启动它。假如进程不响应,god 就会重新启动它。

在这个例子里,simple 进程在前端运行,所以 god 会照看该进程,保持跟踪这个进程的 PID。如果可能,最好要 god 为我们启动进程,这样我们就不必担心指定和保持跟踪 PID 的文件。后面我们将看见不能在前景运行或者需要指定进程 PID 的情况下怎样管理。

为了运行 god,我们使用参数-c 给它提供一个参数。通过参数-D 就可以让 god 在前端运行,能让我们看见发生了什么。

$ god -c path/to/simple.god -D

god 可以通过两种方式来监控你的进程。第一个和最好的一个是方法是用 event。不是每个系统都支持,但是如果系统支持的话会自动使用 event。通过 event,god 会立即知道一个进程是否存在。对那些系统没有 event 支持的,god 使用 polling 机制。这个部分的整个输出如下:

启动 god 后,你回看见一些例如以下的输出:

# Events

I [2011-12-10 15:24:34]  INFO: Loading simple.god
I [2011-12-10 15:24:34]  INFO: Syslog enabled.
I [2011-12-10 15:24:34]  INFO: Using pid file directory: /Users/tom/.god/pids
I [2011-12-10 15:24:34]  INFO: Started on drbunix:///tmp/god.17165.sock
I [2011-12-10 15:24:34]  INFO: simple move 'unmonitored' to 'init'
I [2011-12-10 15:24:34]  INFO: simple moved 'unmonitored' to 'init'
I [2011-12-10 15:24:34]  INFO: simple [trigger] process is not running (ProcessRunning)
I [2011-12-10 15:24:34]  INFO: simple move 'init' to 'start'
I [2011-12-10 15:24:34]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-10 15:24:34]  INFO: simple moved 'init' to 'start'
I [2011-12-10 15:24:34]  INFO: simple [trigger] process is running (ProcessRunning)
I [2011-12-10 15:24:34]  INFO: simple move 'start' to 'up'
I [2011-12-10 15:24:34]  INFO: simple registered 'proc_exit' event for pid 23298
I [2011-12-10 15:24:34]  INFO: simple moved 'start' to 'up'

# Polls

I [2011-12-07 09:40:18]  INFO: Loading simple.god
I [2011-12-07 09:40:18]  INFO: Syslog enabled.
I [2011-12-07 09:40:18]  INFO: Using pid file directory: /Users/tom/.god/pids
I [2011-12-07 09:40:18]  INFO: Started on drbunix:///tmp/god.17165.sock
I [2011-12-07 09:40:18]  INFO: simple move 'unmonitored' to 'up'
I [2011-12-07 09:40:18]  INFO: simple moved 'unmonitored' to 'up'
I [2011-12-07 09:40:18]  INFO: simple [trigger] process is not running (ProcessRunning)
I [2011-12-07 09:40:18]  INFO: simple move 'up' to 'start'
I [2011-12-07 09:40:18]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-07 09:40:19]  INFO: simple moved 'up' to 'up'
I [2011-12-07 09:40:19]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:40:24]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:40:29]  INFO: simple [ok] process is running (ProcessRunning)

你可以看见 god 启动了,注意到 simple 没有在运行,启动它,然后每隔 5 分钟检查一下确保 simple 运行正常。假如你想看见 god 的魔力,kill simple 的进程。你会发现类似如下的输出:

# Events

I [2011-12-10 15:33:38]  INFO: simple [trigger] process 23416 exited (ProcessExits)
I [2011-12-10 15:33:38]  INFO: simple move 'up' to 'start'
I [2011-12-10 15:33:38]  INFO: simple deregistered 'proc_exit' event for pid 23416
I [2011-12-10 15:33:38]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-10 15:33:38]  INFO: simple moved 'up' to 'start'
I [2011-12-10 15:33:38]  INFO: simple [trigger] process is running (ProcessRunning)
I [2011-12-10 15:33:38]  INFO: simple move 'start' to 'up'
I [2011-12-10 15:33:38]  INFO: simple registered 'proc_exit' event for pid 23601
I [2011-12-10 15:33:38]  INFO: simple moved 'start' to 'up'

# Polls

I [2011-12-07 09:54:59]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:55:04]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:55:09]  INFO: simple [trigger] process is not running (ProcessRunning)
I [2011-12-07 09:55:09]  INFO: simple move 'up' to 'start'
I [2011-12-07 09:55:09]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-07 09:55:09]  INFO: simple moved 'up' to 'up'
I [2011-12-07 09:55:09]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 09:55:14]  INFO: simple [ok] process is running (ProcessRunning)

保持进程启动是好的,但是假如能够保证我们的进程表现良好,当资源超过我们的设置,重新启动进程将更好。通过添加一点条件,当内存或者 CPU 超过我们设定的限制,我们能够容易地让我们的进程重启。编辑 simple.god 配置文件如下:

God.watch do |w|
  w.name = 'simple'
  w.start = "ruby /full/path/to/simple.rb"
  w.keepalive( :memory_max => 150.megabytes,
               :cpu_max => 50.percent)
end

这里我在 keepalive 命令中使用了 :memory_max 选项。现在,假如进程的内存用量超过 150M,god 就会重启他。相似地,通过设置 :cpu_max, 假如 CPU 的使用超过 50%,god 也会重启它。默认这些属性每隔 30 秒检查一次,假如五个条件中满足三个,则会执行。这防止了进程因为暂时的资源峰值导致重启。

为了测试这个特性,修改你的 simple.rb 服务器脚本使得引起内存泄露:

data = ''
loop do
  puts 'Hello'
  100000.times { data << 'x' }
end

按 Ctrl-C 结束 god。注意到你的 simple 进程依然在运行。用刚才的方式再次启动 god。现在代替了启动 simple 进程,god 监测到 simple 运行,简单的切换到 up 状态。

# Events

I [2011-12-10 15:36:00]  INFO: Loading simple.god
I [2011-12-10 15:36:00]  INFO: Syslog enabled.
I [2011-12-10 15:36:00]  INFO: Using pid file directory: /Users/tom/.god/pids
I [2011-12-10 15:36:00]  INFO: Started on drbunix:///tmp/god.17165.sock
I [2011-12-10 15:36:00]  INFO: simple move 'unmonitored' to 'init'
I [2011-12-10 15:36:00]  INFO: simple moved 'unmonitored' to 'init'
I [2011-12-10 15:36:00]  INFO: simple [trigger] process is running (ProcessRunning)
I [2011-12-10 15:36:00]  INFO: simple move 'init' to 'up'
I [2011-12-10 15:36:00]  INFO: simple registered 'proc_exit' event for pid 23601
I [2011-12-10 15:36:00]  INFO: simple moved 'init' to 'up'

# Polls

I [2011-12-07 14:50:46]  INFO: Loading simple.god
I [2011-12-07 14:50:46]  INFO: Syslog enabled.
I [2011-12-07 14:50:46]  INFO: Using pid file directory: /Users/tom/.god/pids
I [2011-12-07 14:50:47]  INFO: Started on drbunix:///tmp/god.17165.sock
I [2011-12-07 14:50:47]  INFO: simple move 'unmonitored' to 'up'
I [2011-12-07 14:50:47]  INFO: simple moved 'unmonitored' to 'up'
I [2011-12-07 14:50:47]  INFO: simple [ok] process is running (ProcessRunning)

为了让我们的 simple 服务运行,我们重新启动 simple:

$ god restart simple 

通过日志你可以看见 god 结束了 simple 进程并重新启动了:

# Events

I [2011-12-10 15:38:13]  INFO: simple move 'up' to 'restart'
I [2011-12-10 15:38:13]  INFO: simple deregistered 'proc_exit' event for pid 23601
I [2011-12-10 15:38:13]  INFO: simple stop: default lambda killer
I [2011-12-10 15:38:13]  INFO: simple sent SIGTERM
I [2011-12-10 15:38:14]  INFO: simple process stopped
I [2011-12-10 15:38:14]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-10 15:38:14]  INFO: simple moved 'up' to 'restart'
I [2011-12-10 15:38:14]  INFO: simple [trigger] process is running (ProcessRunning)
I [2011-12-10 15:38:14]  INFO: simple move 'restart' to 'up'
I [2011-12-10 15:38:14]  INFO: simple registered 'proc_exit' event for pid 23707
I [2011-12-10 15:38:14]  INFO: simple moved 'restart' to 'up'

# Polls

I [2011-12-07 14:51:13]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:51:13]  INFO: simple move 'up' to 'restart'
I [2011-12-07 14:51:13]  INFO: simple stop: default lambda killer
I [2011-12-07 14:51:13]  INFO: simple sent SIGTERM
I [2011-12-07 14:51:14]  INFO: simple process stopped
I [2011-12-07 14:51:14]  INFO: simple start: ruby /Users/tom/dev/mojombo/god/simple.rb
I [2011-12-07 14:51:14]  INFO: simple moved 'up' to 'up'
I [2011-12-07 14:51:14]  INFO: simple [ok] process is running (ProcessRunning)

God 现在开始报告内存和 CPU 的使用情况

# Events and Polls

I [2011-12-07 14:54:37]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:54:37]  INFO: simple [ok] memory within bounds [2032kb] (MemoryUsage)
I [2011-12-07 14:54:37]  INFO: simple [ok] cpu within bounds [0.0%%] (CpuUsage)
I [2011-12-07 14:54:42]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:54:42]  INFO: simple [ok] memory within bounds [2032kb, 13492kb] (MemoryUsage)
I [2011-12-07 14:54:42]  INFO: simple [ok] cpu within bounds [0.0%%, *99.7%%] (CpuUsage)
I [2011-12-07 14:54:47]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:54:47]  INFO: simple [ok] memory within bounds [2032kb, 13492kb, 25568kb] (MemoryUsage)
I [2011-12-07 14:54:47]  INFO: simple [ok] cpu within bounds [0.0%%, *99.7%%, *100.0%%] (CpuUsage)
I [2011-12-07 14:54:52]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 14:54:52]  INFO: simple [ok] memory within bounds [2032kb, 13492kb, 25568kb, 37556kb] (MemoryUsage)
I [2011-12-07 14:54:52]  INFO: simple [trigger] cpu out of bounds [0.0%%, *99.7%%, *100.0%%, *98.4%%] (CpuUsage)
I [2011-12-07 14:54:52]  INFO: simple move 'up' to 'restart

在最后的一行,你能看见 CPU 的用量已经超过了 50% 三次了,god 重新启动了进程。god 会持续地监测 simple 进程,只要 god 在运行,进程就会被一直监控。

现在,你结束 god 之前,让我们先通过 god 结束 simple 服务。在一个新的终端,输入以下命令:

$ god stop simple 

你应该看见如下输出:

Sending 'stop' command

The following watches were affected:
   simple

在 god 运行的终端,你会看见发生了什么:

# Events

I [2011-12-10 15:41:04]  INFO: simple stop: default lambda killer
I [2011-12-10 15:41:04]  INFO: simple sent SIGTERM
I [2011-12-10 15:41:05]  INFO: simple process stopped
I [2011-12-10 15:41:05]  INFO: simple move 'up' to 'unmonitored'
I [2011-12-10 15:41:05]  INFO: simple deregistered 'proc_exit' event for pid 23707
I [2011-12-10 15:41:05]  INFO: simple moved 'up' to 'unmonitored'

# Polls

I [2011-12-07 09:59:59]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 10:00:04]  INFO: simple [ok] process is running (ProcessRunning)
I [2011-12-07 10:00:07]  INFO: simple stop: default lambda killer
I [2011-12-07 10:00:07]  INFO: simple sent SIGTERM
I [2011-12-07 10:00:08]  INFO: simple process stopped
I [2011-12-07 10:00:08]  INFO: simple move 'up' to 'unmonitored'
I [2011-12-07 10:00:08]  INFO: simple moved 'up' to 'unmonitored'

现在,你可以自由的按 Ctrl—C 退出 god 了。热烈祝贺!你已经测试了一遍 god,也已经看见 god 是多么容易的让你的进程一直运行了。

不过这只是个开始。在实际应用中,keepalive 命令是一个方便的方法,使用了可以直接使用的更高级的事务和条件构造。你可以配置许多不同的条件,当 CPU 或者内存使用太多,磁盘超过下限,当一个指定的 URL 返回错误代码,等等。另外,你可以写自己的自定义条件,然后在配置文件里使用它。伴随着复杂的和可扩展的通知体系,可以控制许多不同的生命周期。

继续阅读找出 god 不同于其他监测系统的地方,以及它怎么能帮助你解决许多进程监控和控制问题。

###用 Ruby 写配置文件 既然你已经知道怎么使用 god,让我们看看 god 更强大的一面吧。再说一次,最好的学习方法是通过示例。下面这个配置文件是我在 gravatar.com 保证 mongrels 运行使用的配置文件。

RAILS_ROOT = "/Users/tom/dev/gravatar2"

%w{8200 8201 8202}.each do |port|
  God.watch do |w|
    w.name = "gravatar2-mongrel-#{port}"

    w.start = "mogrel_rails start -c #{RAILS_ROOT} -p #{port} \
      -P #{RAILS_ROOT}/log.mogrel.#{port}.pid -d"
    w.stop = "morgrel_rails stop -P #{RAILS_ROOT}/log/mogrel.#{port}.pid"
    w.restart = "mongrel_rails restart -P #{RAILS_ROOT}/log/mogrel.#{port}.pid"

    w.pid_file = File.join(RAILS_ROOT, "log/mogrel.#{port}.pid")

    w.behavior(:clean_pid_file)

    w.start_if do |start|
      start.condition(:process_running) do |c|
        c.inteval = 5.seconds
        c.running = false
      end
    end

    w.restart_if do |restart|
      restart.condition(:memory_usage) do |c|
       c.above = 150.megabytes
       c.times = [3, 5] # 3 out of 5 intevals
      end

      restart.condition(:cpu_usage) do |c|
        c.above = 50.percent
        c.times = 5
      end
    end

    #lifecycle
    w.lifecycle do |on|
     on.condition(:flapping) do |c|
       c.to_state = [:start, :restart]
       c.times = 5
       c.within = 5.minute
       c.transition = :unmonitored
       c.retry_in = 10.minutes
       c.retry_times = 5
       c.retry_within = 2.hours
     end
    end
   end
  end

新手是不是一下子吓蒙了?所以我把它拆散了解释每一部分的作用

RAILS_ROOT = "/var/www/gravatar2/current"

在这里我设置了一个常量,用于整个文件。保持 RAILS_ROOT 的值是一个常量使得脚本很容易适合其他应用。因为这个配置文件是 Ruby 代码,我可以设置任何变量或者常量,这样可以使得配置更简单,更容易工作。

%w{8200 8210 8202}.each do |port|
  ...
end

因为配置文件是用 Ruby 写的,我们能构造循环和其他看起来不可能的智能的东东,山一样多得运行配置文件。我需要监视 mongrel,所以我简单的循环他们的端口号,消除重复,使得我得生活更容易。

God.watch do |w|
  w.name = "gravatar2-mongrel-#{port}"
  w.start = "mongrel_rails start -c #{RAILS_ROOT} -P #{port}  \
         -P #{RAILS_ROOT}/log/mongrel.#{port}.pid -d"
  w.stop = "morgrel_rails stop -P #{RAILS_ROOT}/log/mongrel.#{port}.pid"
  w.restart = "mongrel_rails restart -P #{RAILS_ROOT}/log/mongrel.#{port}.pid"

  w.pid_file = File.join(RAILS_ROOT, "log/mongrel.#{port}.pid")

  ...
end

watch 代表一个简单的进程,包括 start, stop, 和/或 restart 操作。只要你喜欢,你就可以定义 watche。在上例中,我已经有一些 rails 实例运行在 mongrel 中,我需要 mongrel 一直运行。每个 watch 有一个独特的名字以便在后面的操作中识别。start 和 stop 属性用来指定开始和结束进程的命令。假如 restart 没有设置,restart 用一个 stop 和一个 start 代表。可选的 grace 属性设置了重置普通监视操作以前,start/stop/restart 命令等待的时间。假如你正监视的进程是一个后天进程(我的也是),你需要设置 pid_file 属性。

w.behavior(:clean_pid_file)

behavio 允许你伴随着 start/stop/restart 执行额外的命令。在我们的例子里,假如进程死了,它会留下 PID 文件。假如下次重新启动这个程序,就会启动失败,提示 PID 文件已经存在。所以启动程序时,我们想先清除 PID 文件。内建的 clean_pid_file 会清除。

w.start_if do |start|
  start.condition(:process_running) do |c|
    c.interval = 5.seconds
    c.running = false
  end
end

watch 包含由可执行的动作组成的条件应该返回 true。我用 start_if 块开始,这个块包含一个简单的条件。通过用一个识别字符调用 condition 条件来描述 condition,这个例子中是:process_running. 每个条件描述一个 poll 间隔,这个间隔将覆盖默认的间隔。这个例子中,我想要每个 5 秒钟检查一次进程,而不是像其他 condition 一样用 30 秒间隔。设置 condition poll 的间隔使得运行比不太严格的测试(如:memory_usage 和:cpu_usage)更频繁得严格测试成为可能(如:process_running).

w.restart_if do |restart|
  restart.condition(:memory_usage) do |c|
    c.above = 150.megabytes
    c.times = [3, 5]
  end

  ...
end

和 start_if 类似,restart_if 命令组合 condition,然后触发 restart。memory_usage 条件将会失败,假如指定的进程使用了太多的内存。最大允许的内存通过 above 属性来指定(你可以用 kilobytes, megabytes, 或者 gibabytes 助手)。为了触发 restart 需要触发的次数通过 times 设置。这个可以是一个整数,也可以是一个数组。整数意味着它必须连续失败许多次而数组 [x, y] 意味着必须 y 次中失败 x 次。

w.restart_if do |restart|
  ...

  restart.condition(:cpu_usage) do |c|
    c.above = 50.percent
    c.times = 5
  end
end

为了同时监视 CPU 用量,我使用了 cpu_usage 条件。当 mongrel 的 cpu 用量连续超过 50% 超过 5 次,它将会重启。

w.lifecycle do |on|
  on.condition(:flapping) do |c|
    c.to_state = [:start, :restart]
    c.times    = 5
    c.within   = 5.minute
    c.transition   = :unmonitored
    c.retry_in     = 10.minutes
    c.retry_times  = 5
    c.retry_within = 2.hours
  end
end

在 lifecycle 部分中的 condition 只要进程被监视就一直活动(它们通过状态的改变活动)。 :flapping condition 守护除了 god 快速开始和重启你的应用的这些边缘的状态的其他情况。比如服务器配置变化或者外部服务的不可用都可能造成我得进程不能启动。那样的话,god 将会一直重试启动我的进程。:flapping condition 提供了两个水平的放弃不稳定进程。假如我翻译以上的 option 代码,那就是:假如 watch 在 5 分钟里被启动或者重启了 5 次,然后不再监视它。。。然后 10 分钟后,再次监视他看看是否只是一个临时的问题;假如进程在两小时里依然不稳定,然后彻底放弃监视。

就这样!

开始和配置 GOD

如果把 god 作为一个后台进程,只需要把配置文件的路径传递给 god(你需要使用 sudo 假如你在 linux 使用 event 或者想要使用 setuid/setgid):

$ sudo god -c /path/to/config.god

当你写配置文件的时候,在前台运行 god 这样你能看见 log 消息,可能会很有帮助。你可以:

$ sudo god -c /path/to/config.god -D

你能启动、重启、停止、监测、不监测你的 watch 用同样的工具像这样:

$sudo god stop gravatar2-mongrel-8200

###监测非后台进程

需要监视一个不是后台运行的脚本?没问题!god 会为你后台话并且跟踪这个进程。假如你没有指定一个 pid_file,它会自动后台话并且将 PID 文件保存在/var/run/god.

God.pid_file_directory = '/home/tom/pids'

#自动后台化和创建pid文件
God.watch do |w|
  w.name = 'mongrel'
  w.pid_file = File.join(RAILS_ROOT, "log/mongrel.pid")

  w.start = "mongrel_rails start -P #{RAILS_ROOT}/log/mongrel.pid -d"

  #...
 end

 #不自动后台化
 God.watch do |w|
   w.name = 'worker'
   #w.pid_file = is not set

   w.start = "rake resque:worker"

   #...
 end

假如你宁愿将 PID 文件保存在不同的位置,你可以在你的配置文件顶端设置:

God.pid_file_directory = '/home/tom/pids'

目录 god 必须可写

#群组化 WATCH watch 能被分配到组。这些组可以通过命令行一起控制。

God.watch do |w|
  ...
  w.group = 'mongrels'

  ...
end

以上配置文件允许你使用一条命令控制 watch(和这个组里的其他 watch):

$ sudo god stop mongrels

重定向你进程的 STDOUT 和 STDERR

默认的,STDOUT 被定向至/dev/null. 为了进入这个输出,你可以重定向 STDOUT 流到文件或者命令。

为了重定向 STDOUT 到文件,设置 log 属性为文件路径。这个文件将以 append 模式写入,假如不存在则创建它。

God.watch do |w|
  ...
  w.log = '/var/log/myprocess.log'
  ...
end

为了重定向 STDOUT 到命令,设置 log_cmd 属性

God.watch do |w|
  ...
  w.log_cmd = '/usr/bin/logger'
  ...
end

默认地,STDERR 会重定向到 STDOUT。你也可以通过设置 err_log 和 err_log_cmd 重定向他到文件或命令。

改变进程的 UID/GID

你也可以改变 god 运行 start/stop/restart 命令的用户或群组。这个可以通过设置 uid 和 gid 来改变:

God.watch do |w|
  ...
  w.uid = 'tom'
  w.gid = 'devs'
  ...
end

仅仅对字符串有效,对 lambda 命令无效。

设置工作目录

在运行你的进程之前,God 默认会把工作目录设置到 /。(感谢@kayakjiang) 你可以改变这个通过设置 dir:

God.watch do |w|
  ...
  w.dir = '/var/www/myapp'
  ...
end

设置环境变量

你可以通过 env 属性设置任何数目的环境变量。

God.watch do |w|
  ...
  w.env = { 'RAILS_ROOT' => "/var/www/myapp",
            'RAILS_ENV'  => "production" }

  ...
end

使用 CHROOT 改变文件系统的根目录

假如你像要你的进程运行在 chroot,简单的在 watch 上使用 chroot 属性。指定的目录必须存在而且有/dev/null.

God.watch do |w|
  ...
  w.chroot = '/var/myroot'
  ...
end

Lambda 命令

另外用字符串指定 start/stop/restart 命令(为了通过 shell 执行),你也可以指定一个 lambda。

God.watch do |w|
  ...
  w.start = lambda { ENV['APACHE'] ? `apachectl -k graceful ` : `lighttpd restart` }
  ...
end

自定义默认的停止运行 lambda

假如你没有提供一个 stop 命令,God 会首先试图通过发送 SIGTERM 来停止你的进程。然后为了进程退出等待 10 秒钟。假如还没有退出,它会发送一个 SIGKILL 信号。你可以自定义 stop 信号,和/或者通过在 watch 上设置 stop_signal 和 stop_timeout 属性。

God.watch do |w|
  ...
  w.stop_signal = 'QUIT'
  w.stop_timeout = 20.seconds
  ...
end

加载其他配置文件

你可以随意的把 god 配置文件分成几个文件,这样会更容易组织文件。你也可以通过使用 Ruby 的 load 方法来加载其他的配置文件,或者使用 God.load, 它运行你使用 god 风格的路径:

#加载所有的god配置文件
God.load "/usr/local.conf/*.god"

God 直到所有的配置文件加载完才会开始监测操作。

动态加载文件进入一个已经运行的 god

God 允许你加载或者重新加载配置文件进入一个已经运行的实例。当你准备这样做得时候,有几件事情需要考虑:

  • 已经存在的 watch 会被新配置文件里的同名的 watch 覆盖
  • 所有的路径必须是绝对路径或者 god 运行的相对路径

将配置文件加载至一个正在运行的 god,运行以下命令:

$ sudo god load path/to/config.god

动态加载的配置文件可以包含任何一个普通的配置文件,然而,全局变量例如 God.pid_file_directory 块将可能会被忽视(会在日志里产生一个警告)。

为单个 watch 得到日志文件

从许多日志里筛选某个指定的 watch 的日志可能让人倍感狼狈。你可以通过以下命令得到一个实时的 log:

$ sudo god log local-3000

这条命令会展示 local-3000 的 watch 的 log,每秒更新一次。

你也可以提供一个和你的 watch 想匹配的简写 log 命令。假如碰巧匹配几个 watch,匹配缩写如下:

$ sudo god log 13

通知

God 有一个内建的可扩展的通知框架,这使得当条件被触发时发送通知变得很容易。每个通知的类型有一套必须配置的参数。这些参数通过 Contact Defaults 可能被设置成全局的,或者通过 Contact 实例设置成不同的。

Contact Defaults - 一些不可能每个 Contact 都会改变的参数。你应该通过默认的机制设置那些参数。

God::Contacts::Email.defaults do  |d|
  d.from_email = 'god@example.com'
  d.from_name  = 'God'
  d.delivery_method = :sendmail
end

Contact 实例 - 每个 contact 必须有个一独特的名字集合。你可以分配每个 contact 到一个组。

God.contact(:email) do |c|
  c.name   = 'tom'
  c.group  = 'developers'
  c.to_email = 'tom@example.com'
end

God.contact(:email) do |c|
  c.name   =  'vanpelt'
  c.group  =  'developers'
  c.to_email  = 'vanpelt@example.com'
end

God.contact(:email) do |c|
  c.name = 'kevin'
  c.group = 'developers'
  c.to_email = 'kevin@example.com'
end

Condition Attachment - 当事件触发时发送一个指定的通知,简单的设置 condition 的 notify 属性为单独的 contact。

w.transition(:up, :start) do |on|
  on.condition(:process_exits) do |c|
    c.notify = 'tom'
  end
end

有两种方法具体说明应该发送通知。第一个,容易点得方法就是上面的这种。每个 condition 可以单独设一次 notify 属性,当条件满足时触发通知。这个值可以是 contact 的名字或者 contact 的组,或者由他们组成的数组。

w.transition(:up, :start) do |on|
  on.condition(:process_exits) do |c|
    c.notify = {:contacts => ['tom', 'developers'], :priority =>1, :category=> 'product'}
  end
end

另一种方法允许你指定优先级(priority)和类别(category)。额外的属性可以是任意的整数或者字符串,然后传递到通知子系统。

上面的通知将会以一个和下面类似的邮件通知。

From: God <god@example.com> To: tom <tom@example.com> Subject: [god] mongrel-8600 [trigger] process exited (ProcessExits)

Message: mongrel-8600 [trigger] process exited (ProcessExits) Host: candymountain.example.com Priority: 1 Category: product

可用的通知方式

(god 支持 Campfire, email, Jabber, Prowl, Scout, Twitter 多种方式,而且易于扩展,这里只翻译了 Email 的方式,其他可以前往官网自行查看。)

Email

发送通知到指定的 email 地址

God::Contacts::Email.defaults do |d|
  ...
end

God.conteact(:email) do |c|
   ...
end

to_email - 字符串:发送至该 email 地址 to_name - 字符串:接收人的名字 from_email - 字符串:来自于 from_name - 字符串:来自于 delivery_method - 符号:发送的方式,[ :smtp | :sendmail ] 默认是:smtp

=== SMTP 选项 ( 当 delivery_method = :smtp) === server_host - 字符串:SMTP 服务器主机名(默认是:localhost) server_port - 整型:SMTP 服务器端口(默认为 25) server_auth - 布尔型: (默认为 false)

=== SMTP Auth 选项 (当 server_auth = true) === server_domain -字符串:域名 server_user -字符串:用户名 server_password -字符串:密码

=== Sendmail 选项 (当 delivery_method = :sendmail) === sendmail_path -字符串:sendmail 的路径(默认是“/usr/sbin/sendmail”) sendmail_args -字符串:sendmail 的参数(默认是“-i -t”)

至此,基本翻译完毕。

from https://ruby-china.org/topics/21354

(https://developer.aliyun.com/article/476580)

-------

类似工具:https://github.com/kostya/eye,Process monitoring tool. Inspired from Bluepill and God.

No comments:

Post a Comment