如何在Linux服务器上使用speedtest以图形方式检查,存储和报告互联网速度

接下来是一系列宽带连接不畅的问题,我遇到了我决定要监视我获得的Mbps速度...

接下来的一系列宽带连接不畅的问题,我遇到了我决定要监视我从我的供应商定期获得的Mbps速度。 我在晚上试图下载文件时看到特别糟糕的人物,早上实现的速度快得多。

我有一个Linux Debian服务器坐在一个角落,这是我的ISPConfig托管网站的测试和开发机器,还有一些让我们加密的代码,我喜欢玩,所以我寻找一些可以进行带宽测试的软件,可以从linux命令行运行,这可以形成自动化shell脚本系统的基础,以生成我需要的原始数据。 我想将数据存储在SQL数据库中,使得查询变得简单(我可以轻松收集更多的数据,只需要提取一个较小的子集,我感兴趣的时间段),并拥有可以生成简单图表的Web前端可视化数据并帮助突出显示连接问题。

我的搜索的第一个结果是Antonio Valencia真正有用的文章: https//www.howtoing.com/tutorial/check-internet-speed-with-speedtest-cli-on-ubuntu/

按照说明来安装速度测试,快速播放显示我可以使用它来运行测试针对广泛的互联网服务器,并且还生成CSV格式的输出,这是非常适合直接导入到一个SQL表,软件开发中的最小努力。

对于生成的相对较少的数据,我决定使用SQLite作为后端存储,并快速搜索可用的基于开源的基于javascript的图形库导致我的chart.js,它具有简单,干净的设计具有简单的数据接口,但是如果需要,则可以很好地调整高级选项。 转换SQL数据以提取数据子集,我想通过一些直接的PHP代码通过JSON与输出进行图形化。

所以我总是需要设计一个如下所示的系统:

运行速度为cronjob的Linux服务器(可能每小时1个),速度输出存储在SQLite数据库中,所有这些都由bash shell脚本文件控制。 一个Web前端,它是HTML,CSS,javascript和PHP的混合,用于从SQLite中提取数据,并产生一个条形图,显示前24小时(或任何其他可能决定的时间段)的Mbps数据。

有一次实验运行速度超过十几次交互式显示我有几个服务器可用,似乎给出的结果与我遇到的速度是一致的。 我认为对一个以上的服务器进行测试是一个好主意,以便更好地掌握目标服务器的位置以及不同时区的时间对我的Mbps数据的影响。

如果你想跟随并为自己设置一个类似的系统,那么你需要选择一个或者更多的服务器,从数百可用的速度来使用,适合你的位置。

1先决条件

  • 一个linux服务器 - 我使用的是Debian 9.1 - stretch
  • 使用root登录访问服务器 - 我使用Windows笔记本电脑的PuTTY
  • 安装了ISPConfig,还配置了一个FTP帐户的网站 - 我使用3.1.6,将apache设置为Web服务器(您可以使用一个Web服务器进行管理,对以下说明进行了一些细微的更改)
  • PHP - 我使用7.0,但这应该适用于大多数以前的版本
  • FTP客户端 - 我在服务器上运行Filezilla和PureFTPd
  • 纳米或您最喜爱的视觉编辑器

我在这里假设你很熟悉登录到Linux服务器,如何解决目录,Web服务器期望文件的位置布局,以及FTP文件到这些目录的方式。

以下是允许您设置所有这些的详细步骤。

2安装speedtest

以root身份登录到您的linux服务器并运行命令:

# pip install speedtest-cli

有关更多信息,请参阅https://www.howtoing.com/tutorial/check-internet-speed-with-speedtest-cli-on-ubuntu/https://pypi.python.org/pypi/speedtest-cli有任何问题。

注意:speedtest和speedtest-cli在我的安装中是一样的,所以我将在以下参考speedtest。

3安装SQLite3

# apt-get install sqlite3

如果apt-get不适合您,请使用等效的发行版。

4创建bandwidth.sh

在文件中输入以下bash脚本代码并将其保存为/usr/local/etc/bandwidth.sh - 稍后将对其进行编辑,以使其具体针对您。

