本文给出一个与服务器测试连通性的示例,具备邮件通知功能,可以以此为基础添加需要的测试项。
代码功能如下:
- 测试程序与服务器连接,发送指定报文(由内部指定),服务端收到指定报文,回复
testOK
,客户端接收,认为测试通过。 - 否则,测试失败(如果连接不到服务,也认为失败)。
- 当成功或失败时,将结果写到文件(因为nodejs是异步操作,无法保证顺序),然后读取之,再发送邮件给相应的收件人。
- 发送邮件函数比测试函数延后3秒进行,保证测试完毕后才发邮件。
后续改善功能:
- 测试函数调用频率提高,确保第一时间发现问题。
- 每天凌晨发送结果邮件,当错误发生时,立即发送邮件。
代码片段如下:
/*
内部测试,将结果通过邮件通知给收件人
*/
const net = require('net');
const nodemailer = require("nodemailer");
var fs =require('fs');
var g_cnt = 0;
var g_err = 0;
const g_filename = "inntest.txt";
function getTimestamp()
{
var now = new Date();
var y = now.getFullYear();
var m = now.getMonth() + 1;
var d = now.getDate();
var hour = now.getHours();
var min = now.getMinutes();
var sec = now.getSeconds();
var msec = now.getMilliseconds();
return "[" + y + "-" + (m < 10 ? "0" + m : m) +
"-" + (d < 10 ? "0" + d : d) +
" " + (hour < 10 ? "0" + hour : hour) +
":" + (min < 10 ? "0" + min : min) +
":" + (sec < 10 ? "0" + sec : sec) +
"." + (msec < 100 ? (msec < 10 ? "00" + msec : '0' + msec) : msec) + "] ";
}
function printf(fmt, ...extras)
{
console.log(getTimestamp(), fmt, ...extras);
}
// 以追加的形式写到文件
// 注:如果写入内容不一致,最好自行转换成一致再调用
function write(filename, fmt)
{
fs.writeFile(filename, getTimestamp() + fmt + '\r\n', {flag:'a', encoding:'utf-8', mode:'0644'}, function(err){});
}
function read(filename)
{
var buf = '';
buf = fs.readFileSync(filename, 'utf8');
fs.unlink(filename, (err) =>{});
return buf;
}
function nl2br(str, isXhtml) {
var breakTag = (isXhtml || typeof isXhtml === 'undefined') ? '<br />' : '<br>';
var str = (str + '').replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2');
};
function sendMail(from, aliasName, tos, subject, msg)
{
const smtpTransport = nodemailer.createTransport({
host: 'smtp.exmail.qq.com',
secureConnection: true, // use SSL
secure: true,
port: 465,
auth: {
user: from,
pass: '1qaz@WSX',
}
});
smtpTransport.sendMail({
//from : '标题别名 <foobar@latelee.org>',
from : aliasName + ' ' + '<' + from + '>',
to : tos,
subject : subject,//邮件主题
html : nl2br(msg)
}, function(err, res) {
if (err)
{
printf('error: ', err);
}
});
}
function clientmain1(HOST, PORT, msg)
{
var client = new net.Socket();
//printf("connect to ", HOST);
client.connect(PORT, HOST, function()
{
var buffer = Buffer.from(msg, 'hex');
client.write(buffer);
});
// 服务端返回数据处理
client.on('data',function(data){
//printf('got from server: ' + data.toString('hex'));
if (data == 'quit') {
client.destroy();
//printf('server quit, bye');
}
else if (data == 'testOK') {
//printf("test OK");
// printf("test cnt: ", g_cnt, PORT);
g_cnt++;
write(g_filename, "test OK");
client.destroy();
}
});
client.on('error',function(error){
// 当无法连接或其它错误时,在本函数
//printf(`error code: ${error.code}, port: ${error.port}`);
write(g_filename, "test: failed: " + error.code);
client.destroy(); // 调用此函数,会产生close事件
});
client.on('close',function(){
//正常关闭连接
// printf('Connection closed');
//process.exit(0);
});
}
function clientmain2()
{
clientmain1('127.0.0.1', 10086, "test0002147284end"); // packet OK
}
function send2Mail()
{
var context = read(g_filename);
printf('will send email');
sendMail('test@latelee.org', 'my test', 'li@latelee.org', 'my test', context);
}
function clientmain()
{
var Interval = 10;
//send2Mail();
setTimeout(clientmain2, 1000*Interval)
setTimeout(send2Mail, 1000*Interval + 1000*2);
}
// clientmain();
var cron = require('node-cron');
// cron.schedule('* * * * *', () => { // 每分钟 OK
cron.schedule('0 * * * *', () => { // 每小时 OK
// cron.schedule('0 23 * * *', () => { // 每天23点钟
console.log('running a task every hour');
clientmain();
});
说明:本文所用的发送邮箱已被笔者用于gitlab提交邮件通知(用于工作)、其它CI通知,如有需要,可以直接使用,只需将sendMail第三个参数修改为收件人邮箱即可。请不要修改密码,不然会造成影响。
李迟 2019.3.12 周三 中午