Linux Monitor 进程管理操作梳理
Monit对运维人员来说可谓神器,它是一款功能非常丰富的进程、文件、目录和设备的监测工具,用于Unix平台。它可以自动修复那些已经停止运作的程序,特使适合处理那些由于多种原因导致的软件错误。
Monit不但本地监控十分有效,还可以监控远程服务,只要花点功夫就能永远实现服务的“死而复生”,就是说它可以使它监控的服务程序在宕停后迅速自启动,不需要人工干预。绝对牛X的一款系统监控神奇!
比如下面两个场景:
1)持续邮件提醒
默认情况下,如果服务Down了,无论它持续Down了多久,Monit程序只会邮件提醒你一次。下一次提醒,就是服务恢复的时候。
如果希望,在多个周期内,即使服务状态没有变化(持续宕机着),也能收到邮件提醒,那么加上这句:
alert foo@bar with reminder on 10 cycles 此句表示,在10个周期内都会邮件提醒。
2)误报提醒解决
有些时候,Monit也会误报,这很正常,任何监控软件都会。大多数是由于网络状况不佳。比如某一个服务,Monit发现停了,又迅速启动了,那就不要来烦了,别总是一封邮件接着一封。这样设置:
if failed host 172.16.5.1 port 8599 for 3 times within 4 cycles then alert 这样就是:若在四个周期内,三次 8599(我的电驴口)端口都无法通,则邮件通知。很方便!
废话不多说,下面对monit监控环境的部署做一梳理:
需求说明:
随着线上服务器数量的增加,各种开源软件和工具的广泛使用,一些服务自动停止或无响应的情况时有发生,其中有很大一部分是由于软件自身的稳定性或者机器硬件资源限制而造成的。按道理来讲,这些情况都应该设法找到本质原因,然后避免再次出现。但现实是残酷的,不少软件本身的稳定性有待提升,机器的硬件资源提升会触及成本,因此在集群的环境中,具备冗余,使得执行简单的服务重启成为了最现实的选择。这本身不是什么困难的事情,实现的方法有很多,比如在Zabbix或Nagios的报警中增加Action或Commands,或自己写脚本放到计划任务中执行都可以。然而下面要介绍的就是专门来做这种事情的一个工具:Monit。它最大的特点是配置文件简单易读,同时支持进程和系统状态的监控,并灵活的提供了各种检测的方式,周期,并进行报警和响应(重启服务,执行命令等)
Centos6下部署Monit环境过程:
1)安装EPEL仓库
[root@bastion-IDC src]# wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm
[root@bastion-IDC src]# rpm -ivh epel-release-latest-6.noarch.rpm
2)安装monit
[root@bastion-IDC src]# yum install -y monit
--------------------------------------------------------------------------------------------------------------
源码安装包下载:https://mmonit.com/monit/dist/binary/
# wget https://mmonit.com/monit/dist/binary/5.20.0/monit-5.20.0-linux-x86.tar.gz
# tar -zvxf monit-5.20.0-linux-x86.tar.gz
# mv monit-5.20.0 /usr/local/monit
# cp /usr/local/monit/conf/monitrc /etc/
然后编辑配置文件/etc/monitrc即可。centos6的配置文件是monit.conf,centos7的配置文件是monitrc
-------------------------------------------------------------------------------------------------------------
3)monit配置说明(官网配置说明:https://mmonit.com/monit/documentation/monit.html)
Monit配置文件/etc/monit.conf,可以将默认配置文件备份下,然后自定义配置
[root@bastion-IDC src]# cp /etc/monit.conf /etc/monit.conf.bak
[root@bastion-IDC src]# cat /etc/monit.conf //自定义配置如下
set daemon 120 #Poll at 2-minute intervals //每2分钟检查一次,单位为秒;monit做不到实时监控。
set logfile /home/monit/log/monit.log //monit的日志文件
set alert zhouwei@chinabank.com.cn with reminder on 1 cycle //出现1次错误就发报警邮件到指定邮箱。多个邮箱地址就配置多行;with后的配置可以不加。
#set mailserver mail.tildeslash.com, mail.foo.bar port 10025, localhost with timeout 15 seconds
set mailserver 10.10.9.109 //设置邮件服务器
set httpd port 2812 and use address 10.10.8.2 //设置http监控页面的端口和ip
allow localhost #Allow localhost to connect //允许本机访问
allow 10.10.8.0/24 //允许此IP段访问
allow admin:nishiwode #Allow Basic Auth //认证的用户名和密码
# all system //平均负载.内存使用率,cpu使用率
check system 10.10.8.2
if loadavg (1min) > 4 then alert
if loadavg (5min) > 2 then alert
if memory usage > 75% then alert
if cpu usage (user) > 70% then alert
if cpu usage (system) > 30% then alert
if cpu usage (wait) > 20% then alert
# all disk //磁盘空间使用率
check device data with path /dev/sda2
if space usage > 90% then alert
if inode usage > 85% then alert
check device home with path /dev/sda3
if space usage > 85% for 5 cycles then alert //如果在5个监控周期内,space使用率超过85%就发报警邮件
if inode usage > 85% for 5 cycles then alert
# all rsync
#10.10.8.2
check process sshd with pidfile /var/run/sshd.pid //监控ssh服务
start program "/etc/init.d/sshd start"
stop program "/etc/init.d/sshd stop"
if failed host 127.0.0.1 port 22 protocol ssh then restart
if 3 restarts within 5 cycles then timeout //设置在5个监控周期内重启3次则超时,那么就不再监控这个服务程序
check process httpd with pidfile /var/run/httpd.pid //监控http服务
start program = "/etc/init.d/httpd start"
stop program = "/etc/init.d/httpd stop"
if failed host 127.0.0.1 port 80 protocol http then restart
if 5 restarts within 5 cycles then timeout
check process web_lb with pidfile /data/v20/server/web_lb/httpd.pid //监控自定义服务
start program = "/data/v20/bin/lb.sh" //启动脚本
stop program = "/data/v20/bin/lb_stop.sh" //停止脚本
if failed host 10.10.8.2 port 16101 proto http then restart
if failed host 10.10.8.2 port 16101 proto http for 5 times within 5 cycles then exec "/data/v20/bin/lb_pay.sh"
if failed host 10.10.8.2 port 16102 type TCPSSL proto http then restart
if failed host 10.10.8.2 port 16102 type TCPSSL proto http for 5 times within 5 cycles then exec "/data/v20/bin/lb_pay.sh
4)monit的启动(monit的默认端口是30000。最好在本地的/etc/hosts里面做下本机主机名的映射关系,将hostname映射到127.0.0.1)
[root@bastion-IDC src]# /etc/init.d/monit start/stop/reload/status/restart
[root@bastion-IDC ~]# monit -t //检测monit配置是否正确
[root@bastion-IDC ~]# monit reload //重载monit配置
[root@bastion-IDC ~]# monit status //查看monit进程监控情况
若启动monit的时候报错如下:
Cannot translate 'huanqiu_web2' to FQDN name -- Name or service not known Generated unique Monit id af76cbce671f323782e09e0d114857fd and stored to '/root/.monit.id' Reinitializing monit daemon No daemon process found 解决办法: 在本机的/etc/hosts里面做下主机映射,即 127.0.0.1 huanqiu_web2
---------------------------------------------线上用过的一个配置------------------------------------------------
[root@huanqiu_web1 ~]# cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 127.0.0.1 huanqiu_web1 [root@huanqiu_web1 ~]# cat /etc/monit.conf set daemon 30 set logfile syslog facility log_daemon set pidfile /var/run/monit.pid set httpd port 30000 use address 127.0.0.1 allow 127.0.0.1 check process nginx with pidfile /Data/app/nginx/logs/nginx.pid start program = "/Data/app/nginx/sbin/nginx" stop program = "/Data/app/nginx/sbin/nginx -s stop" check process php-fpm with pidfile /Data/app/php5.6.26/var/run/php-fpm.pid start program = "/Data/app/php5.6.26/sbin/php-fpm" stop program = "/bin/bash -c 'kill -s SIGTERM `ps -ef|grep /Data/app/php5.6.26/etc/php-fpm.conf|grep -v grep|awk -F" " '{print $2}'`'" check process mysql with pidfile /Data/app/mysql5.1.57/var/dev-new-test.pid start program = "/Data/app/mysql5.1.57/bin/mysqld_safe --defaults-file=/Data/app/mysql5.1.57/my.cnf &" stop program = "/bin/bash -c 'kill -s SIGTERM `ps -ef|grep mysqld_safe|grep -v grep|awk -F" " '{print $2}'`'" check process tomcat-7-admin-wls matching "/Data/app/tomcat-7-wls/conf" start program = "/Data/app/tomcat-7-wls/bin/startup.sh" stop program = "/bin/bash -c 'kill -s SIGTERM `ps -ef|grep /Data/app/tomcat-7-wls/conf|grep -v grep|awk -F" " '{print $2}'`'" check process tomcat-7-wls matching "/Data/app/tomcat-7-wls/conf" start program = "/Data/app/tomcat-7-wls/bin/startup.sh" stop program = "/bin/bash -c 'kill -s SIGTERM `ps -ef|grep /Data/app/tomcat-7-wls/conf|grep -v grep|awk -F" " '{print $2}'`'" check process tomcat-7 matching "/Data/app/tomcat-7/conf" start program = "/Data/app/tomcat-7/bin/startup.sh" stop program = "/bin/bash -c 'kill -s SIGTERM `ps -ef|grep /Data/app/tomcat-7/conf|grep -v grep|awk -F" " '{print $2}'`'" check process tomcat-7-banshanbandao matching "/Data/app/tomcat-7-banshanbandao/conf" start program = "/Data/app/tomcat-7-banshanbandao/bin/startup.sh" stop program = "/bin/bash -c 'kill -s SIGTERM `ps -ef|grep /Data/app/tomcat-7-banshanbandao/conf|grep -v grep|awk -F" " '{print $2}'`'" check process vpn matching "/etc/vpnc/vpnc-script" start program = "/bin/sh /bin/vpn_start" stop program = "/bin/bash -c 'kill -s SIGTERM `ps -ef|grep vpnc-script|grep -v grep|awk -F" " '{print $2}'`'" [root@huanqiu_web1 ~]# monit -t Control file syntax OK [root@huanqiu_web1 ~]# /etc/init.d/monit start Starting monit: [ OK ] [root@huanqiu_web1 ~]# lsof -i:30000 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME monit 6109 root 5u IPv4 2438183462 0t0 TCP localhost:30000 (LISTEN) [root@huanqiu_web1 ~]# monit reload Reinitializing monit daemon [root@huanqiu_web1 ~]# monit status The Monit daemon 5.14 uptime: 8m Process 'nginx' status Running monitoring status Monitored pid 499 parent pid 1 uid 0 effective uid 0 gid 0 uptime 28d 20h 17m children 8 memory 19.6 MB memory total 381.6 MB memory percent 0.0% memory percent total 0.5% cpu percent 0.0% cpu percent total 0.0% data collected Wed, 22 Mar 2017 11:32:42 Process 'php-fpm' status Running monitoring status Monitored pid 3153 parent pid 1 uid 0 effective uid 0 gid 0 uptime 43d 19h 26m children 16 memory 8.7 MB memory total 352.3 MB memory percent 0.0% memory percent total 0.5% cpu percent 0.0% cpu percent total 0.1% data collected Wed, 22 Mar 2017 11:32:42 Process 'mysql' status Running monitoring status Monitored pid 46403 parent pid 46254 uid 500 effective uid 500 gid 500 uptime 93d 0h 34m children 0 memory 317.8 MB memory total 317.8 MB memory percent 0.4% memory percent total 0.4% cpu percent 0.0% cpu percent total 0.0% data collected Wed, 22 Mar 2017 11:32:42 Process 'tomcat-7-admin-wls' status Running monitoring status Monitored pid 34188 parent pid 1 uid 0 effective uid 0 gid 0 uptime 4d 19h 15m children 0 memory 803.6 MB memory total 803.6 MB memory percent 1.2% memory percent total 1.2% cpu percent 0.0% cpu percent total 0.0% data collected Wed, 22 Mar 2017 11:32:42 Process 'tomcat-7-wls' status Running monitoring status Monitored pid 34188 parent pid 1 uid 0 effective uid 0 gid 0 uptime 4d 19h 15m children 0 memory 803.6 MB memory total 803.6 MB memory percent 1.2% memory percent total 1.2% cpu percent 0.0% cpu percent total 0.0% data collected Wed, 22 Mar 2017 11:32:42 Process 'tomcat-7' status Running monitoring status Monitored pid 14524 parent pid 1 uid 0 effective uid 0 gid 0 uptime 5d 21h 43m children 0 memory 581.2 MB memory total 581.2 MB memory percent 0.9% memory percent total 0.9% cpu percent 0.0% cpu percent total 0.0% data collected Wed, 22 Mar 2017 11:32:42 Process 'tomcat-7-banshanbandao' status Running monitoring status Monitored pid 29217 parent pid 1 uid 0 effective uid 0 gid 0 uptime 117d 0h 35m children 0 memory 1.4 GB memory total 1.4 GB memory percent 2.1% memory percent total 2.1% cpu percent 0.0% cpu percent total 0.0% data collected Wed, 22 Mar 2017 11:32:42 Process 'vpn' status Running monitoring status Monitored pid 13774 parent pid 1 uid 0 effective uid 0 gid 0 uptime 1h 36m children 0 memory 2.4 MB memory total 2.4 MB memory percent 0.0% memory percent total 0.0% cpu percent 0.0% cpu percent total 0.0% data collected Wed, 22 Mar 2017 11:32:42 System 'huanqiu_web1' status Running monitoring status Monitored load average [0.00] [0.04] [0.09] cpu 0.6%us 0.1%sy 0.0%wa memory usage 5.1 GB [8.0%] swap usage 0 B [0.0%] data collected Wed, 22 Mar 2017 11:32:42
5)monit监控程序进程的方式
a)利用进程的pid文件进行监控:with pidfile
b)利用进程的关键字匹配方式进行监控: matching;可以使用“monit procmatch 进程名 CLI”来查找要匹配的唯一关键字
不管是pid文件里的pid号还是进程的关键字,都要求是唯一性的!必须是唯一的,如果matching匹配字段不唯一,那么监控无效!
下面罗列几个平时工作中常用的几个监控项:
[root@bastion-IDC ~]# cat /etc/monit.conf
set daemon 30 set logfile syslog facility log_daemon set pidfile /var/run/monit.pid set httpd port 30000 use address 127.0.0.1 allow 127.0.0.1 ............ check process nginx with pidfile /usr/local/nginx/logs/nginx.pid start program = "/usr/local/nginx/sbin/nginx" stop program = "/usr/local/nginx/sbin/nginx -s stop" check process nginx with pidfile /webserver/nginx/run/nginx.pid start program = "/webserver/init.d/nginx start" with timeout 10 seconds stop program = "/webserver/init.d/nginx stop" if failed host heylinux.com port 80 protocol http with timeout 10 seconds then restart if 3 restarts within 5 cycles then timeout group webserver check process php-fpm with pidfile /var/run/php-fpm/php-fpm.pid start program = "/etc/init.d/php-fpm start" stop program = "/etc/init.d/php-fpm stop" check process mysqld with pidfile "/letv/mysql2/data/cdn.oss.letv.com.pid" start program = "/etc/init.d/mysqld start" stop program = "/etc/init.d/mysqld stop" if failed host 127.0.0.1 port 3306 then restart check process mysql with pidfile /webserver/mysql/run/mysqld.pid start program = "/webserver/init.d/mysqld start" with timeout 10 seconds stop program = "/webserver/init.d/mysqld stop" if failed port 3307 protocol mysql with timeout 10 seconds then restart if 3 restarts within 5 cycles then timeout group webserver check process memcached with pidfile "/var/run/memcached/memcached.pid" start program = "/etc/init.d/memcached start" stop program = "/etc/init.d/memcached stop" if failed host 127.0.0.1 port 11211 protocol memcache then restart check process zabbix with pidfile "/usr/local/zabbix/zabbix_agentd.pid" start program = "/usr/local/zabbix/sbin/zabbix_agentd -c /usr/local/zabbix/conf/zabbix_agentd.conf" stop program = "/bin/bash -c 'kill -s SIGTERM `cat /usr/local/zabbix/zabbix_agentd.pid`'" if failed host 127.0.0.1 port 10050 type tcp 2 times within 2 cycles then restart check process httpd with pidfile "/usr/local/apache/logs/httpd.pid" start program = "/usr/local/apache/bin/httpd -k start" stop program = "/bin/bash -c 'kill -s SIGTERM `cat /usr/local/apache/logs/httpd.pid`'" check process redis with pidfile "/var/run/redis.pid" start program = "/usr/local/bin/redis-server /letv/uss/redis/redis.conf" stop program = "/bin/bash -c 'kill -s SIGTERM `cat /var/run/redis.pid`'" check process rsync with pidfile "/var/run/rsyncd.pid" start program = "/usr/bin/rsync --daemon" stop program = "/bin/bash -c 'kill -s SIGTERM `cat /var/run/rsyncd.pid`'" check process pytask.py matching "/letv/p2sp/offline/pytask.py" start program = "/usr/bin/python /letv/p2sp/offline/pytask.py" stop program = "/bin/bash -c 'kill -s SIGTERM `ps -ef|grep offline/pytask.py|grep -v grep|awk -F" " '{print $2}'`'" check process pytimed.py matching "/letv/p2sp/offline/pytimed.py" start program = "/usr/bin/python /letv/p2sp/offline/pytimed.py" stop program = "/bin/bash -c 'kill -s SIGTERM `ps -ef|grep offline/pytimed.py|grep -v grep|awk -F" " '{print $2}'`'" check process hadoop with pidfile "/usr/local/hadoop/pids/hadoop-hadoop-datanode.pid" start program = "/usr/bin/sudo -u hadoop -i hadoop-daemon.sh start datanode" stop program = "/usr/bin/sudo -u hadoop -i hadoop-daemon.sh stop datanode" check process ETMDaemon matching "/letv/p2sp/xware/lib/ETMDaemon" start program = "/letv/p2sp/xware/portal" stop program = "/bin/bash -c 'kill -s SIGTERM `ps -ef|grep ETMDaemon|grep -v grep |awk '{print $2}'`'"
如果监控配置项比较多,不想放在/etc/monit.conf文件里,那么可以定义include选项,比如:
[root@bastion-IDC ~]# vim /etc/monit.conf
.......
include /etc/services.cfg
然后创建/etc/services.cfg,将监控进程的配置集中放到这个文件里。
[root@bastion-IDC ~]# vim /etc/services.cfg check process nginx with pidfile /usr/local/nginx/logs/nginx.pid start program = "/usr/local/nginx/sbin/nginx" stop program = "/usr/local/nginx/sbin/nginx -s stop" check process php-fpm with pidfile /var/run/php-fpm/php-fpm.pid start program = "/etc/init.d/php-fpm start" stop program = "/etc/init.d/php-fpm stop" check process mysqld with pidfile "/letv/mysql2/data/cdn.oss.letv.com.pid" start program = "/etc/init.d/mysqld start" stop program = "/etc/init.d/mysqld stop" .........
monit.conf文件里的邮件通知就可以这样配置:
# mail-server set mailserver smtp.huanqiu.cn port 587 # email-format set mail-format { from: monit@huanqiu.cn subject: $SERVICE $EVENT at $DATE on $HOST message: Monit $ACTION $SERVICE $EVENT at $DATE on $HOST : $DESCRIPTION. Yours sincerely, Monit } set alert wangshibo@huanqiu.cn
Monit会提供几个内部变量($DATE、$EVENT、$HOST等),你可以按照你的需求自定义邮件内容。如果你想要从Monit所在机器发送邮件,就需要一个已经安装的与sendmail兼容的程序(如postfix或者ssmtp)。
监控本机部分性能:
check system 127.0.0.1 if loadavg (5min) > 4 for 4 times 5 cycles then exec "/etc/monit/script/sendsms sysload 5min >4" if memory usage > 90% then exec "/etc/monit/script/sendsms 127.0.0.1 memory useage>90%" if cpu usage (user) > 70% for 4 times within 5 cycles then exec "/etc/monit/script/sendsms cpu(user) >70%" if cpu usage (system) > 30% for 4 times within 5 cycles then exec "/etc/monit/script/sendsms cpu(system) >30% " if cpu usage (wait) > 20% for 4 times within 5 cycles then exec "/etc/monit/script/sendsms system busy! cpu(wait) >20%"
监控远程机器的部分端口:
check host Unicom_mobi with address 211.90.246.51 if failed icmp type echo count 10 with timeout 20 seconds then exec "/etc/monit/script/sendsms Unicom_mobi 211.90.246.51 ping failed!" if failed port 22 type tcp with timeout 10 seconds for 2 times within 3 cycles then exec "/etc/monit/script/sendsms unicom 211.90.246.51:2222 connect failed!" if failed port 9528 type tcp with timeout 10 seconds for 2 times within 3 cycles then exec "/etc/monit/script/sendsms unicom 211.90.246.51:9528 connect failed!" if failed port 9529 type tcp with timeout 10 seconds for 2 times within 3 cycles then exec "/etc/monit/script/sendsms unicom 211.90.246.51:9529 connect failed!" if failed port 9530 type tcp with timeout 10 seconds for 2 times within 3 cycles then exec "/etc/monit/script/sendsms unicom 211.90.246.51:9530 connect failed!"
monit好处是可以在监控故障设置重启服务和执行自定义脚本,如下
check filesystem root with path /dev/mapper/VolGroup00-LogVol00 if space usage > 80% for 5 times within 15 cycles then exec "/etc/monit/script/clear_core.sh" else if succeed for 1 times within 2 cycles then exec "/etc/monit/script/sendsms '/dev/sda1 usage > 90% clear core file succeed!'>/dev/null 2"
再来看看几个小配置:
1)监控本地服务器的CPU、内存占用 check system localhost if loadavg (1min) > 10 then alert if loadavg (5min) > 6 then alert if memory usage > 75% then alert if cpu usage (user) > 70% then alert if cpu usage (system) > 60% then alert if cpu usage (wait) > 75% then alert 如果某个监控项不需要每个周期都检查,可以如下配置: if loadavg (1min) > 10 for 2 cycles then alert 2)设置一个检查远程SMTP服务器(如192.168.1.102)的监控。假定SMTP服务器运行着SMTP、IMAP、SSH服务。 check host MAIL with address 192.168.1.102 if failed icmp type echo within 10 cycles then alert if failed port 25 protocol smtp then alert else if recovered then exec "/scripts/mail-script" if failed port 22 protocol ssh then alert if failed port 143 protocol imap then alert 检查远程主机是否响应ICMP协议。如果我们在10个周期内没有收到ICMP回应,就发送一条报警。如果监测到25端口上的SMTP协议是异常的,就发送一条报警。如果在一次监测失败后又监测成功了,就运行一个脚本(/scripts/mail-script)。如果检查22端口上的SSH或者143端口上的IMAP协议不正常,同样发送报警。 3)存在性测试: Monit当发现一个文件不存或者一个服务没有启动的时候默认操作是重启这个操作 check file with path /home/laicb/test.txt if does not exist for 5 cycles then alert 注意: 检测的是文件(使用的是path),如果只写了/home/laicb那么监视的时候就会提示,path不是一个有效的类型! 如果检测目录的话,就用directory替换path 4)资源测试: 有些资源可以在check system路口,有些可以在check entry路口,有些都可以。 if cpu is greater than 50% for 5 cycles then restart 注意:greater表示大于,%也可以用字节或者GB,MB等字符 5)时间戳测试: 时间戳[1]是指文件属性里的创建、修改、访问的时间。(下面的exec表示执行后面的命令动作) 改变形式: check file httpd.conf with path /usr/local/apache/conf/httpd.conf if changed timestamp then exec "/usr/local/apache/bin/apachectl graceful" 常量模式: check file stored.ckp with path /msg-foo/config/stored.ckp if timestamp > 1 minute then alert 6)文件大小测试: 这个只能用在check file入口 check file with path /home/laicb/test.txt if does not exist for 5 cycles then alert if changed size for 1 cycles then alert //如果没有指定,查看服务所对应的会发现是for 5 times within 5cycles 如果更改文件大小,那么文件大小变化之后就在状态栏里显示size changed 7)权限测试: check file monit.bin with path "/usr/local/bin/monit" if failed permission 0555 then unmonitor //如果/usr/local/bin/monit文件权限不是555就拒绝执行 check file passwd with path /etc/passwd if failed uid root then unmonitor //如果不是root访问/etc/passwd那么拒绝访问 8)PID测试 check process sshd with pidfile /var/run/sshd.pid if changed pid then exec "/my/script" 9)更新时间测试: 正常运行时间测试: check process myapp with pidfile /var/run/myapp.pid start program = "/etc/init.d/myapp start" stop program = "/etc/init.d/myapp stop" if uptime > 3 days then restart 10)监控主机通信 check host www.huanqiu.com with address www.huanqiu.com if failed icmp type echo count 5 with timeout 15 seconds then alert 11)apache程序监控 check process apache with pidfile /var/run/httpd.pid start program = "/etc/init.d/httpd start" stop program = "/etc/init.d/httpd stop" if cpu > 40% for 2 cycles then alert if totalcpu > 60% for 2 cycles then alert if totalcpu > 80% for 5 cycles then restart if mem > 100 MB for 5 cycles then stop if loadavg(5min) greater than 10.0 for 8 cycles then stop
-------------------------------------------------------------------------------------------
来看看下面遇到的几种monit不能使用的解决办法:
1)monit进程连接错误!(缺少http的端口支持,少了这部分内容)
最后经过排查发现,monit的配置文件/etc/monitrc里面少了下面两行:
set httpd port 30000
allow 127.0.0.1
将上面两行添加上,monit即可恢复正常使用状态中
[root@cdn ~]# cat /etc/monitrc
set daemon 30
set logfile syslog facility log_daemon
set pidfile /var/run/monit.pid
set httpd port 30000
allow 127.0.0.1
#allow admin:TVA3z3i
..........
2)另外一种错误:(修改127.0.0.1为localhost)
在monit -t和monit reload都没有报错的情况下,monit status报错如下:
[root@cdn ~]# monit status
monit: cannot read status from the monit daemon
查看日志信息:
[root@cdn ~]# tail -f /var/log/messages
Aug 18 19:27:21 cdn monit[14491]: monit: Denied connection from non-authorized client [220.181.153.243]
Aug 18 19:27:21 cdn monit[16899]: monit: cannot read status from the monit daemon
解决办法:
将monit配置文件中的“allow 127.0.0.1”修改为“allow localhost”即可!!
[root@cdn ~]# vim /etc/monitrc
set daemon 30
set logfile syslog facility log_daemon
set pidfile /var/run/monit.pid
set httpd port 30000
allow localhost
.........
这样,问题得到解决
[root@cdn ~]# monit status
The Monit daemon 5.3.2 uptime: 5m
.........................
Process 'nginx_down'
status Running
monitoring status Monitored
pid 18671
parent pid 1
uptime 145d 5h 17m
children 8
memory kilobytes 484
memory kilobytes total 4572
memory percent 0.0%
memory percent total 0.0%
cpu percent 0.0%
cpu percent total 0.0%
data collected Mon, 18 Aug 2014 19:34:25
.............
3)下面的错误在使用上面两种方法后,仍不能解决问题! (添加use address 127.0.0.1)
[root@182 conf]# monit -t
Control file syntax OK
[root@182 conf]# monit reload
Reinitializing monit daemon
[root@182 conf]# monit status
monit: error connecting to the monit daemon
查看monit配置文件
[root@182 conf]# cat /etc/monitrc.bak
set daemon 30
set httpd port 30000
allow 127.0.0.1
set logfile syslog facility log_daemon
set pidfile /var/run/monit.pid
..................
最后解决办法:
需要在monit配置文件中添加“use address 127.0.0.1"内容!
[root@182 conf]# cat /etc/monitrc
set daemon 30
set httpd port 30000
use address 127.0.0.1
allow 127.0.0.1
set logfile syslog facility log_daemon
set pidfile /var/run/monit.pid
.............
查看,问题已经得到解决
[root@182 conf]# monit status
The Monit daemon 5.3.2 uptime: 7m
..............
Process 'rsync'
status Running
monitoring status Monitored
pid 13519
parent pid 1
uptime 393d 9h 8m
children 0
memory kilobytes 540
memory kilobytes total 540
memory percent 0.0%
memory percent total 0.0%
cpu percent 0.0%
cpu percent total 0.0%
data collected Thu, 21 Aug 2014 19:24:58
..............
注意:
上面的第3钟方式是最全面的,如果添加了use address 127.0.0.1后,使用monit status仍然出现下面的情况:
[root@ly-u-gfs1 ~]# monit status
monit: error connecting to the monit daemon
那么就稍微等待一会儿,等一小段时间后,就会发现monit使用顺畅了
[root@ly-u-gfs1 ~]# monit status
The Monit daemon 5.3.2 uptime: 6m
Process 'net-snmp'
status Running
monitoring status Monitored
-------------------------------------------------------------------------------------------------------------------------
Centos7下部署Monit环境过程:
[root@linux-node2 ~]# yum update
[root@linux-node2 ~]# yum install -y monit
[root@linux-node2 ~]# rpm -ql monit
/etc/logrotate.d/monit
/etc/monit.d
/etc/monit.d/logging
/etc/monitrc
/usr/bin/monit
/usr/lib/systemd/system/monit.service
/usr/share/doc/monit-5.14
/usr/share/doc/monit-5.14/COPYING
/usr/share/doc/monit-5.14/README
/usr/share/man/man1/monit.1.gz
/var/log/monit.log
[root@linux-node2 ~]# monit -V
This is Monit version 5.14
Copyright (C) 2001-2016 Tildeslash Ltd. All Rights Reserved.
[root@linux-node2 ~]# monit -v
Adding host allow 'localhost'
Skipping redundant host 'localhost'
Adding credentials for user 'admin'
Runtime constants:
Control file = /etc/monitrc
Log file = /var/log/monit.log
Pid file = /run/monit.pid
Id file = /root/.monit.id
State file = /root/.monit.state
Debug = True
Log = True
Use syslog = False
Is Daemon = True
Use process engine = True
Poll time = 30 seconds with start delay 0 seconds
Expect buffer = 256 bytes
Mail from = (not defined)
Mail subject = (not defined)
Mail message = (not defined)
Start monit httpd = True
httpd bind address = localhost
httpd portnumber = 2812
httpd ssl = Disabled
httpd signature = Enabled
httpd auth. style = Basic Authentication and Host/Net allow list
The service list contains the following entries:
System Name = linux-node2.openstack
Monitoring mode = active
查看默认的配置文件内容
[root@linux-node2 ~]# grep -v '^#' /etc/monitrc
set daemon 30 # check services at 30 seconds intervals
set logfile syslog
set httpd port 2812 and
use address localhost # only accept connection from localhost
allow localhost # allow localhost to connect to the server and
allow admin:monit # require user 'admin' with password 'monit'
allow @monit # allow users of group 'monit' to connect (rw)
allow @users readonly # allow users of group 'users' to connect readonly
include /etc/monit.d/*
[root@linux-node2 ~]# cat /etc/logrotate.d/monit
/var/log/monit.log {
missingok
notifempty
size 100k
create 0644 root root
postrotate
/bin/systemctl reload monit.service > /dev/null 2>&1 || :
endscript
}
[root@linux-node2 ~]# cat /etc/monit.d/logging
# log to monit.log
set logfile /var/log/monit.log //监视周期为60秒,日志输出及日志滚动以配置好了
配置monit
[root@linux-node2 ~]# vim /etc/monitrc
set daemon 5 set logfile syslog set httpd port 2812 and use address localhost allow localhost allow admin:monit allow @monit allow @users readonly include /etc/monit.d/* check process sshd with pidfile /var/run/sshd.pid start program "/usr/bin/systemctl start sshd.service" stop program "/usr/bin/systemctl stop sshd.service" if failed port 22 protocol ssh then restart if 5 restart within 5 cycles then timeout check process apache with pidfile /etc/httpd/run/httpd.pid start program = "/usr/bin/systemctl start httpd" with timeout 60 seconds stop program = "/usr/bin/systemctl stop httpd" if failed host linux-node2.openstack port 80 protocol http and request "/readme.html" then restart if 3 restarts within 5 cycles then timeout group apache check process mariadb with pidfile "/var/lib/mysql/linux-node2.pid" start = "/usr/bin/systemctl start mariadb.service" stop = "/usr/bin/systemctl stop mariadb.service" if failed host 127.0.0.1 port 3306 protocol mysql then restart if 5 restarts within 5 cycles then timeout
----------------------------------------------------------------------------------------------
查看mysql服务的pid
MariaDB [(none)]> show variables like "%pid%";
+---------------+--------------------------------+
| Variable_name | Value |
+---------------+--------------------------------+
| pid_file | /var/lib/mysql/linux-node2.pid |
+---------------+--------------------------------+
1 row in set (0.00 sec)
--------------------------------------------------------------------------------------------
启动monit
[root@linux-node2 ~]# systemctl enable monit.service
Created symlink from /etc/systemd/system/multi-user.target.wants/monit.service to /usr/lib/systemd/system/monit.service.
[root@linux-node2 ~]# systemctl start monit.service
[root@linux-node2 ~]# lsof -i:2812
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
monit 89106 root 5u IPv4 172788270 0t0 TCP localhost:atmtcp (LISTEN)
[root@linux-node2 ~]# systemctl status monit.service
● monit.service - Pro-active monitoring utility for unix systems
Loaded: loaded (/usr/lib/systemd/system/monit.service; enabled; vendor preset: disabled)
Active: active (running) since Fri 2017-02-03 10:47:22 CST; 50s ago
Main PID: 89106 (monit)
CGroup: /system.slice/monit.service
└─89106 /usr/bin/monit -I
Feb 03 10:47:22 linux-node2.openstack systemd[1]: Started Pro-active monitoring utility for unix systems.
Feb 03 10:47:23 linux-node2.openstack systemd[1]: Starting Pro-active monitoring utility for unix systems...
Feb 03 10:47:23 linux-node2.openstack monit[89106]: /etc/monitrc:20: Program does not exist: 'systemctl'
Feb 03 10:47:23 linux-node2.openstack monit[89106]: /etc/monitrc:21: Program does not exist: 'systemctl'
Feb 03 10:47:23 linux-node2.openstack monit[89106]: Starting Monit 5.14 daemon with http interface at [localhost]:2812
查看monit状态
[root@linux-node2 ~]# monit status The Monit daemon 5.14 uptime: 9m Process 'sshd' status Running monitoring status Monitored pid 1755 parent pid 1 uid 0 effective uid 0 gid 0 uptime 86d 19h 39m children 6 memory 3.5 MB memory total 25.1 MB memory percent 0.0% memory percent total 0.0% cpu percent 0.0% cpu percent total 0.0% port response time 0.021s to [localhost]:22 type TCP/IP protocol SSH data collected Fri, 03 Feb 2017 10:57:20 Process 'apache' status Not monitored monitoring status Not monitored data collected Fri, 03 Feb 2017 10:50:21 Process 'mariadb' status Running monitoring status Monitored pid 46235 parent pid 1 uid 27 effective uid 27 gid 27 uptime 29d 16h 1m children 0 memory 296.1 MB memory total 296.1 MB memory percent 0.4% memory percent total 0.4% cpu percent 0.0% cpu percent total 0.0% port response time 0.001s to [127.0.0.1]:3306 type TCP/IP protocol MYSQL data collected Fri, 03 Feb 2017 10:57:20 System 'linux-node2.openstack' status Running monitoring status Monitored load average [2.01] [1.86] [1.94] cpu 5.2%us 2.0%sy 0.0%wa memory usage 44.0 GB [70.1%] swap usage 2.6 MB [0.1%] data collected Fri, 03 Feb 2017 10:57:20
重新载入monit服务
[root@linux-node2 ~]# monit reload
Reinitializing monit daemon
确认monit自动启动进程
停止nginx进程之后,查看monit.log文件
[root@linux-node2 ~]# systemctl stop nginx.service
[root@linux-node2 ~]# tailf /var/log/monit.log
[CST Apr 5 21:35:18] error : 'nginx' process is not running
[CST Apr 5 21:35:18] info : 'nginx' trying to restart
[CST Apr 5 21:35:18] info : 'nginx' start: /usr/bin/systemctl
配置启动启动。根据系统及版本自动启动的命令不同,在这里介绍CentOS7上配置自动启动的方法
[root@linux-node2 ~]# systemctl list-unit-files | grep monit.service
monit.service disabled
[root@linux-node2 ~]# systemctl enable monit.service
ln -s '/usr/lib/systemd/system/monit.service' '/etc/systemd/system/multi-user.target.wants/monit.service'
[root@linux-node2 ~]# systemctl list-unit-files | grep monit.service
monit.service enabled
-------------------------------------------------------------------------------------------------------------------------
上一篇: Monit监控
下一篇: 使用 Monit 监控工具
推荐阅读
-
epoll简介及触发模式(accept、read、send)-epoll的简单介绍 epoll在LT和ET模式下的读写方式 一、epoll的接口非常简单,一共就三个函数:1. int epoll_create(int size);创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大。这个参数不同于select中的第一个参数,给出最大监听的fd+1的值。需要注意的是,当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll后,必须调用close关闭,否则可能导致fd被耗尽。2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);epoll的事件注册函数,它不同与select是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。第一个参数是epoll_create的返回值,第二个参数表示动作,用三个宏来表示:EPOLL_CTL_ADD:注册新的fd到epfd中;EPOLL_CTL_MOD:修改已经注册的fd的监听事件;EPOLL_CTL_DEL:从epfd中删除一个fd;第三个参数是需要监听的fd,第四个参数是告诉内核需要监听什么事,struct epoll_event结构如下:struct epoll_event { __uint32_t events; /* Epoll events */ epoll_data_t data; /* User data variable */};events可以是以下几个宏的集合:EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭); EPOLLIN事件:EPOLLIN事件则只有当对端有数据写入时才会触发,所以触发一次后需要不断读取所有数据直到读完EAGAIN为止。否则剩下的数据只有在下次对端有写入时才能一起取出来了。现在明白为什么说epoll必须要求异步socket了吧?如果同步socket,而且要求读完所有数据,那么最终就会在堵死在阻塞里。 EPOLLOUT:表示对应的文件描述符可以写; EPOLLOUT事件:EPOLLOUT事件只有在连接时触发一次,表示可写,其他时候想要触发,那要先准备好下面条件:1.某次write,写满了发送缓冲区,返回错误码为EAGAIN。2.对端读取了一些数据,又重新可写了,此时会触发EPOLLOUT。简单地说:EPOLLOUT事件只有在不可写到可写的转变时刻,才会触发一次,所以叫边缘触发,这叫法没错的!其实,如果真的想强制触发一次,也是有办法的,直接调用epoll_ctl重新设置一下event就可以了,event跟原来的设置一模一样都行(但必须包含EPOLLOUT),关键是重新设置,就会马上触发一次EPOLLOUT事件。1. 缓冲区由满变空.2.同时注册EPOLLIN | EPOLLOUT事件,也会触发一次EPOLLOUT事件这个两个也会触发EPOLLOUT事件 EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);EPOLLERR:表示对应的文件描述符发生错误;EPOLLHUP:表示对应的文件描述符被挂断;EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);等待事件的产生,类似于select调用。参数events用来从内核得到事件的集合,maxevents告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create时的size,参数timeout是超时时间(毫秒,0会立即返回,-1将不确定,也有说法说是永久阻塞)。该函数返回需要处理的事件数目,如返回0表示已超时。-------------------------------------------------------------------------------------------- 从man手册中,得到ET和LT的具体描述如下EPOLL事件有两种模型:Edge Triggered (ET)Level Triggered (LT)假如有这样一个例子:1. 我们已经把一个用来从管道中读取数据的文件句柄(RFD)添加到epoll描述符2. 这个时候从管道的另一端被写入了2KB的数据3. 调用epoll_wait(2),并且它会返回RFD,说明它已经准备好读取操作4. 然后我们读取了1KB的数据5. 调用epoll_wait(2)......Edge Triggered 工作模式:如果我们在第1步将RFD添加到epoll描述符的时候使用了EPOLLET标志,那么在第5步调用epoll_wait(2)之后将有可能会挂起,因为剩余的数据还存在于文件的输入缓冲区内,而且数据发出端还在等待一个针对已经发出数据的反馈信息。只有在监视的文件句柄上发生了某个事件的时候 ET 工作模式才会汇报事件。因此在第5步的时候,调用者可能会放弃等待仍在存在于文件输入缓冲区内的剩余数据。在上面的例子中,会有一个事件产生在RFD句柄上,因为在第2步执行了一个写操作,然后,事件将会在第3步被销毁。因为第4步的读取操作没有读空文件输入缓冲区内的数据,因此我们在第5步调用 epoll_wait(2)完成后,是否挂起是不确定的。epoll工作在ET模式的时候,必须使用非阻塞套接口,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。最好以下面的方式调用ET模式的epoll接口,在后面会介绍避免可能的缺陷。 i 基于非阻塞文件句柄 ii 只有当read(2)或者write(2)返回EAGAIN时才需要挂起,等待。但这并不是说每次read时都需要循环读,直到读到产生一个EAGAIN才认为此次事件处理完成,当read返回的读到的数据长度小于请求的数据长度时,就可以确定此时缓冲中已没有数据了,也就可以认为此事读事件已处理完成。Level Triggered 工作模式相反的,以LT方式调用epoll接口的时候,它就相当于一个速度比较快的poll(2),并且无论后面的数据是否被使用,因此他们具有同样的职能。因为即使使用ET模式的epoll,在收到多个chunk的数据的时候仍然会产生多个事件。调用者可以设定EPOLLONESHOT标志,在 epoll_wait(2)收到事件后epoll会与事件关联的文件句柄从epoll描述符中禁止掉。因此当EPOLLONESHOT设定后,使用带有 EPOLL_CTL_MOD标志的epoll_ctl(2)处理文件句柄就成为调用者必须作的事情。然后详细解释ET, LT:LT(level triggered)是缺省的工作方式,并且同时支持block和no-block socket.在这种做法中,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就绪的fd进行IO操作。如果你不作任何操作,内核还是会继续通知你的,所以,这种模式编程出错误可能性要小一点。传统的select/poll都是这种模型的代表.ET(edge-triggered)是高速工作方式,只支持no-block socket。在这种模式下,当描述符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如,你在发送,接收或者接收请求,或者发送接收的数据少于一定量时导致了一个EWOULDBLOCK 错误)。但是请注意,如果一直不对这个fd作IO操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once),不过在TCP协议中,ET模式的加速效用仍需要更多的benchmark确认(这句话不理解)。在许多测试中我们会看到如果没有大量的idle -connection或者dead-connection,epoll的效率并不会比select/poll高很多,但是当我们遇到大量的idle- connection(例如WAN环境中存在大量的慢速连接),就会发现epoll的效率大大高于select/poll。(未测试)另外,当使用epoll的ET模型来工作时,当产生了一个EPOLLIN事件后,读数据的时候需要考虑的是当recv返回的大小如果等于请求的大小,那么很有可能是缓冲区还有数据未读完,也意味着该次事件还没有处理完,所以还需要再次读取: 这里只是说明思路(参考《UNIX网络编程》) while(rs) {buflen = recv(activeevents[i].data.fd, buf, sizeof(buf), 0);if(buflen < 0){// 由于是非阻塞的模式,所以当errno为EAGAIN时,表示当前缓冲区已无数据可读// 在这里就当作是该次事件已处理处.if(errno == EAGAIN)break; else return; }else if(buflen == 0) { // 这里表示对端的socket已正常关闭. } if(buflen == sizeof(buf) rs = 1; // 需要再次读取 else rs = 0; } 还有,假如发送端流量大于接收端的流量(意思是epoll所在的程序读比转发的socket要快),由于是非阻塞的socket,那么send函数虽然返回,但实际缓冲区的数据并未真正发给接收端,这样不断的读和发,当缓冲区满后会产生EAGAIN错误(参考man send),同时,不理会这次请求发送的数据.所以,需要封装socket_send的函数用来处理这种情况,该函数会尽量将数据写完再返回,返回-1表示出错。在socket_send内部,当写缓冲已满(send返回-1,且errno为EAGAIN),那么会等待后再重试.这种方式并不很完美,在理论上可能会长时间的阻塞在socket_send内部,但暂没有更好的办法. ssize_t socket_send(int sockfd, const char* buffer, size_t buflen) { ssize_t tmp; size_t total = buflen; const char *p = buffer; while(1) { tmp = send(sockfd, p, total, 0); if(tmp < 0) { // 当send收到信号时,可以继续写,但这里返回-1. if(errno == EINTR) return -1; // 当socket是非阻塞时,如返回此错误,表示写缓冲队列已满, // 在这里做延时后再重试. if(errno == EAGAIN) { usleep(1000); continue; } return -1; } if((size_t)tmp == total) return buflen; total -= tmp; p += tmp; } return tmp; } 二、epoll在LT和ET模式下的读写方式 在一个非阻塞的socket上调用read/write函数, 返回EAGAIN或者EWOULDBLOCK(注: EAGAIN就是EWOULDBLOCK) 从字面上看, 意思是: * EAGAIN: 再试一次 * EWOULDBLOCK: 如果这是一个阻塞socket, 操作将被block * perror输出: Resource temporarily unavailable 总结: 这个错误表示资源暂时不够, 可能read时, 读缓冲区没有数据, 或者, write时,写缓冲区满了 。 遇到这种情况, 如果是阻塞socket, read/write就要阻塞掉。 而如果是非阻塞socket, read/write立即返回-1, 同 时errno设置为EAGAIN. 所以, 对于阻塞socket, read/write返回-1代表网络出错了. 但对于非阻塞socket, read/write返回-1不一定网络真的出错了. 可能是Resource temporarily unavailable. 这时你应该再试, 直到Resource available. 综上, 对于non-blocking的socket, 正确的读写操作为: 读: 忽略掉errno = EAGAIN的错误, 下次继续读 写: 忽略掉errno = EAGAIN的错误, 下次继续写 对于select和epoll的LT模式, 这种读写方式是没有问题的. 但对于epoll的ET模式, 这种方式还有漏洞. epoll的两种模式 LT 和 ET
-
[Hadoop2.x] Hadoop 运行一段时间后,stop-dfs 等操作失败 原因及解决方案 - 永久解决方案:修改 $HADOOP_HOME/etc/hadoop/hadoop-env.sh 文件,将 ${HADOOP_PID_DIR} 的 export HADOOP_PID_DIR=${HADOOP_PID_ DIR} 改为你指定的目录,这样 Hadoop 就会将相关的 pid 进程文件保存在指定目录中,避免被 Linux 自动删除。例如 export HADOOP_PID_DIR=/usr/local/hadoop/pids/ 发现问题后的解决方案:
-
Linux - 操作系统和进程的基本概念
-
纯干货分享 | 研发效能提升——敏捷需求篇-而敏捷需求是提升效能的方式中不可或缺的模块之一。 云智慧的敏捷教练——Iris Xu近期在公司做了一场分享,主题为「敏捷需求挖掘和组织方法,交付更高业务价值的产品」。Iris具有丰富的团队敏捷转型实施经验,完成了企业多个团队从传统模式到敏捷转型的落地和实施,积淀了很多的经验。 这次分享主要包含以下2个部分: 第一部分是用户影响地图 第二部分是事件驱动的业务分析Event driven business analysis(以下简称EDBA) 用户影响地图,是一种从业务目标到产品需求映射的需求挖掘和组织的方法。 在软件开发过程中可能会遇到一些问题,比如大家使用不同的业务语言、技术语言,造成角色间的沟通阻碍,还会导致一些问题,比如需求误解、需求传递错误等;这会直接导致产品的功能需求和要实现的业务目标不是映射关系。 但在交付期间,研发人员必须要将这些需求实现交付,他们实则并不清楚这些功能需求产生的原因是什么、要解决客户的哪些痛点。研发人员往往只是拿到了解决方案,需要把它实现,但没有和业务侧一起去思考解决方案是否正确,能否真正的帮助客户解决问题。而用户影响地图通常是能够连接业务目标和产品功能的一种手段。 我们在每次迭代里加入的假设,也就是功能需求。首先把它先实现,再逐步去验证我们每一个小目标是否已经实现,再看下一个目标要是什么。那影响地图就是在这个过程中帮我们不断地去梳理目标和功能之间的关系。 我们在软件开发中可能存在的一些问题 针对这些问题,我们如何避免?先简单介绍做敏捷转型的常规思路: 先做团队级的敏捷,首先把产品、开发、测试人员,还有一些更后端的人员比如交互运维的同学放在一起,组成一个特训团队做交付。这个团队要包含交付过程中所涉及的所有角色。 接着业务敏捷要打通整个业务环节和研发侧的一个交付。上图中可以看到在敏捷中需求是分层管理的,第一层是业务需求,在这个层级是以用户目标和业务目标作为输入进行规划,同时需要去考虑客户的诉求。业务人员通过获取到的业务需求,进一步的和团队一起将其分解为产品需求。所以业务需求其实是我们真正去发布和运营的单元,它可以被独立发布到我们的生产环境上。我们的产品需求其实就是产品的具体功能,它是我们集成和测试的对象,也就是我们最终去部署到系统上的一个基本单元。产品需求再到了我们的开发团队,映射到迭代计划会上要把它分解为相应的技术任务,包括我们平时所说的比如一些前端的开发、后端的开发、测试都是相应的技术任务。所以业务敏捷要达到的目标是需要去持续顺畅高质量的交付业务价值。 将这几个点串起来,形成金字塔结构。最上层我们会把业务目标放在整个金字塔的塔尖。这个业务目标是通过用户的目标以及北极星指标确立的。确认业务目标后再去梳理相应的业务流程,最后生产。另外产品需求包含了操作流程和业务规则,具需求交付时间、工程时间以及我们的一些质量标准的要求。 谈到用户影响的地图,在敏捷江湖上其实有一个传说,大家都有一个说法叫做敏捷需求的“任督二脉”。用户影响地图其实就是任脉,在黑客马拉松上用过的用户故事地图其实叫督脉。所以说用户影响地图是在用户故事地图之前,先帮我们去梳理出我们要做哪些东西。当我们真正识别出我们要实现的业务活动之后,用户故事地图才去梳理我们整个的业务工作流,以及每个工作流节点下所要包含的具体功能和用户故事。所以说用户影响地图需要解决的问题,我们包括以下这些: 首先是范围蔓延,我们在整张地图上,功能和对应的业务目标是要去有一个映射的。这就避免了一些在我们比如有很多干系人参与的会议上,那大家都有不同想法些立场,会提出很多需求(正确以及错误的需求)。这个时候我们会依据目标去看这些需求是否真的是会影响我们的目标。 这里提到的错误需求,比如是利益相关的人提出的、客户认为产品应该有的、某个产品经理需求分析师认为可以有的....但是这些功能在用户影响地图中匹配不到对应目标的话,就需要降低优先级或弃掉。另外,通常我们去制定解决方案的时候,会考虑较完美的实现,导致解决方案括很多的功能。这个时候关键目标至关重要,会帮助我们梳理筛选、确定优先级。 看一下用户影响到地图概貌 总共分为一个三层的结构: 第一层why,你的业务目标哪个是最重要的,为什么?涉及到的角色有哪些? 第二层how ,怎样产生影响?影响用户角色什么样的行为? (不需要去列出所有的影响,基于业务目标) 第三层what,最关键的是在梳理需求时不需一次把所有细节想全,这通常团队中经常遇到的问题。 我们用这个例子来看一下 这是一个客服中心的影响地图,业务目标是 3个月内不增加客服人数的前提下能支持1.5倍的用户数。此业务目标设定是符合 smart 原则的,specific非常的具体,miserable 是可以衡量的,action reoriented是面向活动的, real list 也是很实际的。 量化的目标会指引我们接下来的行动,梳理一个业务目标,尽量去量化,比如 :我们通过打造一条什么样的流水线,能够提高整个部署的效率,时间是原来的 1/2 。这样才是一个能量化的有意义的目标。 回到这幅图, how 层级识别出来的内容,客服角色:想要对它施加的影响,把客户引导到论坛上,帮助客户更容易的跟踪问题,更快速的去定位问题。初级用户:方论坛上找到问题。高级用户:在论坛上回答问题。通过我们这些用户角色,进行活动,完成在不增加客户客服人数的前提下支持更多的用户数量。 最后一个层级,才是我们日常接触比较多的真正的功能的特性和需求,比如引导到客户到论坛上,其实这个产品就需要有一个常见问题的论坛的链接。这个层次需要我们团队进一步地在交付,在每个迭代之前做进一步的梳理,细化成相应的用户故事。 这个是云智慧团队中,自己做的影响地图的范例,可以看下整个的层级结构。序号表示优先级。 那我们用户影响地图可以总结为:
-
深入了解 Linux 进程的堆空间管理
-
操作系统结构原理 - 资源管理技术和进程的抽象设计
-
操作系统的进程管理(下),同步互斥死锁问题,看操作系统如何解决
-
Linux 进程管理:(VI)SMP 负载平衡 - 3.
-
常用软件包管理工具、国内源更改操作和源地址收集(npm、yarn、pip、docker、linux、github)
-
Linux 内核深度分析 - 进程管理 - 读书笔记