#!/bin/bash
# run speedtests against 3 servers and save all output results in CSV file for import to sqlite db
#
# run by cronjob once per hour
#
#
function getCSVString () {
	# if speedtest failed (e.g. it couldn't access a server) we need to create a dummy zero entry for this time slot
	
	# get a timestamp string in the same format that speedtest generates - and we need UTC time
	local RIGHTNOW=$(date --utc +%Y-%m-%dT%H:%M:%SZ)
	
	# which server are we testing against?
	if [ $1 = "5443" ] 
	then
		echo "5443,Fasthosts Internet,Gloucester,$RIGHTNOW,73.09,0.0,0.0,0.0"
	fi
	if [ $1 = "1234" ] 
	then
		echo "1234,Uno,Milton Keynes,$RIGHTNOW,168.27,0.0,0.0,0.0"
	fi
	if [ $1 = "1783" ] 
	then
		echo "1783,Comcast,\"San Francisco, CA\",$RIGHTNOW,8420.0,0.0,0.0,0.0"
	fi
	
# test/debug case only
    if [ $1 = "199999999" ]
    then
        echo "99999,Test,Test,$RIGHTNOW,99.99,0.0,0.0,0.0"
    fi
}

function runTest () {
	# run speedtest against named server with csv output saved in tmp file
	/usr/local/bin/speedtest --csv --server $1 > /usr/local/etc/speedtest.tmp
	if [ $? -gt 0 ] 
	then
		# speedtest failed so create a zero entry in place of any error message
		getCSVString $1 > /usr/local/etc/speedtest.tmp
	fi

	# save output ready for next server test
	cat /usr/local/etc/speedtest.tmp >> /usr/local/etc/speedtest.csv
}

# main
#######
# run speedtest against 3 servers and save all output results in csv file
cd /usr/local/etc

# clear csv file - needs to be empty at start of run
rm -f /usr/local/etc/speedtest.csv

############################################
# test/debug case - forces speedtest to fail
############################################
# runTest "199999999"
# sleep 5
####### comment out after testing ##########
############################################

runTest "5443"
sleep 10

runTest "1234"
sleep 10

runTest "1783"
sleep 1

# now import the csv data in to sqlite db
sqlite3 -batch /usr/local/etc/bandwidth.db <<"EOF"
.separator ","
.import /usr/local/etc/speedtest.csv bandwidth
EOF

# add current run csv to backup
cat /usr/local/etc/speedtest.csv >> /usr/local/etc/speedtest.bak

对于即使不需要使用的文件,使用完整路径的“带和大括号”方法,我也深表歉意。 这只是我喜欢做的方式。 如果您喜欢编辑bash脚本,请随时改进。

设置文件属性以使此脚本可执行:

# chmod 0700 bandwidth.sh

5创建一个SQLite数据库

/ usr / local / etc中创建bandwidth.db SQLite数据库:

#sqlite3 bandwidth.db

然后在sqlite>提示符下,使用以下命令创建一个新表(不要错过最后一个分号):

sqlite> CREATE TABLE IF NOT EXISTS "bandwidth" ("serverid" INTEGER NOT NULL , "sponsor" VARCHAR NOT NULL , "servername" VARCHAR NOT NULL , "times" DATETIME PRIMARY KEY NOT NULL UNIQUE , "distance" FLOAT NOT NULL , "ping" FLOAT NOT NULL , "download" FLOAT NOT NULL , "upload" FLOAT NOT NULL );

sqlite> .quit

这将创建一个称为带宽的表,其中字段直接映射到speedtest的CSV格式输出。

6获取服务器列表

您将需要一个速度最快的服务器列表。

# speedtest --list > servers.txt

现在检查servers.txt以查找要运行测试的服务器的数字ID。

# nano servers.txt

该文件将类似于此:

