怎么把一个普通的进程挂入supervisor 查看进程监控树

laravel(27)
linux(37)
Supervisor是一个C/S系统,它允许用户在类UNIX系统上控制一些进程。它具有以下特性:
&&& 1&&& 简单
&&&&&&&&&&& Supervisor通过INI格式配置文件进行配置,很容易掌握,它为每个进程提供了很多配置选项,可以使你很容易的重启进程或者自动的轮转日志。
&&& 2&&& 统一
&&&&&&&&&&& Supervisor提供了一种统一的方式来start、stop、monitor你的进程, 进程可以单独控制,也可以成组的控制。你可以在本地或者远程命令行或者web接口来配置Supervisor。
&&& 3&&& 有效
&&&&&&&&&&& Supervisor通过fork/exec启动它的子进程,子进程并不是守护进程。当一个进程终止的时候,操作系统会立即给Supervisor发送一个信号,而不是像其他解决方案依赖PID文件。
&&& 4&&& 可扩展
&&&&&&&&&&& Supervisor包含一个简单的事件通知协议,因此任何程序都可以监控它,而且提供一个XML-RPC控制接口。
&&& 5&&& 兼容
&&&&&&&&&&& 除了windows平台,其他平台都可运行。
Supervisor系统的组件:
&&& supervisord:
&&&&&&& 服务会启动supervisord服务,它负责调用自己启动子程序,响应来自客户端的命令,重启crash或者退出的进程,记录进程的输出信息,收集事件信息。该服务的配置文件在/etc/supervisor/supervisord.conf
&&& supervisorctl:
&&&&&&& 客户端的命令行工具,提供一个类shell接口,通过它你可以连接到不同的supervisord进程上来管理它们各自的子程序。客户端命令通过UNIX socket或者TCP来和服务通讯,服务端可以要求客户端提供身份验证之后才能进行操作([supervisorctl])。
&&& Web Server:
&&&&&&& 一个小的web接口被集成进了supervisorctl,重启supervisord之后就可以访问了([inet_http_server])。&&&
&&& XML-RPC Interface:
&&&&&&& 就像HTTP提供WEB UI一样,同时还提供了XML-RPC接口来控制supervisor和由它运行的程序。
&&&&&&& supervisor是python编写的,显然用easy_install、pip都可以安装,我懒,直接apt-get了,在ubuntu14.04下安装完后版本是3.0b2。
Supervisor服务的启动
&&&&&&& 其实启动Supervisor很简单,supervisord -h看看就知道了,最简单的-c根配置文件即可:
supervisord -- run a set of applications as daemons.
Usage: /usr/bin/supervisord [options]
-c/--configuration FILENAME -- configuration file
-n/--nodaemon -- run in the foreground (same as 'nodaemon true' in config file)
-h/--help -- print this usage message and exit
-v/--version -- print supervisord version number and exit
-u/--user USER -- run supervisord as this user (or numeric uid)
-m/--umask UMASK -- use this umask for daemon subprocess (default is 022)
-d/--directory DIRECTORY -- directory to chdir to when daemonized
-l/--logfile FILENAME -- use FILENAME as logfile path
-y/--logfile_maxbytes BYTES -- use BYTES to limit the max size of logfile
-z/--logfile_backups NUM -- number of backups to keep when max bytes reached
-e/--loglevel LEVEL -- use LEVEL as log level (debug,info,warn,error,critical)
-j/--pidfile FILENAME -- write a pid file for the daemon process to FILENAME
-i/--identifier STR -- identifier used for this instance of supervisord
-q/--childlogdir DIRECTORY -- the log directory for child process logs
-k/--nocleanup --& prevent the process from performing cleanup (removal of
&&&&&&&&&&&&&&&&&& old automatic child log files) at startup.
-a/--minfds NUM -- the minimum number of file descriptors for start success
-t/--strip_ansi -- strip ansi escape codes from process output
--minprocs NUM& -- the minimum number of processes available for start success
--profile_options OPTIONS -- run supervisord under profiler and output
&&&&&&&&&&&&&&&&&&&&&&&&&&&& results based on OPTIONS, which& is a comma-sep'd
&&&&&&&&&&&&&&&&&&&&&&&&&&&& list of 'cumulative', 'calls', and/or 'callers',
&&&&&&&&&&&&&&&&&&&&&&&&&&&& e.g. 'cumulative,callers')
&&&&&&& 不过既然我这懒人是用apt-get安装的,那安装包的规范必然符合debian系的风格了,直接service supervisor start即可启动,且慢,我们还没配置supervisor的配置文件呢,启动了也没什么效果。我们后面详解配置文件的配置。
supervisorctl客户端的使用
&&&&&&& supervisorctl有两种模式,一种是交互模式,一种是命令行模式。在命令行输入supervisorctl直接回车,即可进入交互模式。
supervisorctl -- control applications run by supervisord from the cmd line.
Usage: /usr/bin/supervisorctl [options] [action [arguments]]
-c/--configuration -- configuration file path (default /etc/supervisor.conf)
-h/--help -- print usage message and exit
-i/--interactive -- start an interactive shell after executing commands
-s/--serverurl URL -- URL on which supervisord server is listening
&&&& (default &http://localhost:9001&).&&
-u/--username -- username to use for authentication with server
-p/--password -- password to use for authentication with server
-r/--history-file -- keep a readline history (if readline is available)
action [arguments] -- see below
Actions are commands like &tail& or &stop&.& If -i is specified or no action is
specified on the command line, a &shell& interpreting actions typed
interactively is started.& Use the action &help& to find out about available
Supervisor的开机自启动
&&&&&&& 如果你是pip或者easy_install安装的,开机服务自启动还真是个麻烦事,不过官方已经给出一些rc.d脚本示例了,在github上,不过由于我是apt-get安装的,显然这个开机自启动是不用担心的,用debian的update-rc.d即可搞定。
Supervisor的进程安全
&&&&&&& 既然是用Supervisor来保证其他进程的正常运行,但是万一Supervisor进程挂了怎么办,我们可以使用daemontools来保证Supervisor正常运行,就类似于监控的监控。
supervisord的配置文件主要由几个配置段构成,配置项以K/V格式呈现,下面就看看各个配置端需要怎样配置:
[unix_http_server]
&&& 在该配置块的参数项表示的是一个监听在socket上的HTTP server,如果[unix_http_server]块不在配置文件中,则不会启动基于socket的HTTP server。
file:一个unix domain socket的文件路径,HTTP/XML-RPC会监听在这上面
chmod:在启动时修改unix domain socket的mode
chown:修改socket文件的属主
username:HTTP server在认证时的用户名
password:认证密码&span style=&font-family:'Microsoft YaHei';font-size:16line-height:1.5;&&&/span&
[unix_http_server]
file = /tmp/supervisor.sock
chmod = 0777
chown= nobody:nogroup
username = user
password = 123
[inet_http_server]
&&& 在该配置块的参数项表示的是一个监听在TCP上的HTTP server,如果[inet_http_server]块不在配置文件中,则不会启动基于TCP的HTTP server。
port:TCP监听的地址和端口(ip:port),这个地址会被HTTP/XML-RPC监听
username:HTTP server在认证时的用户名
password:认证密码
[inet_http_server]
port = 127.0.0.1:9001
username = user
password = 123
[supervisord]
该配置块的参数项是关于supervisord进程的全局配置项。
logfile:log文件路径
logfile_maxbytes:log文件达到多少后自动进行轮转,单位是KB、MB、GB。如果设置为0则表示不限制日志文件大小
logfile_backups:轮转日志备份的数量,默认是10,如果设置为0,则不备份
loglevel:error、warn、info、debug、trace、blather、critical
pidfile:pid文件路径
umask:umask值,默认022
nodaemon:如果设置为true,则supervisord在前台启动,而不是以守护进程启动
minfds:supervisord在成功启动前可用的最小文件描述符数量,默认1024
minprocs:supervisord在成功启动前可用的最小进程描述符数量,默认200
nocleanup:防止supervisord在启动的时候清除已经存在的子进程日志文件
childlogdir:自动启动的子进程的日志目录
user:supervisord的运行用户
directory:supervisord以守护进程运行的时候切换到这个目录
strip_ansi:消除子进程日志文件中的转义序列
environment:一个k/v对的list列表
[supervisord]
logfile = /tmp/supervisord.log
logfile_maxbytes = 50MB
logfile_backups=10
loglevel = info
pidfile = /tmp/supervisord.pid
nodaemon = false
minfds = 1024
minprocs = 200
umask = 022
user = chrism
identifier = supervisor
directory = /tmp
nocleanup = true
childlogdir = /tmp
strip_ansi = false
environment = KEY1=&value1&,KEY2=&value2&
[supervisorctl]
&&& 该配置块参数是关于supervisorctl
serverurl:这个url是用来访问supervisord服务的(http://localhost:9001),或者是个sockets文件(unix:///absolute/path/to/file.sock)
username:supervisorctl连接supervisord的认证用户
password:认证密码
prompt:默认是supervisor
history_file:history文件路径
[supervisorctl]
serverurl = unix:///tmp/supervisor.sock
username = chris
password = 123
prompt = mysupervisor
[program:x]
&&& 该配置块包含一个或者多个program段,program来表明supervisord要控制哪些程序。该配置块的头部是有固定格式的,一个关键字program,后面跟着一个冒号,接下来才是程序名。例如:[program:foo],foo就是程序名,在使用supervisorctl来操作程序的时候,就是以foo来标明的。
command:启动程序使用的命令,可以是绝对路径或者相对路径
process_name:一个python字符串表达式,用来表示supervisor进程启动的这个的名称,默认值是%(program_name)s
numprocs:Supervisor启动这个程序的多个实例,如果numprocs&1,则process_name的表达式必须包含%(process_num)s,默认是1
numprocs_start:一个int偏移值,当启动实例的时候用来计算numprocs的值
priority:权重,可以控制程序启动和关闭时的顺序,权重越低:越早启动,越晚关闭。默认值是999
autostart:如果设置为true,当supervisord启动的时候,进程会自动重启。
autorestart:值可以是false、true、unexpected。false:进程不会自动重启,unexpected:当程序退出时的退出码不是exitcodes中定义的时,进程会重启,true:进程会无条件重启当退出的时候。
startsecs:程序启动后等待多长时间后才认为程序启动成功
startretries:supervisord尝试启动一个程序时尝试的次数。默认是3
exitcodes:一个预期的退出返回码,默认是0,2。
stopsignal:当收到stop请求的时候,发送信号给程序,默认是TERM信号,也可以是 HUP, INT, QUIT, KILL, USR1, or USR2。
stopwaitsecs:在操作系统给supervisord发送SIGCHILD信号时等待的时间
stopasgroup:如果设置为true,则会使supervisor发送停止信号到整个进程组
killasgroup:如果设置为true,则在给程序发送SIGKILL信号的时候,会发送到整个进程组,它的子进程也会受到影响。
user:如果supervisord以root运行,则会使用这个设置用户启动子程序
redirect_stderr:如果设置为true,进程则会把标准错误输出到supervisord后台的标准输出文件描述符。
stdout_logfile:把进程的标准输出写入文件中,如果stdout_logfile没有设置或者设置为AUTO,则supervisor会自动选择一个文件位置。
stdout_logfile_maxbytes:标准输出log文件达到多少后自动进行轮转,单位是KB、MB、GB。如果设置为0则表示不限制日志文件大小
stdout_logfile_backups:标准输出日志轮转备份的数量,默认是10,如果设置为0,则不备份
stdout_capture_maxbytes:当进程处于stderr capture mode模式的时候,写入FIFO队列的最大bytes值,单位可以是KB、MB、GB
stdout_events_enabled:如果设置为true,当进程在写它的stderr到文件描述符的时候,PROCESS_LOG_STDERR事件会被触发
stderr_logfile:把进程的错误日志输出一个文件中,除非redirect_stderr参数被设置为true
stderr_logfile_maxbytes:错误log文件达到多少后自动进行轮转,单位是KB、MB、GB。如果设置为0则表示不限制日志文件大小
stderr_logfile_backups:错误日志轮转备份的数量,默认是10,如果设置为0,则不备份
stderr_capture_maxbytes:当进程处于stderr capture mode模式的时候,写入FIFO队列的最大bytes值,单位可以是KB、MB、GB
stderr_events_enabled:如果设置为true,当进程在写它的stderr到文件描述符的时候,PROCESS_LOG_STDERR事件会被触发
environment:一个k/v对的list列表
directory:supervisord在生成子进程的时候会切换到该目录
umask:设置进程的umask
serverurl:是否允许子进程和内部的HTTP服务通讯,如果设置为AUTO,supervisor会自动的构造一个url
[program:cat]
command=/bin/cat
process_name=%(program_name)s
numprocs=1
directory=/tmp
priority=999
autostart=true
autorestart=true
startsecs=10
startretries=3
exitcodes=0,2
stopsignal=TERM
stopwaitsecs=10
user=chrism
redirect_stderr=false
stdout_logfile=/a/path
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=10
stdout_capture_maxbytes=1MB
stderr_logfile=/a/path
stderr_logfile_maxbytes=1MB
stderr_logfile_backups=10
stderr_capture_maxbytes=1MB
environment=A=&1&,B=&2&
serverurl=AUTO
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:32230次
积分:1268
积分:1268
排名:千里之外
原创:68篇
转载:176篇
(8)(7)(10)(19)(28)(9)(29)(22)(28)(5)(19)(18)(42)(3)(1)Supervisor进程监控 - 零一积流 - 博客园
yum install -y python-setuptools&
easy_install supervisor&
echo_supervisord_conf & /etc/supervisord.conf将默认配置保存在/etc/supervisord.conf中&
supervisord连接方式使用http,而不是unix socket,并设置登录验证信息。&&
添加被监控程序,被监控程序自身非后台运行&
使配置生效kill -HUP supervisord_pid&
需要注意的地方&
如果autostart设为true(默认),而被监控进程为单例模式运行,则在被监控进程已运行的情况下重启supervisord,supervisord会不停的尝试启动被监控进程,造成资源浪费。&
被监控进程的stdout和stderr输出默认被保存在单独的临时文件中,可根据需要进行配置。supervisord默认启动时会清除这些临时文件,如需要可修改配置nocleanup=true。建议将被监控进程的输出手动重定向。&
supervisord [-c /etc/supervisord.conf]&
增加到开机启动&
通过客户端命令行操作&
supervisorctl -s&&-u user -p passwd command&
通过web页面简单操作&
status [nginxes:nginx]&
reload/reread/shutdown&
start/restart/stop &proc&&
事件监听及通知机制&
supervisor向listeners发送和子进程或自身有关的notification。对于同一pool内的listeners,supervisor会选取任一可用的进行通知。&
配置被监控进程[program:x]的日志Capture Mode,被监控进程可向stdout输出业务数据,由supervisod捕获这些数据,发给listener。&
配置event-listener:监听PROCESS_COMMUNICATION_STDOUT事件&
envent-listener模块开发:使用python的supervisor.childutils模块。该模块可作为监控代理模块,和进程及网管服务通信。与网管服务可采用redis的list实现。&
XML-RPC API(待完善)&Erlang构建基于OTP的系统(五)——监控树
监控树是由进程形成的一棵树。树的顶端是监控进程,它负责监控下方的工作进程,如果工作进程崩溃了,它就会执行重启操作。监控树有两种类型:
One-for-one&监控树:在One-for-one&监控方式下,如果一个进程失效,它的监控进程就会重启它。
All-for-one&监控树:在All-for-one&监控方式下,如果一个进程失效,所有的工作进程都会被终止(通过调用回调模块的terminate/2函数)。然后所有的工作进程又重新启动。
使用OTP的supervisor行为模式可以创建一个监控进程。可以通过一个回调模块来制定监控的策略,与此同时,也要指定如何启动每一个工作进程的方法。监控树通过下面这种形式的函数来描述:
init(...)&-&
&&&&{ok,&{RestartStrategy,&MaxRestarts,&Time},
&&&&[Worker1,&Worker2,&...]}.
这里的RestartStrategy可以是one_for_one或者all_for_one。MaxRestarts和Time设定了一个“重启频率”。如果一个监控进程在Time时间内执行了超过MaxRestarts次重启,那么监控进程会终止所有的工作进程,然后退出自己。这种机制是为了避免出现这种情况:一个进程崩溃,然后重启,让后因为相同的原因又发生崩溃,如此不断反复,形成一个死循环。
Worker1,Worker2等是描述如何启动每一个工作进程的元组。我们马上就会看到它们长成什么样子。
好了,有了这些知识,我们可以回到我们的公司,构建一个监控树。
我们要做的第一件事就是要为我们的监控进程选一个名字。比如说,叫“sellaprime”,sellaprime监控进程的工作就是要保证素数服务和面积服务一直处于运行状态。要达成这一目标,我们还需要写一个回调模块。这一次要遵循gen_supervisor行为模式。这就是我们的回调模块:
sellaprime_supervisor.erl
%%&&Excerpted&from&"Programming&Erlang",&
%%&&published&by&The&Pragmatic&Bookshelf.&
%%&&Copyrights&apply&to&this&code.&It&may&not&be&used&to&create&training&material,&&
%%&&courses,&books,&articles,&and&the&like.&Contact&us&if&you&are&in&doubt.&
%%&&We&make&no&guarantees&that&this&code&is&fit&for&any&purpose.&&
%%&&Visit&/titles/jaerlang&for&more&book&information.&
-module(sellaprime_supervisor).&
-behaviour(supervisor).&&&%&see&erl&-man&supervisor&
-export([start/0,&start_in_shell_for_testing/0,&start_link/1,&init/1]).&
start()&-&&
&&&&spawn(fun()&-&&
&&&&&&supervisor:start_link({local,?MODULE},&?MODULE,&_Arg&=&[])&
&&&&end).&
start_in_shell_for_testing()&-&&
&&&&{ok,&Pid}&=&supervisor:start_link({local,?MODULE},&?MODULE,&_Arg&=&[]),&
&&&&unlink(Pid).&
start_link(Args)&-&&
&&&&supervisor:start_link({local,?MODULE},&?MODULE,&Args).&
init([])&-&&
&&&&%%&Install&my&personal&error&handler&
&&&&&gen_event:swap_handler(alarm_handler,&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{alarm_handler,&swap},&
&&&&&&&&&&&{my_alarm_handler,&xyz}),&
&&&&{ok,&{{one_for_one,&3,&10},&
&&&&[{tag1,&&
&&&&&&{area_server,&start_link,&[]},&
&&&&&&permanent,&&
&&&&&&10000,&&
&&&&&&worker,&&
&&&&&&[area_server]},&
&&&&&{tag2,&&
&&&&&&{prime_server,&start_link,&[]},&
&&&&&&permanent,&&
&&&&&&10000,&&
&&&&&&worker,&&
&&&&&&[prime_server]}&
%%&When&the&supervisor&is&started,&it&calls&init(Arg).&
%%&This&function&should&return&{ok,&{SupFlags,&Children}}.&
%%&SupFlags&:&{supervision_strategy(),&maxR(),&maxT()}&
%%&supervision_strategy()&:&one_for_one&|&one_for_all&|&simple_one_for_one&
%%&Children&:&[ChildStartSpecification]&
%%&ChildStartSpecification&:&{internal_name(),&
%%&&&&&&&&&&&&&&&&&&&&&&&&&&&&{module(),&function(),&args()},&
%%&&&&&&&&&&&&&&&&&&&&&&&&&&&&shutdown_time(),&
%%&&&&&&&&&&&&&&&&&&&&&&&&&&&&child_type(),&
%%&&&&&&&&&&&&&&&&&&&&&&&&&&&&modules()}&
%%&See&erl&-man&supervisor&for&more&details.&
%%&A&word&on&MaxR/MaxT:&
%%&Choosing&a&good&restart&frequency&is&difficult.&The&following&
%%&reasoning&might&help:&
%%&-&MaxR&should&be&low&enough&that&escalation&is&not&needlessly&delayed.&
%%&&&Remember&that&if&you&have&multiple&levels&of&supervisors,&MaxR&will&
%%&&&&you&might&want&to&set&MaxR=0&for&most&higher&supervisors.&
%%&-&MaxT&should&be&low&enough&that&unrelated&restarts&aren't&counted&as&
%%&&&looping&restart&(think:&how&long&does&it&take&for&the&effects&of&a&
%%&&&problem&to&"heal"?);&if&MaxT&is&too&low,&there&may&not&be&time&enough&
%%&&&for&MaxR&restarts.&
%%&In&general,&think&about&what&should&happen&if&a&certain&process&restars.&
%%&Some&processes&may&be&designed&as&"kernel&processes",&such&that&the&only&
%%&reasonable&course&of&action,&should&they&crash,&is&to&terminate&the&node.&
%%&I've&chosen&three&restarts&in&10&seconds.&
这里最关键的部分是init/1函数返回的数据结构:
&&&&{ok,&{{one_for_one,&3,&10},&
&&&&[{tag1,&&
&&&&&&{area_server,&start_link,&[]},&
&&&&&&permanent,&&
&&&&&&10000,&&
&&&&&&worker,&&
&&&&&&[area_server]},&
&&&&&{tag2,&&
&&&&&&{prime_server,&start_link,&[]},&
&&&&&&permanent,&&
&&&&&&10000,&&
&&&&&&worker,&&
&&&&&&[prime_server]}&
这个数据结构定义了一个监控策略。前面我们已经讨论过监控策略和重启频率的问题了。现在剩下来的也就是素数服务和面积服务的启动描述。
工作进程的描述是这样的元组:
{Tag,&{Mod,&Func,&ArgList},&Restart,
Shutdown,&Type,
这样参数的含义是:
这是一个原子,用来标记我们之后要如何来表示这个工作进程(如果有必要的话)。
{Mod,&Func,&ArgList}
这定义了监控进程是如何启动工作进程的。它会继续传递给apply(Mod,&Fun,&ArgList)。
Restart&=&permanent&|&transient&|&temporary
一个永久进程每次崩溃都会进行重启,一个瞬态进程只有在它非正常退出的情况下进行重启(退出值不是一个合法的正常退出值)。一个临时进程则不会进行重启。
这是一个终止时间。这是一个工作进程从它启动到它终止之间允许运行的时间。如果超过这个时间仍在运行,就会将其终止。(可以有其他的值,具体参考supervisor的用户手册)。
Type&=&worker&|&supervisor
这是被监控进程的类型。我们可以将一个监控进程置于另外一个监控进程的控制之下,并由此构建一个更复杂的监控树。
如果子进程是一个监控进程或gen_server行为模式的回调函数,这个名字指定了回调模块的名称(可以有其他的值,具体参考supervisor的用户手册)
这些参数看起来挺唬人的,实则不然。实际应用中,你大可以从前面的代码中拷贝粘贴这些值到你的代码中,然后稍作修改,以符合你的模块名称。这在大多数情况下都够用了。
启动整个系统
现在好了,我们已经准备就绪,期待已久的好戏就要上演。我们的公司“闪亮登场”了。谁要买第一个素数?
我们把系统跑起来:
root@controller:~/erlang_jiangjiafu#&erl&-boot&start_sasl&-config&elog3
Erlang&R14B04&(erts-5.8.5)&[source]&[64-bit]&[smp:8:8]&[rq:8]&[async-threads:0]&[kernel-poll:false]
Eshell&V5.8.5&&(abort&with&^G)
1&&sellaprime_supervisor:start_in_shell_for_testing().
***&my_alarm_handler&init:{xyz,{alarm_handler,[]}}
area_server&starting
prime_server&starting
2&&area_server:area({square,10}).
3&&area_server:area({rectangle,10,20}).
area_server&stopping
=ERROR&REPORT====&8-Apr-:32&===
**&Generic&server&area_server&terminating
**&Last&message&in&was&{area,{rectangle,10,20}}
**&When&Server&state&==&1
**&Reason&for&termination&==
**&{function_clause,[{area_server,compute_area,[{rectangle,10,20}]},
&&&&&&&&&&&&&&&&&&&&&{area_server,handle_call,3},
&&&&&&&&&&&&&&&&&&&&&{gen_server,handle_msg,5},
&&&&&&&&&&&&&&&&&&&&&{proc_lib,init_p_do_apply,3}]}
area_server&starting
**&exception&exit:&{{function_clause,[{area_server,compute_area,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&[{rectangle,10,20}]},
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{area_server,handle_call,3},
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{gen_server,handle_msg,5},
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{proc_lib,init_p_do_apply,3}]},
&&&&&&&&&&&&&&&&&&&&{gen_server,call,[area_server,{area,{rectangle,10,20}}]}}
&&&&&in&function&&gen_server:call/2
喔哦,发生了什么事?面积服务崩溃了。我们碰到了故意埋下的错误。监控进程已经检测到了这个崩溃,并重启了面积服务。这些在日志中都有记录。
崩溃之后,一切都恢复了正常,就像什么都没发生过一样。我们试试再来一个合法的查询:
4&&area_server:area({square,25}).
一切运转良好!现在,我们再来生成一个小素数:
5&&prime_server:new_prime(20).
Generating&a&20&digit&prime&..............................................
And&let's&generate&a&big&prime:
14&&prime_server:new_prime(120).
Generating&a&120&digit&prime
=ERROR&REPORT====&8-Apr-:34&===
***&Tell&the&Engineer&to&turn&on&the&fan
...............................................................................
=ERROR&REPORT====&8-Apr-:34&===
***&Danger&over.&Turn&off&the&fan
现在我们有了一个可用的系统。如果服务崩溃,会自动进行重启,而错误的情况会记录在日志当中。
我们来看看错误日志:
6&&rb:start([{max,&20}]).
rb:&reading&report...done.
rb:&reading&report...done.
{ok,&0.53.0&}
7&&rb:list().
&&No&&&&&&&&&&&&&&&&Type&&&&&&Process&&&&&&&Date&&&&&Time
&&==&&&&&&&&&&&&&&&&====&&&&&&=======&&&&&&&====&&&&&====
&&20&&&supervisor_report&&&&&&0.25.0&&&20:03:01
&&19&&&&&&&&&&&&progress&&&&&&0.25.0&&&20:03:01
&&18&&&&&&&&&&&&&&&error&&&&&&0.31.0&&&20:05:34
&&17&&&&&&&&&&&&&&&error&&&&&&0.31.0&&&20:05:34
&&16&&&&&&&&&&&&&&&error&&&&&&0.31.0&&&20:05:54
&&15&&&&&&&&&&&&&&&error&&&&&&0.31.0&&&20:05:55
&&14&&&&&&&&&&&&progress&&&&&&0.31.0&&&20:06:31
&&13&&&&&&&&&&&&progress&&&&&&0.31.0&&&20:09:56
&&12&&&&&&&&&&&&progress&&&&&&0.31.0&&&20:09:56
&&11&&&&&&&&&&&&progress&&&&&&0.31.0&&&20:09:56
&&10&&&&&&&&&&&&progress&&&&&&0.31.0&&&20:09:56
&&&9&&&&&&&&&&&&progress&&&&&&0.24.0&&&20:09:56
&&&8&&&&&&&&&&&&progress&&&&&&0.25.0&&&20:10:17
&&&7&&&&&&&&&&&&progress&&&&&&0.25.0&&&20:10:17
&&&6&&&&&&&&&&&&&&&error&&&&&&0.25.0&&&20:10:27
&&&5&&&&&&&&crash_report&&area_server&&20:10:27
&&&4&&&supervisor_report&&&&&&0.25.0&&&20:10:27
&&&3&&&&&&&&&&&&progress&&&&&&0.25.0&&&20:10:27
&&&2&&&&&&&&&&&&&&&error&&&&&&0.31.0&&&20:10:42
&&&1&&&&&&&&&&&&&&&error&&&&&&0.31.0&&&20:10:44
这里有问题。我们有一个面积服务的崩溃报告。
发生了什么事呢?(假装还不知道啦)
8&&rb:show(5).
CRASH&REPORT&&&0.44.0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&20:10:27
===============================================================================
Crashing&process
&&&initial_call&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&{area_server,init,['Argument__1']}
&&&pid&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&0.44.0&
&&&registered_name&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&area_server
&&&error_info
&&&&&&&&&{exit,
&&&&&&&&&&&&{function_clause,
&&&&&&&&&&&&&&&&[{area_server,compute_area,[{rectangle,10,20}]},
&&&&&&&&&&&&&&&&&{area_server,handle_call,3},
&&&&&&&&&&&&&&&&&{gen_server,handle_msg,5},
&&&&&&&&&&&&&&&&&{proc_lib,init_p_do_apply,3}]},
&&&&&&&&&&&&[{gen_server,terminate,6},{proc_lib,init_p_do_apply,3}]}
&&&ancestors&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&[sellaprime_supervisor,&0.41.0&]
&&&messages&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&[]
&&&links&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&[&0.43.0&]
&&&dictionary&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&[]
&&&trap_exit&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&true
&&&status&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&running
&&&heap_size&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&377
&&&stack_size&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&24
&&&reductions&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&161
{function_clause,&compute_are,...}这一句输出告诉了我们程序崩溃发生的确切位置,定位问题并进行改正并不复杂。我们继续往下看。
9&&rb:show(2).
ERROR&REPORT&&&0.35.0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&20:10:42
===============================================================================
***&Tell&the&Engineer&to&turn&on&the&fan
10&&rb:show(1).
ERROR&REPORT&&&0.35.0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&20:10:44
===============================================================================
***&Danger&over.&Turn&off&the&fan
这是计算大素数时产生的风扇警报。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 supervisor重启进程 的文章

 

随机推荐