前言

用过nodejs都知道PM2,这章主要讲讲PM2监控程序及报警邮件
用pm2 启动app后,app挂掉自动拉起,但是维护人员不知道啊,所以需要其他方式通过(如邮件)

1:环境
centos7
node14

2: 安装nodejs 及 pm2
1: node安装 (以node-v14.17.3-linux-x64为例) 版本自行选择
1>下载 node-v14.17.3-linux-x64.tar.xz 网上自行去搜
路径: /home/node-v14.17.3-linux-x64.tar.xz
2>解压缩
xz -d node-v14.17.3-linux-x64.tar.xz
tar -xf node-v14.17.3-linux-x64.tar
3>创建软链接
ln -s /home/node-v14.17.3-linux-x64/bin/npm /usr/bin/npm
ln -s /home/node-v14.17.3-linux-x64/bin/node /usr/bin/node
4>测试
node -v

2: 安装pm2
1> npm install -g pm2 //全局安装
安装完 如下

[root@VM-22-234-centos nodejsserver0628]# npm install -g pm2
npm WARN deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
/home/node-v14.17.3-linux-x64/bin/pm2 -> /home/node-v14.17.3-linux-x64/lib/node_modules/pm2/bin/pm2
/home/node-v14.17.3-linux-x64/bin/pm2-dev -> /home/node-v14.17.3-linux-x64/lib/node_modules/pm2/bin/pm2-dev
/home/node-v14.17.3-linux-x64/bin/pm2-docker -> /home/node-v14.17.3-linux-x64/lib/node_modules/pm2/bin/pm2-docker
/home/node-v14.17.3-linux-x64/bin/pm2-runtime -> /home/node-v14.17.3-linux-x64/lib/node_modules/pm2/bin/pm2-runtime
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.3.2 (node_modules/pm2/node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {"os":"darwin","arch":"any"} (current:

2> 创建软连接
ln -s /home/node-v14.17.3-linux-x64/bin/pm2 /usr/bin/pm2

3>pm2 命令

$ pm2 start app.js -i 4 #后台运行pm2,启动4个app.js # 也可以把'max' 参数传递给 start# 正确的进程数目依赖于Cpu的核心数目
$ pm2 start app.js --name my-api # 命名进程
$ pm2 list               # 显示所有进程状态
$ pm2 monit              # 监视所有进程
$ pm2 logs               #  显示所有进程日志
$ pm2 stop all           # 停止所有进程
$ pm2 restart all        # 重启所有进程
$ pm2 reload all         # 0秒停机重载进程 (用于 NETWORKED 进程)
$ pm2 stop 0             # 停止指定的进程
$ pm2 restart 0          # 重启指定的进程
$ pm2 startup            # 产生 init 脚本 保持进程活着
$ pm2 web                # 运行健壮的 computer API endpoint (http://localhost:9615)
$ pm2 delete 0           # 杀死指定的进程
$ pm2 delete all         # 杀死全部进程

3:监控及邮件
monit_app.js 内容如下

const pm2 = require('pm2')
//const sendmail = require('./sendmail');
function pm2checkdump(){console.log("enter pm2checkdump");pm2.connect(function(err) {if (err) {console.error(err)//process.exit(2)return }pm2.list((err, list) => {//  console.log(err, list)if(err){}else{parsedata(list);}pm2.disconnect()})})
}const fs = require('fs')
const path = require('path')var mapprocess = {};
map['key1'] = 1;
//map['key2@'] = 2;//console.log(map['key1']);//结果是1.
console.log(map['key2@']);//结果是2.
var shellcount = 0 ;
var writelogcount = 0;
var monit_pid = 0 ;  //监控程序的PID
var waiwang_ip  = "" ; //外网IP
//如果遍历map
for(var prop in mapprocess){if(mapprocess.hasOwnProperty(prop)){console.log('key is ' + prop +' and value is' + mapprocess[prop]);}
}var exec = require('child_process').exec;function sendmailto(context){let sendermail =   "sendermail@163.com" ;    //发送人let receiver = "receiver1@qq.com,receiver2@qq.com"; //接收人let mailserver = "smtp.163.com:25" ;       //邮箱服务器及端口let mailpw = "shouquanma123"; //授权码let  cmdstr = "sendEmail -o tls=no -f " +sendermail + " -t " + receiver + "   -s " + mailserver + " -xu " + sendermail +" -xp "+ mailpw + "  -u " ;cmdstr = cmdstr + context ;cmdstr = cmdstr + " -m " +context ;//  " '33邮件测试33' -m '33邮件正文你的错误了2'" ;exec(cmdstr ,function(error, stdout, stderr){if(error) {console.error('error: ' + error);return;}console.log('stdout: ' + stdout);});
}//查询外网IP
function queryip(){//curl ifconfig.me   返回IPlet cmdstr = "curl ip.cip.cc"; ////返回IP 加地区  curl cip.ccexec(cmdstr ,function(error, stdout, stderr){if(error) {console.error('error: ' + error);return;}//console.log('stdout: ' + stdout);waiwang_ip = ''+stdout ;console.log(waiwang_ip);});
}//测试发送邮件
function testmail(){let curtime = Date.now();let text ="["+curtime+"] "+"testmail!!";sendmailto(text) ;
}var http=require('http');
//http post
function  httppost(url,port,path,jsobject){//  var data = {//      a: 111,
//      time: Date.now()
//  }if (typeof(jsobject) != 'object')){return ;}port  = port || 80 ;path = path || '/'  ;var dataString = JSON.stringify(jsobject) // 转换为字符串格式var option = {hostname: url,//'127.0.0.1',    // 要访问的服务器的ip地址port: port,//3000,  // 要访问的服务器的端口path: path,//'/xx/xx', // 请求的接口method: 'POST',  // 请求方式headers: {  'Content-Type':'application/json','Content-Length':dataString.length} }var rep = http.request(option, function(res){console.log('状态码:' + res.statusCode)console.log('响应头:' + JSON.stringify(res.headers))res.setEncoding('utf8');res.on('data', (chunk) => {//console.log(`响应主体: ${chunk}`);});res.on('end', () => {//console.log('响应中已无数据');});})req.on('error', (e) => {console.error(`请求遇到问题: ${e.message}`);});req.write(dataString)  // post请求携带的参数(将数据写入请求主体)req.end();     // 必须始终调用 req.end() 来表示请求的结束}function parsedata(data){try{// 异步写入数据到文件//fs.writeFile(file, JSON.stringify(data, null, 4), { encoding: 'utf8' }, err => {})let curtime = Date.now();//    let riqi = Date('Y-m-d H:i:s',''+curtime);let date = new Date(curtime);let dt = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()+' '+date.getHours()+':'+date.getMinutes()+':'+date.getSeconds()let ymr = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate() ;let logfile = path.resolve(__dirname, "./log/"+ymr+"_restart.log");let tmpfile = path.resolve(__dirname, './log/pm2listlog.log')if(typeof(data) == 'object'){for (var i = 0; i < data.length; i++) {let jsonobject = data[i] ;//console.log(dt,i, jsonobject.name,jsonobject.pm2_env.restart_time);  //jsonobject.pidif (mapprocess[jsonobject.name]){let curcount = mapprocess[jsonobject.name];if(jsonobject.pm2_env.restart_time >  curcount){console.log("restart",jsonobject.name,curcount)mapprocess[jsonobject.name] =  jsonobject.pm2_env.restart_timelet text =''+waiwang_ip+"["+curtime+"] "+jsonobject.name+" restart!";sendmailto(text) ;fs.writeFile(logfile, text, { encoding: 'utf8', flag: 'a'}, err => {})}else{console.log(dt,jsonobject.name,curcount,jsonobject.pm2_env.restart_time)}}else {//if(shellcount > 0   || jsonobject.name.indexOf("monit") < 0) {mapprocess[jsonobject.name] = jsonobject.pm2_env.restart_time ;// console.log("first save[0]",jsonobject.name,jsonobject.pm2_env.restart_time);//}console.log("first save",jsonobject.name,jsonobject.pm2_env.restart_time);}}//          let newdata = JSON.stringify(data, null, 4);if((shellcount%16) == 0){let newdata = JSON.stringify(data, null, 4);newdata = ''+dt+' '+newdata  ; //增加时间if(writelogcount < 24){fs.writeFile(tmpfile, newdata, { encoding: 'utf8', flag: 'a' }, err => {})  //追加}else{fs.writeFile(tmpfile, newdata, { encoding: 'utf8', flag: 'w' }, err => {})   //截断writelogcount  = 0 ;}writelogcount+=1 ;}shellcount += 1; }/// var json = JSON.parse(data);}catch(e){console.log(e)}
}const timeval = 120*1000  ;// 120秒
setInterval(pm2checkdump, timeval); //启动定时器 //多少时间后再启动
console.log("setInterval setup"+timeval);
pm2checkdump();     //所以这里先启动一次
queryip() ;         //查询外网IP
//testmail();

原理
通过 pm2checkdump 解析数据,记录每个app的次数,
通过对比重启次数 判定该app是否被拉起过
启动监控 pm2 start ./monit_app.js //(根据文件路径自行修改)


4: 注意 把发送人邮箱 放入白名单里,以免收不到邮件

nodejs PM2监控及报警邮件发送(二)相关推荐

  1. php邮件发送tp,Thinkphp5 邮件发送Thinkphp发送邮件

    在项目的开发中 用户修改密码,需要发送验证码到用户邮箱, 在common.php公共文件中加入以下代码: /** * 系统邮件发送函数 * @param string $tomail 接收邮件者邮箱 ...

  2. nagios监控三部曲之——为什么nagios不能发送报警邮件(2)

    最近我写了关于naigos监控的安装与配置的技术文档,公司运维按照我的文档部署naigos,发现不能发送报警邮件,经过我的检查,发现问题如下: 1.hosts里的配置 [root@nagios ~]# ...

  3. shell脚本编写监控本机内存和硬盘剩余空间,剩余内存小于 500M、根分区剩余空间小于 1000M时,发送报警邮件给 root 管理员

    监控本机内存和硬盘剩余空间,剩余内存小于 500M.根分区剩余空间小于 1000M时,发送报警邮件给 root 管理员 # 创建shell脚本文件 vim free.sh #!/bin/bash di ...

  4. zabbix监控mysq且配置自动发送报警邮件

    这里写目录标题 zabbix监控mysq且配置自动发送报警邮件 zabbix监控mysql 实验环境 创建一个目录存放mysql用户的帐号密码 将mysql用户密码配置在文件中(安全) 安装perco ...

  5. nagios监控mysql服务_nagios监控mysql及邮件报警

    1.使用默认监控命令check_http命令+相关的参数来实现,如下: 在command.cfg添加如下关键词监控命令:check_http_word,参数解析:-I指定IP或者主机名,-u指定URL ...

  6. python-flask(二)集成bootstrap、集成web表单、集成邮件发送

    文章目录 一.flask集成bootstrap 1. 什么是Bootstrap? 2. Flask中如何集成Bootstrap? 3. Flask-Bootstrap实现了什么? 二.Flask中集成 ...

  7. Linux下监控磁盘使用量并在超过阀值后自动发送报警邮件

    参考博客:http://www.heminjie.com/system/linux/1923.html 最近Linux服务器磁盘使用量经常到100%,直到影响到正常服务出现故障才会去注意,做不到防患于 ...

  8. Zabbix监控交换机以及邮件报警配置

    Zabbix监控交换机以及邮件报警配置 搭建zabbix LNMP环境 部署zabbix_server 配置zabbix 交换机开启SNMP zabbix添加交换机 自动发现 配置报警媒介 配置接收邮 ...

  9. linux检测磁盘 报警,linux服务器磁盘监控脚本分享(含报警邮件)

    在日常的运维工作中,我们经常会对服务器的磁盘使用情况进行巡检,以防止磁盘爆满导致的业务故障. 如果能编写一个合理完善的监控脚本,当磁盘使用率达到我们设置的阀值时,就自动发送报警邮件,以便我们及时获悉到 ...

最新文章

  1. Java前端控制器模式
  2. 不会MySQL索引,面试官让回家等通知!
  3. 数据持久化 技术比较
  4. mkisofs简单定制linux iso
  5. STM32L1X系列GPIO运用
  6. Java中final和static对修饰类、方法、属性的总结
  7. python odoo_odoo开发学习 -- Python2 or Python3 ?
  8. oracle 数据库查询 COALESCE字符函数
  9. Android提高篇内容整理
  10. Python3+Selenium3自动化测试-(四)
  11. 分布式框架的基石之远程通信协议
  12. 关于电量采集芯片(库仑计)DS2781相关操作及配置
  13. Matlab排序函数
  14. 使用UOS微信桌面版协议登录,wechaty免费版web协议又可以用了
  15. 【单片机笔记】PWM信号与PPM信号简单理解
  16. Oracle数据库上机练习6
  17. 用qt 编译qt moc
  18. Serial Programming Guide for POSIX Operating Systems(转)
  19. Win10装系统及科研常用软件
  20. 在html中引入谷歌地图

热门文章

  1. 遍历对象Object的两类方法
  2. 关注物联网、关注NB-IoT
  3. CSS代码常用代码以及前端图片代码
  4. 安装blackbox_exporter
  5. 国家的mysql表_中国省份数据库+世界国家名数据库
  6. SuperData上线VR数据平台,做行业发展的“指明灯”
  7. Azkaban配置Work Flow案例实操
  8. 编译原理 —— 逆波兰式
  9. 玩转华为ENSP模拟器系列 | 配置BGP EVPN
  10. element card样式无边框