Retrieving speedtest.net configuration...
 5833) Hub Network Services Ltd (Newport, Wales) [57.50 km]
 5938) Spectrum Internet (Cardiff, Great Britain) [65.89 km]
 5443) Fasthosts Internet (Gloucester, Great Britain) [74.31 km]
 6504) Secure Web Services Ltd (Shrewsbury, Great Britain) [78.64 km]
 7265) Unitron Systems & Development Ltd (Telford, Great Britain) [87.11 km]
 8225) Exascale Limited (Wolverhampton, Great Britain) [96.08 km]
 3110) zero.net.uk Ltd (Studley, Great Britain) [96.12 km]
12401) Dragon WiFi LTD (Haverfordwest, United Kingdom) [120.78 km]
 1153) Warwicknet Ltd. (Coventry, Great Britain) [125.18 km]
 1685) Vodafone UK (Newbury, Great Britain) [153.25 km]
 4384) Iomart (Leicester, Great Britain) [157.40 km]
 1234) Uno (Milton Keynes, Great Britain) [170.71 km]
 3504) TNP Ltd. (Manchester, Great Britain) [170.93 km]
11747) Vispa (Manchester, United Kingdom) [170.93 km]

服务器ID位于左侧。 每行末尾的数字是速度测试已经确定您的位置与服务器位置之间的距离(以公里为单位)的估计,尽管我不确定它是否太准确,并且可以从运行到运行。 测试服务器将按照从最近的距离开始的顺序列出。 理论上来说,针对这个列表顶端附近的服务器进行测试,理论上可以给您最快的ping和最好的下载速度与上传速度相比,这些服务器比下拉列表更远。

7选择服务器ID并编辑bandwidth.sh

现在是时候运行speedtest手动选择不同的服务器ids可用,看看你得到什么样的结果。 我在英国选择了几台靠近我的服务器,另一台在加州进行了比较。 要使用的命令格式为:

# speedtest --server 1234

您看到的输出将类似于:

Retrieving speedtest.net configuration...
Testing from xxxxxxx (n.n.n.n)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by Uno (Milton Keynes) [187.87 km]: 33.243 ms
Testing download speed................................................................................
Download: 1.60 Mbit/s
Testing upload speed...............................................................................................
Upload: 0.55 Mbit/s

一旦您选择了要使用的服务器,将数字服务器ID(我已使用3台服务器,但您可以根据需要进行更改)进入bandwidth.sh中的相关行

runTest "5443"
sleep 10

runTest "1234"
sleep 10

runTest "1783"
sleep 1

您还需要调整错误例程中的代码,以创建虚拟条目,如果speedtest在任何特定的运行失败。

	# which server are we testing against?
	if [ $1 = "5443" ] 
	then
		echo "5443,Fasthosts Internet,Gloucester,$RIGHTNOW,73.09,0.0,0.0,0.0"
	fi
	if [ $1 = "1234" ] 
	then
		echo "1234,Uno,Milton Keynes,$RIGHTNOW,168.27,0.0,0.0,0.0"
	fi
	if [ $1 = "1783" ] 
	then
		echo "1783,Comcast,\"San Francisco, CA\",$RIGHTNOW,8420.0,0.0,0.0,0.0"
	fi

在$ RIGHTNOW之后的数字(例如73.09)是您所在位置与所涉及的服务器之间的公里距离。 我不会在任何地方使用它们,所以它们只是一个占位符,可以是任何数值。

请注意,1783的例子,我们必须在该位置放置引号,并将其转义为使其进入我们创建的CSV文件。 这里需要引号,因为这个位置恰好有一个逗号。 没有转义的引号,逗号将被视为CSV字段分隔符,这将导致SQLite导入的问题。 如果您选择的服务器具有与其中的逗号相似的位置文本,那么您将需要使用转义的引号。

8设置一个cronjob

设置一个cronjob,每小时运行一次(或者按照你想要的原则),执行/usr/local/etc/bandwidth.sh 。 如果您正在运行ISPConfig,那么可以使用它来安排cronjob。

创建cronjob

或者,在linux命令行,您可以输入:

# crontab -e

你应该看到类似的东西(记住你以“root”身份登录):

