Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)
websocketd 是WebSocket守护进程,它负责处理WebSocket连接,启动您的程序来处理WebSockets,并在程序和Web浏览器之间传递消息。
安装:websocketd
wget https://github.com/joewalnes/websocketd/releases/download/v0.2.12/websocketd-0.2.12-linux_amd64.zip
unzip websocketd-0.2.12-linux_amd64.zip
解压后生成这个文件:websocketd
复制该文件到 /usr/bin目录下,修改环境变量
sudo cp websocketd /usr/bin/websocketd
sudo vim /etc/profile
export PATH=$PATH:/usr/bin/websocketd
可能出现的错误:如果修改了/etc/profile,那么编辑结束后执行source profile 或 执行点命令 ./profile,PATH的值就会立即生效了,但是会提示以下错误:
#source /etc/profile 之后为什么会出现
command not found
解决办法,直接切换到root 用户模式既可,再次执行source profile 就可以了,输入help 看是否配置合适,如下所示:
tinywan@tinywan:~/shell$ websocketd --help
websocketd (0.2.12 (go1.6 linux-amd64) --)
websocketd is a command line tool that will allow any executable program
that accepts input on stdin and produces output on stdout to be turned into
a WebSocket server.
Usage:
Export a single executable program a WebSocket server:
websocketd [options] COMMAND [command args]
Or, export an entire directory of executables as WebSocket endpoints:
websocketd [options] --dir=SOMEDIR
Options:
--port=PORT HTTP port to listen on.
--address=ADDRESS Address to bind to (multiple options allowed)
Use square brackets to specify IPv6 address.
Default: "" (all)
开启WebSocketd 服务Tinywan
tinywan@tinywan:~/shell$ websocketd --port=63800 ./count.sh
Mon, 08 May 2017 17:26:50 +0800 | INFO | server | | Serving using application : ./count.sh
Mon, 08 May 2017 17:26:50 +0800 | INFO | server | | Starting WebSocket server : ws://tinywan:8080/
测试代码:count.sh
#!/bin/bash
for ((COUNT = 1; COUNT <= 10; COUNT++)); do
echo $COUNT
sleep 1
done
运行脚本时你可能会遇到以下错误:
root@TinywanAliYun:/home/www/bin# websocketd --port=63800 ./count.sh
Unable to locate specified COMMAND './count.sh' in OS path.
Usage:
Export a single executable program a WebSocket server:
websocketd [options] COMMAND [command args]
Or, export an entire directory of executables as WebSocket endpoints:
websocketd [options] --dir=SOMEDIR
Or, show extended help message using:
websocketd --help
请赋予权限,使其可执行:
$ chmod +x ./count.sh
随便打开一个浏览器,在console中输入一下代码测试:
var ws = new WebSocket('ws://192.168.18.12:63800/');
ws.onopen = function() {
console.log('CONNECT');
};
ws.onclose = function() {
console.log('DISCONNECT');
};
ws.onmessage = function(event) {
console.log('MESSAGE: ' + event.data);
};
(1)测试结果如下所示:
(2)新建立一个客户端测试client.html
<!doctype html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>websocketd</title>
</head>
<body>
<h2>websocketd 客户端的简单测试</h2>
<pre id="log"></pre>
<script>
// helper function: log message to screen
function log(msg) {
document.getElementById('log').textContent += msg + '\n';
}
// setup websocket with callbacks
var ws = new WebSocket('ws://192.168.18.12:8080/');
ws.onopen = function() {
console.log('CONNECT');
};
ws.onclose = function() {
console.log('DISCONNECT');
};
ws.onmessage = function(event) {
console.log('MESSAGE: ' + event.data);
};
</script>
</body>
</html>
在查看结果信息,查看结果已经ok
查看服务端信息
我本机IP地址为,也就是client.html客户端
websocketd --port=9501 --devconsole luajit ./json_ws.lua
》》》实际案例,使用WebSocketd 实时监控内存信息
1、编写脚本,system_info_send_websocketd.sh
#!/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
SHELL_DIR="/home/www/bin"
SHELL_NAME="system_info_websocketd"
SHELL_TIME=$(date '+%Y-%m-%d')
SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}-${SHELL_TIME}.log"
REDIS_MEMORY_KEYS_NAME="REDIS_MEMORY_INFO:001"
REDIS_DISH_KEYS_NAME="REDIS_DISH_INFO:001"
while(true)
do
FIND_DATA=$(cat /proc/meminfo | grep "MemFree:" | awk '{print $2}')
echo "[$SHELL_TIME]: FIND_DATA = $FIND_DATA INSERT_RES = ${INSERT_RES} CUT_LIST_LEN = ${CUT_LIST_LEN}" >> $SHELL_LOG
echo '{"data":'"${FIND_DATA}"',"errcode":0,"errmsg":0}'
sleep 2
done
2、客户端实时监控代码:
<div class="panel-footer" id="container" style="width: 100%; height: 400px; margin: 0 auto"></div>
<script language="JavaScript">
//数据获取
var moniServerIp = "{{moniServerIp}}";
var moniServerSshUsername = "{$moniServerSshUsername}";
var moniServerSshPassword = "{$moniServerSshPassword}";
var wsServerIP = "127.0.0.1";
var wsServerPort = "12380";
var moniMehtod = "server02";
var moniInterval = 1;
var moniDataUnit = 'MB';
var wsData = 0.0;
wsSend = {
"action": moniMehtod,
"name": "tinywan",
};
$(document).ready(function () {
//----------WebSocket部分--------------
var ws = new WebSocket("ws://" + wsServerIP + ":" + wsServerPort);
ws.onopen = function () {
ws.send(JSON.stringify(wsSend));
};
ws.onclose = function () {
console.log('链接已断开');
ws.close();
};
ws.onmessage = function (e) {
var response = JSON.parse(e.data);
if (Number(response.errcode) !== 0) {
console.log(String(response.errmsg));
ws.close();
alert('出错啦!' + String(response.errmsg));
return;
}
var divisor = 1;
switch (moniDataUnit.toLocaleLowerCase()) {
case 'mb':
divisor = 1024;
break;
}
wsData = response.data / divisor;
console.log("收到服务端的消息:" + wsData);
};
//----------highcharts的图标插件部分--------------
Highcharts.setOptions({
global: {
useUTC: false
}
});
$('#container').highcharts({
chart: {
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
// current time
var x = (new Date()).getTime(),
y = wsData * 1.00;
series.addPoint([x, y], true, true);
}, 2000);
}
}
},
title: {
text: '服务器【' + moniServerIp + '】内存指标(单位:' + moniDataUnit + ')'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'MemFree'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
formatter: function () {
return '<b>' + this.series.name + '</b><br/>' +
Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '<br/>' +
Highcharts.numberFormat(this.y, 2);
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'MemFree指标',
data: (function () {
// generate an array
var data = [],
time = (new Date()).getTime(),
i;
for (i = -19; i <= 0; i += 1) {
data.push({
x: time + i * 1000,
y: wsData
});
}
return data;
}())
}]
});
});
</script>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
3、测试结果:
4、客户端可能会出现超时链接的,可以使用 ReconnectingWebSocket
var ws = new ReconnectingWebSocket("ws://" + wsServerIP + ":" + wsServerPort);
》》》》》》》》》》》》 参数详解
(1)参数一:--staticdir=.
--staticdir=. Allow websocketd to serve count.html as a static file
//允许websocketd作为静态文件提供count.html
这个参数是什么意思来,就是在当前项目指定通知执行的语言脚本文件(count.sh)同名的count.html作为静态文件,直接使用http访问
当前目录
count.sh 文件 (tinywan@tinywan:~/Go/websocket$ cat count.sh)
#!/bin/bash
# Count from 1 to 10, pausing for a second between each iteration.
for COUNT in $(seq 1 10); do
echo $COUNT
sleep 1
done
count.html 文件
<!DOCTYPE html>
<html>
<head>
<title>websocketd count example</title>
<style>
#count {
font: bold 150px arial;
margin: auto;
padding: 10px;
text-align: center;
}
</style>
</head>
<body>
<div id="count"></div>
<script>
var ws = new WebSocket('ws://192.168.18.180:8080/');
ws.onopen = function() {
document.body.style.backgroundColor = '#cfc';
};
ws.onclose = function() {
document.body.style.backgroundColor = null;
};
ws.onmessage = function(event) {
document.getElementById('count').textContent = event.data;
};
</script>
</body>
</html>
打开谷歌浏览器,在地址栏输入:http://192.168.18.180:8080/
点击count.html后的效果图
(2)参数二: --devconsole
该--devconsole标志使内置的控制台websocketd与WebSocket端点手动交互。
指向浏览器http://localhost:8080/,您将看到控制台。按复选框连接。
请注意,您不能同时使用--devconsole和--staticdir。开发控制台旨在提供临时用户界面,直到您构建了真实的用户界面。
开始测试:
打开浏览器测试,发送一个空数据是没办法发送的,由于我们没有指定开启那个一个语言脚本文件充当WebSocket 服务器,为我们提供客户端的服务
指定/home/tinywan/Go/websocket 目录下的 count.sh 作为服务文件,继续测试的结果如下所示
Websocket 代理服务器
1、没代理之前访问
var ws = new WebSocket('ws://192.168.18.188:63800');
ws.onopen = function() {
console.log('CONNECT');
};
ws.onclose = function() {
console.log('DISCONNECT');
};
ws.onmessage = function(event) {
console.log('MESSAGE: ' + event.data);
};
2、代理之后访问
var ws = new WebSocket('ws://192.168.18.188:8087/chat/');
ws.onopen = function() {
console.log('CONNECT');
};
ws.onclose = function() {
console.log('DISCONNECT');
};
ws.onmessage = function(event) {
console.log('MESSAGE: ' + event.data);
};
守护进程运行
nohup websocketd --port=63800 /home/www/bin/system_info_send_all_websocketd.sh >/dev/null 2>&1 &
加载证书
sudo websocketd --port=6500 --ssl --sslcert="/etc/letsencrypt/live/www.tinywan.top/fullchain.pem" --
sslkey="/etc/letsencrypt/live/www.tinywan.top//privkey.pem" /home/www/bin/system_info_send_all_websocketd.s
wss 协议测试
var ws = new WebSocket('wss://www.tinywan.top:6500');
ws.onopen = function() {
console.log('CONNECT');
};
ws.onclose = function() {
console.log('DISCONNECT');
};
ws.onmessage = function(event) {
console.log('MESSAGE: ' + event.data);
};
实时监控服务器日志信息
服务端执行脚本执行脚本
1 2 3 4 | $ websocketd --port=63800 . /system_info_send_all_websocketd .sh Sun, 09 Sep 2018 14:34:55 +0800 | INFO | server | | Serving using application : ... /system_info_send_all_websocketd .sh Sun, 09 Sep 2018 14:34:55 +0800 | INFO | server | | Starting WebSocket server : ws: //iZ2zec3dge6rwz2uw4tveuZ :63800/ Sun, 09 Sep 2018 14:35:30 +0800 | ACCESS | session | url: 'http://159.110.213.20:63800/websocket/' id : '1536474930878947882' remote: '60.186.221.134' command : '/home/www/bin/system_info_send_all_websocketd.sh' origin: 'file://' | CONNECT |
本地随便新建以下文件内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | <!DOCTYPE html> <html> <head> <style> body{ background-color: #0e1012;color: #ffffff; } *{ margin: 0; padding: 0; } #msg{ overflow:auto; border:2px solid #303030; color:#ffffff; background-color: #2b2b2b; font-size: 13px; position: absolute; left: 8px; right: 8px; bottom: 8px; top: 40px; word-break: break -all; } #log{ position: fixed; top: 0; left: 0; width: 100%; height: 40px; text-align: left; margin: 4px 0 0 8px; } #log b{ font-size: 26px; } #msgBtn{ padding: 5px 10px; border: none; background: #777; float: right; margin: 0 16px 0 0; } </style> </head> <body> <div id= "log" ><span><b>服务器实时日志</b></span><button id= "msgBtn" type= "button" >清空</button></div> <div id= "msg" > <ul class = "list" ></ul> </div> <script src= "http://libs.baidu.com/jquery/1.9.1/jquery.min.js" ></script> <script> $(document).ready( function () { if (!window.WebSocket) { if (window.MozWebSocket) { window.WebSocket = window.MozWebSocket; } else { $( '#msg' ).append( "<p>你的浏览器不支持websocket</p>" ); } } var ws = new WebSocket( 'ws://www.tinywan.com:63800/websocket/' ); ws.onopen = function (evt) { $( '.list' ).append( '<li>websocket连接成功</li>' ); } ws.onmessage = function (evt) { $( '.list' ).append( '<li>' + evt.data + '</li>' ); setTimeout( function () { $( '#msg' ).scrollTop($( '.list' ).height() - $( '#msg' ).height()); }, 100) } $( "#msgBtn" ).click( function () { $( ".list" ).html( "" ); }) }); </script> </body> </html> |
浏览器打开log.html效果:
Nginx 代理配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | server { listen 443 ssl http2; server_name wallet.www.top; ssl_certificate /etc/letsencrypt/wallet.www.top/full_chain.pem; ssl_certificate_key /etc/letsencrypt/wallet.www.top/ private .key; location /wssd { proxy_pass http: //lnmp-php:8888; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade" ; proxy_set_header X-Real-IP $remote_addr; proxy_read_timeout 600; } } |
连接方式
1 | var ws = new WebSocket( 'wss://wallet.www.top/wssd' ); |
运行一个PHP案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #!/usr/local/php/bin/php <?php require_once './vendor/autoload.php' ; $db = new MysqliDb ([ 'host' => '127.0.0.1' , 'username' => 'test' , 'password' => 'test' , 'db' => 'test' , 'port' => 3308, 'prefix' => 'cl_' , 'charset' => 'utf8' ]); $params = [1, -1]; while (true){ $users = $db ->rawQuery( "SELECT count(*) as nums FROM cl_investor WHERE is_order_taking = ? AND ws_online = ?" , $params ); echo json_encode([ 'counts' => $users [0][ 'nums' ]]). "\n" ; usleep(5000000); } |
注意:开头的PHP路径为绝对路径
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?