* * * * * /usr/local/ispconfig/server/server.sh 2>&1 | while read line; do echo `/bin/date` "$line" >> /var/log/ispconfig/cron.log; done
* * * * * /usr/local/ispconfig/server/cron.sh 2>&1 | while read line; do echo `/bin/date` "$line" >> /var/log/ispconfig/cron.log; done
1 * * * * /usr/local/etc/bandwidth.sh 2>&1

如果您没有运行ISPConfig,那么这可能最初是空的。 添加最后一行完全如上所示 - 间距很重要 - 从00:01 AM开始运行shell脚本,然后每天重复一次。 当然可以选择不同的时间。 (第一次运行它,crontab会问你想要使用哪个编辑器 - 我选择nano。)

9设置PHP open_basedir

/ usr / local / etc添加到网站的PHP open_basedir条目。 在ISPConfig中,可以在网站的选项选项卡中找到。

设置open_basedir

这允许bandwidth.php代码能够访问我们刚刚在该目录中创建的SQLite数据库。

如果我们决定在已经设置为可访问的目录(如/ var / www / clients / client1 / web1 / web /)中创建数据库,那么我们可以跳过这一点,但从安全角度来说这将是一个不好的选择。

10创建bandwidth.php

您需要将此代码复制到基本Web文档目录中您服务器上名为bandwidth.php的文件。 如果你正在使用ISPConfig,这将像/ var / www / clients / client1 / web1 / web /

<html lang="en"> 
<head> 
<meta charset="utf-8" /> 
<title>Bandwidth Monitor - download speeds in last 24 hours</title>
<script src="scripts/Chart.bundle.min.js"></script>
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
</head>
<body>
<h3 style="font-family: 'Roboto', sans-serif; text-align: center">
Download speeds - last 24 hours
</h3>
<canvas id="myChart" width="1100px" height="500px"></canvas>
<script>
	var bandwidth_data = <?php
	// generate json formatted data from sqlite db
	// Specify sqlite database name and path
	// apache server has setting for PHP open_basedir to include /usr/local/etc
	class MyDB extends SQLite3 {
		function __construct() {
			$this->open('/usr/local/etc/bandwidth.db');
		}
	}
	$db = new MyDB();
	if(!$db) {
		echo $db->lastErrorMsg();
	} else {
		echo "";
	}
	// select the most recent 24 entries to display the last 24 hours of test results (3 servers are tested per hour)
	$sql =<<<EOF
	SELECT serverid, strftime("%H:%M", times) || " " || strftime("%d/%m/%Y", times) AS timestamp, sponsor, servername, download
	FROM bandwidth WHERE serverid = 1234 ORDER BY times LIMIT 24 OFFSET (SELECT COUNT(*)/3 FROM bandwidth)-24;
	EOF;
	$ret = $db->query($sql);
	if(!$ret){
		echo $db->lastErrorMsg();
	} else {
		while($row = $ret->fetchArray(SQLITE3_ASSOC) ) {
			$results[] = $row;
		}
	$ukdata = json_encode($results);
	}
	echo $ukdata;
	$db->close();
	?>
	;
	// extract the fields we want to chart from the JSON data
	var bwlabels = [], bwdata = [];
	var mbps, bvalue;
	for (var i = 0; i < bandwidth_data.length ; i++){
		bwlabels.push(bandwidth_data[i].timestamp);
		// convert bps to Mbps rounded with 3 decimal places in local format
		mbps = Math.round(bandwidth_data[i].download/1000).toFixed(3)/1000;
		bvalue = mbps.toLocaleString(undefined, { minimumFractionDigits: 3 });
		bwdata.push(bvalue);
	}
	var bar_color = 'rgba(0, 128, 255, 0.9)';
	var ctx = document.getElementById("myChart").getContext('2d');
	var myChart = new Chart(ctx, {
		type: 'bar',
		data: {
			labels: bwlabels,
			datasets: [{
				label: 'Mbps download',
				data: bwdata,
				backgroundColor: bar_color,
				borderColor: bar_color,
				borderWidth: 1
			}]
		},
		options: {
			// we override the default tooltip which drops trailing zeros even though we already put them there
			tooltips: {
				callbacks: {
					label: function(tooltipItem, data) {
						var value = data.datasets[0].data[tooltipItem.index];
						var label = 'download: ';
						var retvalue = value.toLocaleString(undefined, { minimumFractionDigits: 3 });
						return label + ' ' + retvalue + ' Mbps';
					}
				}
			},
			responsive: false,
			scales: {
				xAxes: [{
					ticks: {
						autoSkip: false,
						maxTicksLimit: 24
					}
				}],
				yAxes: [{
					ticks: {
						beginAtZero:true
					}
				}]
			}
		}
	});
</script>
</body>
</html>

编辑此文件以使用要报告的serverid。 我在我的示例中使用服务器1234,因为我发现,在浏览了几天的数据之后,这台服务器正在生成与我感觉到的速度最接近的Mbps数据。 serverid位于SQL SELECT语句的WHERE子句中:

SELECT serverid, strftime("%H:%M", times) || " " || strftime("%d/%m/%Y", times) AS timestamp, sponsor, servername, 
download
FROM bandwidth
WHERE serverid = 1234
ORDER BY times
LIMIT 24 OFFSET (SELECT COUNT(*)/3 FROM bandwidth)-24;

这个SQL语句究竟在做什么? 如果你不熟悉SQL,那么我们来看看每个部分。

一个。 SELECT是从SQL数据库表读取记录的命令,后跟要读取的字段和其他选项。

strftime(“%H:%M”,times)|| “”|| strftime(“%d /%m /%Y”,次)AS时间戳

是将speedtest在其CSV输出中创建的datetime字符串重新格式化为更加用户友好的东西。 我想要英国格式的日期,所以这将采取一个字符串,如“2017-08-31T12:02:51.898186Z”,并将其变成“12:02 31/08/2017”。 在SQL语句中直接进行重新格式化更简单,而不必后续处理。 这里的时间将是UTC / GMT,对我来说可以,但是你可能想改变这个; 例如,如果你想要美国格式的日期,然后将第二部分更改为strftime(“%m /%d /%Y”,次数)

C。 serverid,timestamp,sponsor,servername,download是我们要从SQL表中读取并在我们的JSON对象中创建的字段。

天。 FROM带宽是我们正在读取的SQL表的名称。

WHERE serverid = 1234设置要读取的表的子集 - 将其更改为与您使用的serverid相匹配,您可能希望读取多个服务器的数据,但这会使图表复杂化。

F。 ORDER BY times设置输出的排序顺序 - 我们希望按每个运行的速度设置的时间戳排序。

G。 LIMIT 24将输出限制为24条记录,因为我们只想显示24小时的数据,因为我们的cronjob设置为每小时运行一次。 如果您每小时运行两次,那么您需要将其设置为48以获得24小时的数据。

H。 OFFSET(SELECT COUNT(*)/ 3 FROM bandwidth)-24; 我们想要表中最后24条记录,因为它们是我们感兴趣的最近的条目,所以我们必须指定一个OFFSET来匹配LIMIT。 没有这个,我们将永远得到表中的前24个记录,而不是最近的24个记录。 为了获得正确的偏移量,我们用(SELECT COUNT(*))对表中的所有记录进行计数,然后将其除以3(因为我们每小时运行速度为3次,每次为3个不同的服务器运行一次),然后减去24从这个总计获得正确的OFFSET位置,以便LIMIT 24将获得我们想要的记录。

如果您将bash脚本更改为每小时运行3次不同的服务器测试,那么相应地调整该/ 3部分。 如果你只是针对一个服务器进行测试,那么根本就不需要这个部门。

您可能还需要调整图表的整体尺寸,我已经采取了适合我屏幕尺寸的硬编码的简单路线 - 它设置在此行中:

<canvas id="myChart" width="1100px" height="500px"></canvas>

11获取本地文件副本

我更喜欢拥有网页所需的任何css和js库文件(但不是Google字体)的本地版本,如果相同,则需要在Chart.bundle.min的服务器上获取副本。 js并将其放在您的服务器上的/ var / www / clients / client1 / web1 / web / scripts目录中(或者适用于您的基本目录)。

您可以从以下网站下载文件: https//cdnjs.cloudflare.com/ajax/libs/Chartajs/2.6.0/Chart.bundle.min.js

如果您不想使用本地副本,请编辑bandwidth.php指向公共CDN版本。 只需改变这一行:

<script src="scripts/Chart.bundle.min.js"></script>

到这个:

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chartajs/2.6.0/Chart.bundle.min.js"></script>

12在ISPConfig中启用PHP

不要忘记在您的网站设置上启用PHP,如果尚未设置。

在网站中启用PHP

13在浏览器中加载bandwidth.php

我们终于完成了 一旦bandwidth.sh shell脚本有时间运行几次以生成一些数据(或者您可以首先手动运行多次),将浏览器指向您的linux服务器网站,加载bandwidth.php,您应该会看到类似的东西这个:

带宽图

是的,我的宽带真的是那么糟糕!

最后这里还有一些值得一提的点:

14条形图输出

我们应该注意到,存储在SQL表中的下载和上传数字是以bps而不是Mbps(连同一个令人迷惑的十进制数字 - 数字,如1533681.5922415722)。 这只是在CSV模式下运行时速度测试产生数据的方式。 要在条形图的y轴输出上显示Mbps图而不是bps,请在bandwidth.php中的Javascript代码中包含几行以执行转换:

	mbps = Math.round(bandwidth_data[i].download/1000).toFixed(3)/1000; 
	bvalue = mbps.toLocaleString(undefined, { minimumFractionDigits: 3 });

使用toLocaleString应该插入由浏览器的区域设置设置的正确的十进制小数标点符号(“。”或“,”),但这是依赖于实现的,有些不一致。 如果你看到 。 而不是,它会让你感到厌烦,然后全球化就是解决这个问题的方法。 参见'18下面的进一步的步骤和想法'。

需要更多的线路来覆盖尾随零的默认悬停代码处理,因为chart.js通常将显示“2.000”为“2”,这不是我想要的,特别是在遇到麻烦之后确保他们在那里首先:

    // we over-ride the default tooltip which drops trailing zeros even though we already put them there
    tooltips: {
        callbacks: {
            label: function(tooltipItem, data) {
                var value = data.datasets[0].data[tooltipItem.index];
                var label = 'download: ';
                var retvalue = value.toLocaleString(undefined, { minimumFractionDigits: 3 });
                return label + ' ' + retvalue + ' Mbps';
            }
        }
    },

这是一个很好的例子,说明你如何“深入挖掘”到chart.js中,并改变它的做法。

此外,我还设置了图表选项,可以在x轴上为每个栏打印时间戳:

	xAxes: [{
		ticks: {
			autoSkip: false,
			maxTicksLimit: 24
		}

默认选项(autoSkip设置为true)导致标签中有几个奇怪的空白。 如果要显示除24个条目之外的其他内容,则需要更改maxTicksLimit。

如果您想要更多的帮助来更改任何chart.js选项,或者您无法获得想要的工作,那么请查看具体的chart.js溢出页面 - 有很多有用的信息 - https:// stackoverflow .com / questions / tagged / chart.js - 只需使用搜索框缩小搜索范围。 不幸的是,在一些更高级的示例中缺少chart.js文档,这将非常有助于加快使用这个非常好的开源代码。

15错误处理

在我的初始测试运行期间,我注意到几次速度测试报告在CSV文件中报告“无法检索速度测试服务器列表”。 大概这反映了我的宽带连接非常糟糕的时候,速度测试根本无法连接到测试服务器。 这个文本显然不是我们想要导入到SQLite数据库的格式,所以我需要一个解决方案,它将从CSV文件中删除这个不需要的文本,并且在数据库中为特定的时隙包含一个零条目,否则,SQL表中的任何缺少的条目将被简单地看不见,并且在创建图表时也会抛出我想要的每天24个条目的对齐。

您将在bandwidth.sh中看到脚本使用脚本变量$测试speedtest设置的退出代码? 如果大于零,则表示速度失败。 这将触发该功能创建一个虚拟CSV条目,然后用于覆盖该运行的CSV文件。

在bash脚本中有几行被注释掉,但如果在取消注释这些行之后运行该脚本,那么将测试此错误例程以生成一个虚拟零条目。

############################################
# test/debug case - forces speedtest to fail
############################################
# runTest "199999999"
# sleep 5
####### comment out after testing ##########
############################################

这使用速度测试不喜欢的'废话'服务器id,从而导致它返回非零退出代码。 脚本然后应该创建一个虚拟条目,它可以高兴地坐在SQL表中,并被忽略,或者你可以删除它。

强制速度测试失败的另一个方法是为了删除服务器的网络连接。 不要忘记,您可以随时手动运行bandwidth.sh脚本,您不必等待cronjob将其启动,尽管如果cronjob即将来临,您应该避免手动运行它。 同时运行两个脚本可能会导致CSV文件和SQL表的混乱。

如果最坏的情况发生,那么有一个备份的CSV文件保存为/usr/local/etc/speedtest.bak ,它应该包含从第一次运行bash脚本开始的speedtest的所有CSV输出。 这可以被编辑以删除任何不需要的条目,SQL表被清除,然后将整个CSV条目重新导入到SQLite中。

16时区

Speedtest以UTC为单位报告时间(基本上与格林威治标准时间或GMT相同)。 使用UTC意味着存储在SQL表中的所有时间都是一致的,夏令时不会有任何不必要的影响。

但这意味着bandwidth.sh中的错误处理例程需要为虚拟条目创建一个时间戳来反映这一点。 这很简单 - 我们只包括--utc标志:

local RIGHTNOW=$(date --utc +%Y-%m-%dT%H:%M:%SZ)

如果您希望图形x轴标签显示时间为UTC / GMT以外的其他时间,则进行此更改的最佳位置将位于SQL SELECT语句中,例如:

strftime("%H:%M", time(times, 'localtime')) || " " || strftime("%d/%m/%Y", times) AS timestamp

这将使用Linux服务器的时区设置来调整图表上显示的时间。 或者您可以深入了解Globalize如何在前台做到这一点。

有关详细信息,请参阅https://www.timeanddate.com/time/gmt-utc-time.htmlhttp://www.tutorialspoint.com/sqlite/sqlite_date_time.htm

17进一步的步骤和想法

Speedtest不需要是您的原始数据的来源 - 它可以来自任何地方,而不仅仅是互联网速度。 原则是相同的 - 后端服务器进程可以以有用的格式获取原始数据,然后从bash脚本将其导入到SQLite,前端提取所需数据子集,然后对其进行排序。

如果格式化为CSV不是一个选项,一个更复杂的bash脚本可以将数据直接写入SQL表(使用SQL INSERT命令)。 当您设计SQL表时,请考虑如何稍后提取数据。

进行任何更改时,请牢记您正在编辑的代码的上下文; 即我们在HTML内部的JavaScript脚本内部有SQL语句。 记住你所处的水平并相应地进行编码。 可能很容易失去跟踪,最终编写PHP代码应该是Javascript! 我可以保证这不行。

这里有一些进一步探索的想法:

  • toLocaleString并不一定在浏览器中实现。 使用全球化并处理所有数字,日期和时区格式。
  • 结帐httpstat(有一个bash脚本版本),允许收集不同类型的互联网连接数据。 将其存储在(单独的)SQL表中,并绘制输出。
  • 改善bandwidth.php的前端,为用户提供不同的选择:24,48,72小时; 选择特定日期,包括上传和下载数据,ping次数。
  • 转换HTML以使用响应式Bootstrap代码,使其在不同的设备或屏幕尺寸上运行良好。
  • 探索chart.js的其他一些选项; 也许是一个组合的线条和条形图; 改变颜色和条尺寸。
  • 将SQLite替换为MySQL,并通过用户/密码从PHP添加更多的安全性和读取访问权限。
  • 构建一个类似的系统,但使用node.js.