aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--README.md5
-rw-r--r--Report-web_2.html5
-rw-r--r--Report-web_3.html8
-rw-r--r--Report-web_TABLE.html2
-rw-r--r--apt-panopticommon.lua104
-rwxr-xr-xapt-panopticon-report-email-web.lua100
-rwxr-xr-xapt-panopticon.lua162
-rwxr-xr-xlaggers3
-rwxr-xr-xupdate_apt-panopticon63
9 files changed, 329 insertions, 123 deletions
diff --git a/README.md b/README.md
index 2edc3ca..4d80062 100644
--- a/README.md
+++ b/README.md
@@ -29,9 +29,9 @@ The details of that are yet to be determined.
29 29
30 30
31You can get the source code from [https://sledjhamr.org/cgit/apt-panopticon/](https://sledjhamr.org/cgit/apt-panopticon/) (main repo) 31You can get the source code from [https://sledjhamr.org/cgit/apt-panopticon/](https://sledjhamr.org/cgit/apt-panopticon/) (main repo)
32and [https://git.devuan.dev/onefang/apt-panopticon](https://git.devuan.dev/onefang/apt-panopticon) (Devuan repo). 32and [https://git.devuan.org/onefang/apt-panopticon](https://git.devuan.org/onefang/apt-panopticon) (Devuan repo).
33You can get the cgp graphing source code from [https://sledjhamr.org/cgit/apt-panopticon_cgp/]() (main repo) 33You can get the cgp graphing source code from [https://sledjhamr.org/cgit/apt-panopticon_cgp/]() (main repo)
34and [https://git.devuan.dev/onefang/apt-panopticon_cgp](https://git.devuan.dev/onefang/apt-panopticon_cgp) (Devuan repo). 34and [https://git.devuan.org/onefang/apt-panopticon_cgp](https://git.devuan.org/onefang/apt-panopticon_cgp) (Devuan repo).
35 35
36The issue tracker is at [https://sledjhamr.org/mantisbt/project_page.php?project_id=13](https://sledjhamr.org/mantisbt/project_page.php?project_id=13) 36The issue tracker is at [https://sledjhamr.org/mantisbt/project_page.php?project_id=13](https://sledjhamr.org/mantisbt/project_page.php?project_id=13)
37 37
@@ -55,6 +55,7 @@ installed -
55* lua-rrd 55* lua-rrd
56* LuaSocket, on Debian based systems it'll be in the lua-socket package. 56* LuaSocket, on Debian based systems it'll be in the lua-socket package.
57* md5sum and sha256, on Debian based systems they'll be in the coreutils package. 57* md5sum and sha256, on Debian based systems they'll be in the coreutils package.
58* timeout, on Debian based systems it'll be in the coreutils package.
58* rrdtool 59* rrdtool
59* xz, on Debian based systems it'll be in the xz-utils package. 60* xz, on Debian based systems it'll be in the xz-utils package.
60 61
diff --git a/Report-web_2.html b/Report-web_2.html
index 592e8c6..2882179 100644
--- a/Report-web_2.html
+++ b/Report-web_2.html
@@ -1,5 +1,8 @@
1 <p><font style='background-color:red; color:black'>EXPERIMENTAL CODE - double check all results you see here, and read the logs if it's important.</font></p> 1 <p><font style='background-color:red; color:black'>EXPERIMENTAL CODE - double check all results you see here, and read the logs if it's important.</font></p>
2 <p>The full list of Devuan package mirrors is available at the URL: <a href='https://pkgmaster.devuan.org/mirror_list.txt'>https://pkgmaster.devuan.org/mirror_list.txt</a></p> 2 <p>The full list of Devuan package mirrors is available at the URL: <a href='https://pkgmaster.devuan.org/mirror_list.txt'>https://pkgmaster.devuan.org/mirror_list.txt</a></p>
3 <p>Due to the nature of the tests, some errors or warnings will be counted several times. &nbsp; The links in the table and DNS list go to the detailed testing logs.</p> 3 <p>Due to the nature of the tests, some errors or warnings will be counted several times. There will be some duplication.</p>
4 <p>Due to the nature of the tests, some errors or warnings will be counted several times. There will be some duplication.</p>
5 <p>Due to the nature of the tests, some errors or warnings will be counted several times. There will be some duplication.</p>
6 <p>The links in the table and DNS list go to the detailed testing logs.</p>
4 7
5 <hr> 8 <hr>
diff --git a/Report-web_3.html b/Report-web_3.html
index 632e6f4..a1ca70d 100644
--- a/Report-web_3.html
+++ b/Report-web_3.html
@@ -7,7 +7,13 @@
7 <p><font color='aqua'><b>TIMEOUT</b></font> or <font color='blue'><b>TIMEOUT</b></font> means the mirror had too many timeouts, and tests where aborted, so there is no result for this test.</p> 7 <p><font color='aqua'><b>TIMEOUT</b></font> or <font color='blue'><b>TIMEOUT</b></font> means the mirror had too many timeouts, and tests where aborted, so there is no result for this test.</p>
8 <p>NOTE: timeouts may be due to a problem on the testing computer, it might be busy with other things, or be having it's own network problems.</p> 8 <p>NOTE: timeouts may be due to a problem on the testing computer, it might be busy with other things, or be having it's own network problems.</p>
9 <p>NOTE: the speed of the server this checking script is running on might be wildly exaggerated, it doesn't have to go through the Internet to download from itself.</p> 9 <p>NOTE: the speed of the server this checking script is running on might be wildly exaggerated, it doesn't have to go through the Internet to download from itself.</p>
10 <p>The DNS round robin (DNS-RR) column shows the IPs for that mirror, or <font color='grey'><b>no</b></font> if it isn't part of the DNS-RR. &nbsp; The IPs link to the testing log for that IP accessed via the DNS-RR. &nbsp; deb.devuan.org is the DNS-RR itself, so it doesn't get tested directly.</p> 10 <p>The DNS round robin (DNS-RR) column shows the IPs for that mirror, or <font color='grey'><b>no</b></font> if it isn't part of the DNS-RR.</p>
11 <p> &nbsp; The IPs link to the testing log for that IP accessed via the DNS-RR.</p>
12 <p> &nbsp; If a mirror <a href='DNS-RR_good.txt'>should be</a> it is marked with '<font color='green'><b>&#x2705;</b></font>',
13 if it <a href='DNS-RR_bad.txt'>should not be</a> it is marked with '<font color='red'>&#x274c;</font>',
14 if it might be but still pending full testing, it is marked with '<font color='red'>&#x2753;</font>'.</p>
15 <p> &nbsp; deb.devuan.org is the DNS-RR itself, so it doesn't get tested directly.
16 </p>
11 <p>The time in the Updated column is how often the mirror updates itself.</p> 17 <p>The time in the Updated column is how often the mirror updates itself.</p>
12 <p>Mirrors with a <font style='background-color:dimgrey'>grey background</font> are not active (though may be usable as part of the DNS-RR).</p> 18 <p>Mirrors with a <font style='background-color:dimgrey'>grey background</font> are not active (though may be usable as part of the DNS-RR).</p>
13 <p><font color='grey'><b>skip</b></font> means that the test hasn't been written yet.</p> 19 <p><font color='grey'><b>skip</b></font> means that the test hasn't been written yet.</p>
diff --git a/Report-web_TABLE.html b/Report-web_TABLE.html
index 6ee14f4..b267094 100644
--- a/Report-web_TABLE.html
+++ b/Report-web_TABLE.html
@@ -1,4 +1,4 @@
1 <table> 1 <table id=results>
2 <tr> 2 <tr>
3 <th></th> 3 <th></th>
4 <th class="TTitem"> 4 <th class="TTitem">
diff --git a/apt-panopticommon.lua b/apt-panopticommon.lua
index 0862b77..982ff21 100644
--- a/apt-panopticommon.lua
+++ b/apt-panopticommon.lua
@@ -3,14 +3,18 @@ local APT = {}
3-- https://oss.oetiker.ch/rrdtool/prog/rrdlua.en.html 3-- https://oss.oetiker.ch/rrdtool/prog/rrdlua.en.html
4APT.rrd = require 'rrd' 4APT.rrd = require 'rrd'
5 5
6APT.version = '0.3 alpha'
7
6APT.protocols = {"ftp", "http", "https", "rsync"} 8APT.protocols = {"ftp", "http", "https", "rsync"}
7APT.tests = {'raw', 'Integrity', 'Protocol', 'Redirects', 'Updated', 'URLSanity', 'Speed'} 9APT.tests = {'raw', 'Integrity', 'Protocol', 'Redirects', 'Updated', 'URLSanity', 'Speed'}
8APT.releases = {"ascii", "beowulf", "chimaera", "ceres"} 10--APT.releases = {"jessie", "ascii", "beowulf", "chimaera", "daedalus", "ceres"}
11APT.releases = {"beowulf","chimaera", "daedalus", "excalibur", "ceres"}
9APT.subRels = {'backports', 'proposed-updates', 'security', 'updates'} 12APT.subRels = {'backports', 'proposed-updates', 'security', 'updates'}
10APT.notExist = 13APT.notExist =
11{ 14{
12 'chimaera-backports', 15 'excalibur-backports',
13 'chimaera-security', 16 'excalibur-security',
17 'excalibur-updates',
14 'ceres-backports', -- These will never exist, it's our code name for the testing suite. 18 'ceres-backports', -- These will never exist, it's our code name for the testing suite.
15 'ceres-proposed-updates', 19 'ceres-proposed-updates',
16 'ceres-updates', 20 'ceres-updates',
@@ -50,6 +54,12 @@ APT.options =
50 help = "The round robin DNS name.", 54 help = "The round robin DNS name.",
51 value = "deb.devuan.org", 55 value = "deb.devuan.org",
52 }, 56 },
57 roundRobinCname =
58 {
59 typ = "string",
60 help = "The round robin DNS name.",
61 value = "deb.rr.devuan.org",
62 },
53 tests = 63 tests =
54 { 64 {
55 typ = "table", 65 typ = "table",
@@ -80,7 +90,7 @@ APT.options =
80 { 90 {
81 typ = "number", 91 typ = "number",
82 help = "", 92 help = "",
83 value = 5, 93 value = 24,
84 }, 94 },
85 timeouts = 95 timeouts =
86 { 96 {
@@ -125,7 +135,7 @@ APT.parseArgs = function(args)
125 local arg = {} 135 local arg = {}
126 local sendArgs = "" 136 local sendArgs = ""
127 -- A special test to disable IPv6 tests if IPv6 isn't available. 137 -- A special test to disable IPv6 tests if IPv6 isn't available.
128 if 1 == APT.exe('ip -6 addr | grep inet6 | grep " global"'):Do().status then 138 if 1 == APT.exe('ip -6 addr | grep inet6 | grep " global"'):timeout():Do().status then
129 table.insert(args, '--tests=-IPv6') 139 table.insert(args, '--tests=-IPv6')
130 end 140 end
131 if 0 ~= #(args) then 141 if 0 ~= #(args) then
@@ -139,7 +149,7 @@ APT.parseArgs = function(args)
139 end 149 end
140 os.exit() 150 os.exit()
141 elseif "--version" == a then 151 elseif "--version" == a then
142 print("apt-panopticon version 0.2 alpha") 152 print("apt-panopticon version " .. APT.version)
143 os.exit() 153 os.exit()
144 elseif "-v" == a then 154 elseif "-v" == a then
145 APT.verbosity = APT.verbosity + 1 155 APT.verbosity = APT.verbosity + 1
@@ -398,7 +408,7 @@ APT.logOpen = function(host, a2, a3)
398 local name = APT.logName(host, a2, a3)[1] 408 local name = APT.logName(host, a2, a3)[1]
399 if APT.checkFile(name) then return false end 409 if APT.checkFile(name) then return false end
400 APT.logFile, e = io.open(name, "a+") 410 APT.logFile, e = io.open(name, "a+")
401 if nil == APT.logFile then C('opening log file (' .. name .. ') - ' .. e); return false end 411 if nil == APT.logFile then print('CRITICAL - opening log file (' .. name .. ') - ' .. e); return false end
402 if nil ~= APT.logFile then 412 if nil ~= APT.logFile then
403 APT.logFile:write("<html><head>\n") 413 APT.logFile:write("<html><head>\n")
404 APT.logFile:write("</head><body bgcolor='black' text='white' alink='red' link='aqua' vlink='fuchsia'>\n") 414 APT.logFile:write("</head><body bgcolor='black' text='white' alink='red' link='aqua' vlink='fuchsia'>\n")
@@ -415,6 +425,7 @@ APT.logPost = function()
415 if nil ~= APT.logFile then 425 if nil ~= APT.logFile then
416 APT.logFile:write("</body></html> \n") 426 APT.logFile:write("</body></html> \n")
417 APT.logFile:close() 427 APT.logFile:close()
428 APT.logFile = nil
418 end 429 end
419end 430end
420 431
@@ -455,7 +466,7 @@ local log = function(v, t, s, prot, test, host)
455 if nil ~= APT.logFile then 466 if nil ~= APT.logFile then
456 if APT.html then 467 if APT.html then
457 local colour = "white" 468 local colour = "white"
458 if -1 == v then colour = "fuchsia" end -- CRITICAL 469 if -1 == v then colour = "fuchsia"; print(t .. " " .. s) end -- CRITICAL
459 if 0 == v then colour = "red " end -- ERROR 470 if 0 == v then colour = "red " end -- ERROR
460 if 1 == v then colour = "yellow " end -- WARNING 471 if 1 == v then colour = "yellow " end -- WARNING
461 if 2 == v then colour = "blue " end -- TIMEOUT 472 if 2 == v then colour = "blue " end -- TIMEOUT
@@ -482,6 +493,19 @@ local E = APT.E
482local C = APT.C 493local C = APT.C
483 494
484 495
496APT.readCmd = function(cmd)
497 local result = {}
498 local output = io.popen(cmd)
499 if nil ~= output then
500 for l in output:lines() do
501 table.insert(result, l)
502 end
503 end
504 -- While this does return the same things as os.execute(), it's just as useless.
505 output:close()
506 return result
507end
508
485APT.debians = {} 509APT.debians = {}
486APT.mirrors = {} 510APT.mirrors = {}
487 511
@@ -508,7 +532,7 @@ APT.tested = function(prot, test, host)
508end 532end
509 533
510APT.exe = function(c) 534APT.exe = function(c)
511 local exe = {status = 0, result = '', log = true, cmd = c .. ' '} 535 local exe = {status = 0, result = '', log = true, cmd = c .. ' ', command = c}
512 536
513 function exe:log() 537 function exe:log()
514 self.log = true 538 self.log = true
@@ -522,6 +546,16 @@ APT.exe = function(c)
522 end 546 end
523 return self 547 return self
524 end 548 end
549 function exe:timeout(c)
550 -- timeout returns a status of - command status if --preserve-status; "128+9" (actually 137) if --kill-after ends up being done; 124 if it had to TERM; command status if all went well.
551 -- --kill-after means "send KILL after TERM fails.
552 if nil == c then
553 self.cmd = 'timeout --kill-after=10.0 --foreground 42.0s ' .. self.cmd
554 else
555 self.cmd = 'timeout --kill-after=10.0 --foreground ' .. c .. ' ' .. self.cmd
556 end
557 return self
558 end
525 function exe:also(c) 559 function exe:also(c)
526 if nil == c then c = '' else c = ' ' .. c end 560 if nil == c then c = '' else c = ' ' .. c end
527 self.cmd = self.cmd .. ';' .. c .. ' ' 561 self.cmd = self.cmd .. ';' .. c .. ' '
@@ -558,17 +592,51 @@ APT.exe = function(c)
558 I'm getting 7168 or 0. No idea what the fuck that is. 592 I'm getting 7168 or 0. No idea what the fuck that is.
559 local ok, rslt, status = os.execute(s) 593 local ok, rslt, status = os.execute(s)
560 ]] 594 ]]
561 local f = io.popen(self.cmd .. ' ; echo "$?"', 'r') 595
562 -- The last line will be the command's returned status, collect everything else in result. 596 local f = APT.readCmd(self.cmd, 'r')
597 -- The last line will be the command's returned status, collect everything else in result.
563 self.status = '' -- Otherwise the result starts with 0. 598 self.status = '' -- Otherwise the result starts with 0.
564 for l in f:lines() do 599 self.result = '\n'
565 self.result = self.result .. self.status .. "\n" 600 for i,l in ipairs(f) do
566 self.status = l 601 self.result = self.result .. l .. "\n"
602 end
603 f = APT.readCmd('echo "$?"', 'r')
604 for i,l in ipairs(f) do
605 self.status = tonumber(l)
606 if (137 == self.status) or (124 == self.status) then
607 print("timeout killed " .. self.status .. ' ' .. self.command)
608 E("timeout killed " .. self.status .. ' ' .. self.command)
609 elseif (0 ~= self.status) then
610 print("status |" .. self.status .. '| ' .. self.command)
611 E("status |" .. self.status .. '| ' .. self.command)
612 end
613 end
614
615--[[ While this is more reliable, it breaks stuff that's likely making assumptions that match the old way.
616TODO - fix it later.
617 local f = APT.readCmd(self.cmd .. '; echo "$?"', 'r')
618 -- The last line will be the command's returned status, collect everything else in result.
619 self.status = tonumber(f[#f])
620 f[#f] = nil
621 self.result = '\n'
622 for i,l in ipairs(f) do
623 self.result = self.result .. l .. "\n"
624 end
625 if (137 == self.status) or (124 == self.status) then
626 print("timeout killed " .. self.status .. ' ' .. self.command)
627 print('ERROR ' .. "timeout killed " .. self.status .. ' ' .. self.command)
628 elseif (nil == self.status) then
629 print("status |" .. "NIL" .. '| ' .. self.command)
630 E("status |" .. "NIL" .. '| ' .. self.command)
631 elseif (0 ~= self.status) then
632-- print("status |" .. self.status .. '| ' .. self.command)
633 E("status |" .. self.status .. '| ' .. self.command)
567 end 634 end
568 self.status = tonumber(self.status) 635]]
569 return self 636 return self
570 end 637 end
571 function exe:fork() 638 function exe:fork(host)
639 if nil ~= host then self.cmd = self.cmd .. '; r=$?; if [ $r -ge 124 ]; then echo "$r ' .. host .. ' failed forked command ' .. string.gsub(self.cmd, '"', "'") .. '"; fi' end
572 self.cmd = '{ ' .. self.cmd .. '; } &' 640 self.cmd = '{ ' .. self.cmd .. '; } &'
573 if true == self.log then D(" forking - &nbsp; <code>" .. self.cmd .. "</code>") end 641 if true == self.log then D(" forking - &nbsp; <code>" .. self.cmd .. "</code>") end
574 os.execute(self.cmd) 642 os.execute(self.cmd)
@@ -578,7 +646,9 @@ APT.exe = function(c)
578end 646end
579 647
580APT.checkExes = function (exe) 648APT.checkExes = function (exe)
581 local count = io.popen('ps x | grep "' .. exe .. '" | grep -v " grep " | grep -v "flock -n apt-panopticon.lock " | wc -l'):read("*l") 649 local count = 0
650 local ps = io.popen('ps x | grep "' .. exe .. '" | grep -v " grep " | grep -v "flock -n apt-panopticon.lock " | wc -l')
651 if nil ~= ps then count = ps:read("*l") end
582 D(count .. " " .. exe .. " commands still running.") 652 D(count .. " " .. exe .. " commands still running.")
583 return tonumber(count) 653 return tonumber(count)
584end 654end
diff --git a/apt-panopticon-report-email-web.lua b/apt-panopticon-report-email-web.lua
index b21ba8a..de63274 100755
--- a/apt-panopticon-report-email-web.lua
+++ b/apt-panopticon-report-email-web.lua
@@ -18,11 +18,13 @@ APT.debians = loadfile("results/debians.lua")()
18local revDNS = function(hosts, dom, IP) 18local revDNS = function(hosts, dom, IP)
19 if APT.options.roundRobin.value ~= dom then 19 if APT.options.roundRobin.value ~= dom then
20 if nil ~= hosts[APT.options.roundRobin.value] then 20 if nil ~= hosts[APT.options.roundRobin.value] then
21 if nil ~= hosts[APT.options.roundRobin.value].IPs["deb.roundr.devuan.org"][IP] then 21 if nil ~= hosts[APT.options.roundRobin.value].IPs[APT.options.roundRobinCname.value] then
22 if APT.html then 22 if nil ~= hosts[APT.options.roundRobin.value].IPs[APT.options.roundRobinCname.value][IP] then
23 return "<font color='purple'><b>DNS-RR</b></font>" 23 if APT.html then
24 else 24 return "<font color='purple'><b>DNS-RR</b></font>"
25 return "DNS-RR" 25 else
26 return "DNS-RR"
27 end
26 end 28 end
27 end 29 end
28 end 30 end
@@ -87,6 +89,7 @@ local status = function(hosts, host, results, typ)
87 89
88 if to then 90 if to then
89 result = "TIMEOUT" 91 result = "TIMEOUT"
92 hosts[host].passed = false;
90 if not s then result = result .. "*" end 93 if not s then result = result .. "*" end
91 if APT.html then 94 if APT.html then
92 if s then 95 if s then
@@ -102,6 +105,7 @@ local status = function(hosts, host, results, typ)
102 end 105 end
103 elseif 0 < e then 106 elseif 0 < e then
104 result = "FAILED" 107 result = "FAILED"
108 hosts[host].passed = false;
105 if not s then result = result .. "*" end 109 if not s then result = result .. "*" end
106 if APT.html then 110 if APT.html then
107 if s then 111 if s then
@@ -198,24 +202,28 @@ local DNSrrTest = function(hosts, k)
198 space = ' &nbsp; ' 202 space = ' &nbsp; '
199 no = "<font color='grey'><b>no</b></font>" 203 no = "<font color='grey'><b>no</b></font>"
200 end 204 end
201 if (APT.options.roundRobin.value ~= k) and (nil ~= hosts[APT.options.roundRobin.value]) and (nil ~= hosts[k].IPs) then 205 if (APT.options.roundRobin.value ~= k) and (nil ~= hosts[APT.options.roundRobin.value]) and (nil ~= hosts[k].IPs) and ("no" ~= hosts[k].DNSRR) then
202 APT.allpairs(hosts[k].IPs, 206 APT.allpairs(hosts[k].IPs,
203 function(i, w, k, v) 207 function(i, w, k, v)
204 if nil ~= hosts[APT.options.roundRobin.value].IPs["deb.roundr.devuan.org"][i] then 208-- if nil ~= hosts[APT.options.roundRobin.value].IPs[APT.options.roundRobinCname.value] then
205 local log = logCount(APT.options.roundRobin.value, i) 209-- if nil ~= hosts[APT.options.roundRobin.value].IPs[APT.options.roundRobinCname.value][i] then
206 if "" ~= log then 210 local log = logCount(APT.options.roundRobin.value, i)
207 if "" == dns then dns = " " else dns = dns .. space end 211 local inRR = "<font color='green'><b>&#x2705;</b></font>"
208 dns = dns .. logCount(APT.options.roundRobin.value, i) 212 if nil ~= log:find("<font color='") then inRR = "<font color='red'>&#x274c;</font>" end
209 else 213 if "" ~= log then
210 if "" == dns then dns = " " else dns = dns .. space end 214 if "" == dns then dns = " " else dns = dns .. space end
211 if APT.html then i = "<font color='maroon'><b>" .. i .. "</b></font>" end 215 dns = dns .. inRR .. logCount(APT.options.roundRobin.value, i)
212 dns = dns .. i 216 else
213 end 217 if "" == dns then dns = " " else dns = dns .. space end
214 end 218 if APT.html then i = "<font color='maroon'><b>" .. i .. "</b></font>" end
219 dns = dns .. inRR .. i
220 end
221-- end
222-- end
215 end 223 end
216 ) 224 )
217 if "" == dns then dns = no end
218 end 225 end
226 if "" == dns then dns = no end
219 return dns 227 return dns
220end 228end
221 229
@@ -242,6 +250,7 @@ local makeTable = function(web, hosts)
242 if nil == v.Active then active = 'nil' else active = v.Active end 250 if nil == v.Active then active = 'nil' else active = v.Active end
243 web:write(" <tr style='background-color:dimgrey'><th>" .. k .. "</th> ") 251 web:write(" <tr style='background-color:dimgrey'><th>" .. k .. "</th> ")
244 end 252 end
253 hosts[k].passed = true;
245 local inRR = "<font color='green'><b>&#x2705;</b></font>" 254 local inRR = "<font color='green'><b>&#x2705;</b></font>"
246 local ftp = "<font color='grey'><b>skip</b></font>" 255 local ftp = "<font color='grey'><b>skip</b></font>"
247 local http = status(hosts, k, results, "http") 256 local http = status(hosts, k, results, "http")
@@ -260,14 +269,7 @@ local makeTable = function(web, hosts)
260 local week = '<td>&nbsp;</td><td>&nbsp;</td>' 269 local week = '<td>&nbsp;</td><td>&nbsp;</td>'
261 if nil == rate then rate = '' end 270 if nil == rate then rate = '' end
262 271
263 -- DNS-RR test. 272 if not hosts[k].passed then inRR = "<font color='red'>&#x274c;</font>" end
264-- if nil == http: find('OK') then inRR = "<font color='red'>&#x274c;</font>" end
265-- if nil == https: find('OK') then inRR = "<font color='red'>&#x274c;</font>" end
266-- if nil == protocol: find('OK') then inRR = "<font color='red'>&#x274c;</font>" end
267-- if nil == redirects: find('OK') then inRR = "<font color='red'>&#x274c;</font>" end
268-- if nil == sanity: find('OK') then inRR = "<font color='red'>&#x274c;</font>" end
269-- if nil == integrity: find('OK') then inRR = "<font color='red'>&#x274c;</font>" end
270-- if nil == updated: find('OK') then inRR = "<font color='red'>&#x274c;</font>" end
271 273
272 if (APT.options.roundRobin.value ~= k) and (nil ~= hosts[APT.options.roundRobin.value]) then 274 if (APT.options.roundRobin.value ~= k) and (nil ~= hosts[APT.options.roundRobin.value]) then
273 if 0 == max then 275 if 0 == max then
@@ -319,8 +321,10 @@ local makeTable = function(web, hosts)
319 week = '<td>&nbsp;' .. percentUp .. '% up</td><td>&nbsp;' .. percentUpdated .. '% updated</td>' 321 week = '<td>&nbsp;' .. percentUp .. '% up</td><td>&nbsp;' .. percentUpdated .. '% updated</td>'
320-- if ('100.00' ~= percentUp) or ('100.00' ~= percentUpdated) then inRR = "<font color='red'>&#x274c;</font>" end 322-- if ('100.00' ~= percentUp) or ('100.00' ~= percentUpdated) then inRR = "<font color='red'>&#x274c;</font>" end
321 end 323 end
324 if "yes" ~= hosts[k].DNSRR then inRR = " &nbsp; &nbsp; " end
325 if "maybe" == hosts[k].DNSRR then inRR = "<font color='red'>&#x2753;</font>" end
322 326
323 web:write("<td>" .. ftp .. "&nbsp;</td><td>" .. http .. "&nbsp;</td><td>" .. https .. "&nbsp;</td><td>" .. rsync .. "&nbsp;</td><td>" .. dns .. 327 web:write("<td>" .. ftp .. "&nbsp;</td><td>" .. http .. "&nbsp;</td><td>" .. https .. "&nbsp;</td><td>" .. rsync .. "&nbsp;</td><td>" .. inRR .. " " .. dns ..
324 "&nbsp;</td><td>" .. protocol .. "&nbsp;</td><td>" .. redirects .. "&nbsp;</td><td>" .. sanity .. "&nbsp;</td><td>" .. integrity .. "&nbsp;</td>" .. '<td>' .. rate .. 328 "&nbsp;</td><td>" .. protocol .. "&nbsp;</td><td>" .. redirects .. "&nbsp;</td><td>" .. sanity .. "&nbsp;</td><td>" .. integrity .. "&nbsp;</td>" .. '<td>' .. rate ..
325 '</td><td>' .. updated .. '</td>&nbsp;' .. spd .. "&nbsp;" .. week .."&nbsp;</tr>\n") 329 '</td><td>' .. updated .. '</td>&nbsp;' .. spd .. "&nbsp;" .. week .."&nbsp;</tr>\n")
326 if "" ~= active then 330 if "" ~= active then
@@ -360,15 +364,14 @@ local makeIPlist = function(hosts)
360 if nil ~= hosts[k].IPs then 364 if nil ~= hosts[k].IPs then
361 for l, w in pairs(hosts[k].IPs) do 365 for l, w in pairs(hosts[k].IPs) do
362 if type(w) == "table" then 366 if type(w) == "table" then
363-- TODO - don't hard code deb.roundr.devuan.org.
364 -- Don't output the extra DNS-RR entries that are for admin reasons. 367 -- Don't output the extra DNS-RR entries that are for admin reasons.
365 if ((APT.options.roundRobin.value == k) and ("deb.roundr.devuan.org" == l)) or (APT.options.roundRobin.value ~= k) then 368 if ((APT.options.roundRobin.value == k) and (APT.options.roundRobinCname.value == l)) or (APT.options.roundRobin.value ~= k) then
366 n[l] = {} 369 n[l] = {}
367 for i, u in pairs(w) do 370 for i, u in pairs(w) do
368 if (APT.testing("IPv6") and ("AAAA" == u)) or ("A" == u) then 371 if (APT.testing("IPv6") and ("AAAA" == u)) or ("A" == u) then
369 local inRR = "" 372 local inRR = ""
370 local lc = logCount(k, i) 373 local lc = logCount(k, i)
371 if checkRR then 374 if checkRR and ('no' ~= hosts[k].DNSRR) then
372 -- If there where errors, warnings, or timeouts, then it'll have that wrapped in font tags. 375 -- If there where errors, warnings, or timeouts, then it'll have that wrapped in font tags.
373 inRR = "<font color='green'><b>&#x2705;</b></font>" 376 inRR = "<font color='green'><b>&#x2705;</b></font>"
374 if nil ~= lc:find("<font color='") then 377 if nil ~= lc:find("<font color='") then
@@ -382,7 +385,8 @@ local makeIPlist = function(hosts)
382 if f == nil then C("writing DNS-RR_good.txt file - " .. e) end 385 if f == nil then C("writing DNS-RR_good.txt file - " .. e) end
383 end 386 end
384 end 387 end
385 if "yes" ~= hosts[k].DNSRR then inRR = "" end 388 if "maybe" == hosts[k].DNSRR then inRR = "<font color='red'>&#x2753;</font>" end
389 if "no" == hosts[k].DNSRR then inRR = "" end
386 local log = '[<a href="' .. adr .. k .. '_' .. i .. '">graphs</a>] &nbsp; ' 390 local log = '[<a href="' .. adr .. k .. '_' .. i .. '">graphs</a>] &nbsp; '
387 if "" == log then n[l][i] = u else n[l][log .. inRR .. ' ' .. revDNS(hosts, k, i) .. ' ' .. lc] = u end 391 if "" == log then n[l][i] = u else n[l][log .. inRR .. ' ' .. revDNS(hosts, k, i) .. ' ' .. lc] = u end
388 end 392 end
@@ -392,7 +396,7 @@ local makeIPlist = function(hosts)
392 if (APT.testing("IPv6") and ("AAAA" == w)) or ("A" == w) then 396 if (APT.testing("IPv6") and ("AAAA" == w)) or ("A" == w) then
393 local inRR = "" 397 local inRR = ""
394 local lc = logCount(k, l) 398 local lc = logCount(k, l)
395 if checkRR then 399 if checkRR and ('no' ~= hosts[k].DNSRR) then
396 -- If there where errors, warnings, or timeouts, then it'll have that wrapped in font tags. 400 -- If there where errors, warnings, or timeouts, then it'll have that wrapped in font tags.
397 inRR = "<font color='green'><b>&#x2705;</b></font>" 401 inRR = "<font color='green'><b>&#x2705;</b></font>"
398 if nil ~= lc:find("<font color='") then 402 if nil ~= lc:find("<font color='") then
@@ -406,7 +410,8 @@ local makeIPlist = function(hosts)
406 if f == nil then C("writing DNS-RR_good.txt file - " .. e) end 410 if f == nil then C("writing DNS-RR_good.txt file - " .. e) end
407 end 411 end
408 end 412 end
409 if "yes" ~= hosts[k].DNSRR then inRR = "" end 413 if "maybe" == hosts[k].DNSRR then inRR = "<font color='red'>&#x2753;</font>" end
414 if "no" == hosts[k].DNSRR then inRR = "" end
410 local log = '[<a href="' .. adr .. k .. '_' .. l .. '">graphs</a>] &nbsp; ' 415 local log = '[<a href="' .. adr .. k .. '_' .. l .. '">graphs</a>] &nbsp; '
411 if "" == log then n[l] = w else n[log .. inRR .. ' ' .. revDNS(hosts, k, l) .. ' ' .. lc] = w end 416 if "" == log then n[l] = w else n[log .. inRR .. ' ' .. revDNS(hosts, k, l) .. ' ' .. lc] = w end
412 end 417 end
@@ -439,7 +444,9 @@ if nil == email then C("opening mirrors file - " .. e) else
439 "The full results of the mirror checking is available at the URLs:\n\n" .. 444 "The full results of the mirror checking is available at the URLs:\n\n" ..
440 " https://borta.devuan.dev/apt-panopticon/results/Report-web.html\n (updated once every hour)\n" .. 445 " https://borta.devuan.dev/apt-panopticon/results/Report-web.html\n (updated once every hour)\n" ..
441 " https://sledjhamr.org/apt-panopticon/results/Report-web.html\n (updated once every ten minutes)\n\n" .. 446 " https://sledjhamr.org/apt-panopticon/results/Report-web.html\n (updated once every ten minutes)\n\n" ..
442 "Due to the nature of the tests, some errors or warnings will be \ncounted several times. " .. 447 "Due to the nature of the tests, some errors or warnings will be \ncounted several times. There will be some duplication.\n\n" ..
448 "Due to the nature of the tests, some errors or warnings will be \ncounted several times. There will be some duplication.\n\n" ..
449 "Due to the nature of the tests, some errors or warnings will be \ncounted several times. There will be some duplication.\n\n" ..
443 "Refer to the logs on the web page for details.\n\n" .. 450 "Refer to the logs on the web page for details.\n\n" ..
444 "Please see below the current status of the Devuan Package Mirror \nnetwork:\n\n" .. 451 "Please see below the current status of the Devuan Package Mirror \nnetwork:\n\n" ..
445 "==== package mirror status " .. os.date("!%F %H:%M") .. " GMT ====\n" .. 452 "==== package mirror status " .. os.date("!%F %H:%M") .. " GMT ====\n" ..
@@ -479,9 +486,9 @@ if nil == email then C("opening mirrors file - " .. e) else
479 "* This means that this protocol isn't actually supported, but the test was run ayway.\n\n" .. 486 "* This means that this protocol isn't actually supported, but the test was run ayway.\n\n" ..
480 "Thanks for your precious help in ensuring that Devuan GNU+Linux \nremains a universal, stable, dependable, free operating system.\n\n" .. 487 "Thanks for your precious help in ensuring that Devuan GNU+Linux \nremains a universal, stable, dependable, free operating system.\n\n" ..
481 "You can get the source code from https://sledjhamr.org/cgit/apt-panopticon/about/ (main repo)\n" .. 488 "You can get the source code from https://sledjhamr.org/cgit/apt-panopticon/about/ (main repo)\n" ..
482 "and from https://git.devuan.dev/onefang/apt-panopticon' (Devuan repo).\n" .. 489 "and from https://git.devuan.org/onefang/apt-panopticon' (Devuan repo).\n" ..
483 "You can get the cgp graphing source code from https://sledjhamr.org/cgit/apt-panopticon_cgp/about/ (main repo)\n" .. 490 "You can get the cgp graphing source code from https://sledjhamr.org/cgit/apt-panopticon_cgp/about/ (main repo)\n" ..
484 "and https://git.devuan.dev/onefang/apt-panopticon_cgp (Devuan repo)\n\n" .. 491 "and https://git.devuan.org/onefang/apt-panopticon_cgp (Devuan repo)\n\n" ..
485 "Love\n\n" .. 492 "Love\n\n" ..
486 "The Dev1Devs\n\n") 493 "The Dev1Devs\n\n")
487 email:close() 494 email:close()
@@ -512,6 +519,17 @@ local colours =
512 '00880080', 519 '00880080',
513 '00088080', 520 '00088080',
514 '00008880', 521 '00008880',
522 '80000080',
523 '08000080',
524 '00800080',
525 '00080080',
526 '00008080',
527 '00000880',
528 'fff00080',
529 '0fff0080',
530 '00fff080',
531 '000fff80',
532 '0000fff0',
515} 533}
516local g = {} 534local g = {}
517local count = 0 535local count = 0
@@ -526,6 +544,7 @@ for k, v in APT.orderedPairs(mirrors) do
526 if APT.options.roundRobin.value ~= k then 544 if APT.options.roundRobin.value ~= k then
527 local c = colours[count] 545 local c = colours[count]
528 local name = string.format('%32s', k) 546 local name = string.format('%32s', k)
547 if c == nil then c = 'ffffff' end
529 if APT.options.referenceSite.value == k then c = 'ffffff' end 548 if APT.options.referenceSite.value == k then c = 'ffffff' end
530 table.insert(g, 'DEF:speedn' .. count .. '=rrd/' .. k .. '/Speed/Speed.rrd:max:MIN') 549 table.insert(g, 'DEF:speedn' .. count .. '=rrd/' .. k .. '/Speed/Speed.rrd:max:MIN')
531 table.insert(g, 'DEF:speedx' .. count .. '=rrd/' .. k .. '/Speed/Speed.rrd:max:MAX') 550 table.insert(g, 'DEF:speedx' .. count .. '=rrd/' .. k .. '/Speed/Speed.rrd:max:MAX')
@@ -576,7 +595,8 @@ if nil == web then C("opening mirrors file - " .. e) else
576 APT.options.roundRobin.value .. " is the DNS round robin, which points to the mirrors that are part of the DNS-RR. &nbsp; " .. 595 APT.options.roundRobin.value .. " is the DNS round robin, which points to the mirrors that are part of the DNS-RR. &nbsp; " ..
577 "If an IP is part of the DNS-RR, it is marked with '<font color='purple'><b>DNS-RR</b></font>'," .. 596 "If an IP is part of the DNS-RR, it is marked with '<font color='purple'><b>DNS-RR</b></font>'," ..
578 " if it <a href='DNS-RR_good.txt'>should be</a> it is marked with '<font color='green'><b>&#x2705;</b></font>'," .. 597 " if it <a href='DNS-RR_good.txt'>should be</a> it is marked with '<font color='green'><b>&#x2705;</b></font>'," ..
579 " if it <a href='DNS-RR_bad.txt'>should not be</a> it is marked with '<font color='red'>&#x274c;</font>'. &nbsp; " .. 598 " if it <a href='DNS-RR_bad.txt'>should not be</a> it is marked with '<font color='red'>&#x274c;</font>'," ..
599 " if it might be but still pending full testing, it is marked with '<font color='red'>&#x2753;</font>'. &nbsp; " ..
580 "<br>" .. 600 "<br>" ..
581 APT.options.referenceSite.value .. " is the master mirror, all the others copy files from it. &nbsp; " .. 601 APT.options.referenceSite.value .. " is the master mirror, all the others copy files from it. &nbsp; " ..
582 "</p>\n" 602 "</p>\n"
@@ -603,12 +623,12 @@ if nil == web then C("opening mirrors file - " .. e) else
603 web:write( "<hr>\n<hr>\n<p>The <a href='Report-email.txt'>email report</a>. &nbsp; " .. 623 web:write( "<hr>\n<hr>\n<p>The <a href='Report-email.txt'>email report</a>. &nbsp; " ..
604 "All <a href='../results'>the logs and other output</a>. &nbsp; " .. 624 "All <a href='../results'>the logs and other output</a>. &nbsp; " ..
605 "You can get the <a href='https://sledjhamr.org/cgit/apt-panopticon/about/'>source code here (main repo)</a>" .. 625 "You can get the <a href='https://sledjhamr.org/cgit/apt-panopticon/about/'>source code here (main repo)</a>" ..
606 "and <a href='https://git.devuan.dev/onefang/apt-panopticon'>here (Devuan repo)</a>. &nbsp;" .. 626 "and <a href='https://git.devuan.org/onefang/apt-panopticon'>here (Devuan repo)</a>. &nbsp;" ..
607 "You can get the cgp graphing <a href='https://sledjhamr.org/cgit/apt-panopticon_cgp/about/'>source code here (main repo)</a>" .. 627 "You can get the cgp graphing <a href='https://sledjhamr.org/cgit/apt-panopticon_cgp/about/'>source code here (main repo)</a>" ..
608 "and <a href='https://git.devuan.dev/onefang/apt-panopticon_cgp'>here (Devuan repo)</a>.</p>\n" 628 "and <a href='https://git.devuan.org/onefang/apt-panopticon_cgp'>here (Devuan repo)</a>.</p>\n"
609 ) 629 )
610 local whn = APT.exe('TZ="GMT" ls -dl1 --time-style="+%s" results/stamp | cut -d " " -f 6-6'):Do().result:sub(2, -2) 630 local whn = APT.exe('TZ="GMT" ls -dl1 --time-style="+%s" results/stamp | cut -d " " -f 6-6'):Do().result:sub(2, -2)
611 web:write( "<p>This run took " .. (os.time() - tonumber("0" .. whn)) .. " seconds.</p>" .. 631 web:write( "<p>This run took " .. (os.time() - tonumber("0" .. whn)) .. " seconds. &nbsp &nbsp apt-panopticon version " .. APT.version .. " </p>" ..
612 "\n</body></html>\n") 632 "\n</body></html>\n")
613 web:close() 633 web:close()
614end 634end
diff --git a/apt-panopticon.lua b/apt-panopticon.lua
index 4019fdf..50e6177 100755
--- a/apt-panopticon.lua
+++ b/apt-panopticon.lua
@@ -14,7 +14,6 @@ APT.html = true
14 14
15 15
16local defaultURL = {scheme = "http"} 16local defaultURL = {scheme = "http"}
17local releases = {"jessie", "ascii", "beowulf", "ceres"}
18local releaseFiles = 17local releaseFiles =
19{ 18{
20 -- Release file. 19 -- Release file.
@@ -22,7 +21,7 @@ local releaseFiles =
22 "Release.gpg", -- 21 "Release.gpg", --
23-- "InRelease", -- 3.7 MB 22-- "InRelease", -- 3.7 MB
24-- "main/binary-all/Packages.xz", -- 2.6 GB for all that changed recently. 23-- "main/binary-all/Packages.xz", -- 2.6 GB for all that changed recently.
25 -- Contents files. -- 3.3 GB 24-- Contents files. -- 3.3 GB
26-- "main/Contents-all.xz", 25-- "main/Contents-all.xz",
27-- "main/Contents-amd64.xz", 26-- "main/Contents-amd64.xz",
28-- "main/Contents-arm64.xz", 27-- "main/Contents-arm64.xz",
@@ -37,16 +36,21 @@ local notExist =
37local referenceDebs = 36local referenceDebs =
38{ 37{
39 -- Debian package. 38 -- Debian package.
40 "merged/pool/DEBIAN/main/d/debian-keyring/debian-keyring_2019.02.25_all.deb", 39 "merged/pool/DEBIAN/main/d/debian-keyring/debian-keyring_2025.03.23_all.deb",
41 -- Debian security package. NOTE this one should always be redirected? 40 -- Debian security package. NOTE this one should always be redirected?
42 "merged/pool/DEBIAN-SECURITY/updates/main/a/apt/apt-transport-https_1.4.10_amd64.deb", 41 "merged/pool/DEBIAN-SECURITY/updates/main/e/exim4/exim4_4.96-15+deb12u7_all.deb",
43} 42}
44local referenceDevs = 43local referenceDevs =
45{ 44{
46 -- Devuan package. NOTE this one should not get redirected, but that's more a warning than an error. 45 -- Devuan package. NOTE this one should not get redirected, but that's more a warning than an error.
47 "merged/pool/DEVUAN/main/d/devuan-keyring/devuan-keyring_2017.10.03_all.deb", 46 "merged/pool/DEVUAN/main/d/devuan-keyring/devuan-keyring_2025.06.02_all.deb", -- Devuan keeps changing this since the key expiry incident.
47 -- Hmmm used to be _all, but it was split to the individual archs. Seems pointless, each one is the same size as the previous all.
48 "merged/pool/DEVUAN/main/b/base-files/base-files_13.8devuan1_amd64.deb",
48} 49}
49 50
51local keyring = "/usr/share/keyrings/devuan-archive-keyring.gpg"
52--local keyring = "/etc/apt/trusted.gpg.d/devuan-keyring-2022-archive.gpg"
53
50local curlStatus = 54local curlStatus =
51{ 55{
52 [1 ] = "Unsupported protocol. This build of curl has no support for this protocol.", 56 [1 ] = "Unsupported protocol. This build of curl has no support for this protocol.",
@@ -170,38 +174,76 @@ local repoExists = function (r)
170end 174end
171 175
172local IP = {} 176local IP = {}
173gatherIPs = function (host) 177gatherIPs = function (host, again)
178 if nil == again then again = '' end
174 if nil == IP[host] then 179 if nil == IP[host] then
175 local IPs 180 local IPs
176 -- Takes about 30 seconds to look up the lot. 181 -- Takes about 30 seconds to look up the lot.
177 -- I tested using dig's -f option, it didn't seem much faster. 182 -- I tested using dig's -f option, it didn't seem much faster.
178 -- The sort -r assumes that deb.devuan.org is the first alphabetically. 183 -- The sort -r assumes that deb.devuan.org is the first alphabetically.
179 local dig = io.popen('dig +keepopen +noall +nottlid +answer ' .. host .. ' A ' .. host .. ' AAAA ' .. host .. ' CNAME ' .. host .. ' SRV | sort -r | uniq') 184 if "" == host then print("Empty host name!") end
180 repeat 185 local dig = APT.readCmd('dig ' .. again .. ' +keepopen +noall +nottlid +answer ' .. host .. ' A ' .. host .. ' AAAA ' .. host .. ' CNAME ' .. host .. ' SRV | sort -r | uniq')
181 IPs = dig:read("*l") 186 for i,IPs in ipairs(dig) do
182 if nil ~= IPs then 187 for k, t, v in IPs:gmatch("([%w_%-%.]*)%.%s*IN%s*(%a*)%s*(.*)") do
183 for k, t, v in IPs:gmatch("([%w_%-%.]*)%.%s*IN%s*(%a*)%s*(.*)") do 188 if "." == v:sub(-1, -1) then v = v:sub(1, -2) end
184 if "." == v:sub(-1, -1) then v = v:sub(1, -2) end 189 if nil == IP[k] then IP[k] = {} end
185 if nil == IP[k] then IP[k] = {} end 190 IP[k][v] = t
186 IP[k][v] = t 191 D(" DNS record " .. host .. " == " .. k .. " type " .. t .. " -> " .. v)
187 D(" DNS record " .. host .. " == " .. k .. " type " .. t .. " -> " .. v) 192 if t == "CNAME" then
188 if t == "CNAME" then 193 if "" == v then
194 if '' ~= again then
195 print("Empty host name! DNS record " .. host .. " == " .. k .. " type " .. t .. " -> " .. v)
196 else
197 return gatherIPs(host, '@9.9.9.11')
198 end
199 else
189 gatherIPs(v) 200 gatherIPs(v)
190 IP[k][v] = IP[v] 201 IP[k][v] = IP[v]
191 elseif v == "SRV" then 202 end
192 print("SVR record found, now what do we do?") 203 elseif v == "SRV" then
204 print("SVR record found, now what do we do?")
205 elseif "" == v then
206 if '' ~= again then
207 print("Empty host name! DNS record " .. host .. " == " .. k .. " type " .. t .. " -> " .. v)
208 else
209 return gatherIPs(host, '@9.9.9.11')
193 end 210 end
194 end 211 end
195 end 212 end
196 until nil == IPs 213 end
197 end 214 end
198 215
199 -- If this is the DNS-RR domain name, gather the IPs for the mirrors that mirror_list.txt says should be in it. 216 -- If this is the DNS-RR domain name, gather the IPs for the mirrors that mirror_list.txt says should be in it.
200 if host == APT.options.roundRobin.value then 217 if host == APT.options.roundRobin.value then
201 for k, m in pairs(APT.mirrors) do 218 for k, m in pairs(APT.mirrors) do
202 if "yes" == m.DNSRR then 219 if ("yes" == m.DNSRR) or ("maybe" == m.DNSRR) then
220 if "" == m.FQDN then
221 print("Empty FQDN name! " .. host)
222 end
203 gatherIPs(m.FQDN) 223 gatherIPs(m.FQDN)
204 IP[host][m.FQDN] = IP[m.FQDN] 224 IP[host][m.FQDN] = IP[m.FQDN]
225 -- Strip them out so we don't test them twice.
226 if (nil ~= IP[m.FQDN]) and (nil ~= IP[host][APT.options.roundRobinCname.value]) then
227 for l, n in pairs(IP[m.FQDN]) do
228 if type(n) == 'table' then
229 for h, p in pairs(n) do
230 for j, o in pairs(IP[host][APT.options.roundRobinCname.value]) do
231 if h == j then IP[host][m.FQDN][l][h] = nil end
232 end
233 o = 0
234 for j in pairs(IP[host][m.FQDN][l]) do o = o + 1 end
235 if 0 == o then IP[host][m.FQDN][l] = nil end
236 end
237 else
238 for j, o in pairs(IP[host][APT.options.roundRobinCname.value]) do
239 if l == j then IP[host][m.FQDN][l] = nil end
240 end
241 end
242 o = 0
243 for j in pairs(IP[host][m.FQDN]) do o = o + 1 end
244 if 0 == o then IP[host][m.FQDN] = nil end
245 end
246 end
205 end 247 end
206 end 248 end
207 end 249 end
@@ -235,7 +277,11 @@ checkHEAD = function (host, URL, r, retry, sanity)
235 if "http" == PU.scheme then 277 if "http" == PU.scheme then
236 hdr = '-H "Host: ' .. host .. '"' 278 hdr = '-H "Host: ' .. host .. '"'
237 end 279 end
238 IP = '--connect-to "' .. pu.host .. '::' .. PU.host .. ':"' 280 if '-6' == APT.IPv46 then
281 IP = '--connect-to "' .. pu.host .. '::[' .. PU.host .. ']:"'
282 else
283 IP = '--connect-to "' .. pu.host .. '::' .. PU.host .. ':"'
284 end
239 fname = host .. "_" .. pu.host .. '_' .. PU.host .. "_" .. PU.path:gsub("/", "_") .. ".txt" 285 fname = host .. "_" .. pu.host .. '_' .. PU.host .. "_" .. PU.path:gsub("/", "_") .. ".txt"
240 end 286 end
241 os.execute('rm -f results/HEADERS_' .. fname .. ' 2>/dev/null; rm -f results/STATUS_' .. fname .. ' 2>/dev/null; touch results/STATUS_' .. fname) 287 os.execute('rm -f results/HEADERS_' .. fname .. ' 2>/dev/null; rm -f results/STATUS_' .. fname .. ' 2>/dev/null; touch results/STATUS_' .. fname)
@@ -266,6 +312,10 @@ checkHEAD = function (host, URL, r, retry, sanity)
266 if "https" == PU.scheme and APT.options.roundRobin.value == host then 312 if "https" == PU.scheme and APT.options.roundRobin.value == host then
267 I(spcd .. "Not testing " .. APT.lnk(URL) .. " mirrors wont have the correct HTTPS certificate for the round robin.", host) 313 I(spcd .. "Not testing " .. APT.lnk(URL) .. " mirrors wont have the correct HTTPS certificate for the round robin.", host)
268 return 314 return
315-- TODO - For some odd reason, sometimes one of these is nil. Dig deeper to figure out why.
316 elseif "https" == PU.scheme and (APT.mirrors[host] ~= nil) and (APT.mirrors[host].Protocols ~= nil) and (not APT.mirrors[host].Protocols.https) then
317 I(spcd .. "Not testing " .. APT.lnk(URL) .. " host doesn't support HTTPS.", host)
318 return
269 else 319 else
270 I(spcd .. check .. " " .. APT.lnk(URL), host) 320 I(spcd .. check .. " " .. APT.lnk(URL), host)
271 end 321 end
@@ -289,7 +339,7 @@ checkHEAD = function (host, URL, r, retry, sanity)
289 'curl -I --retry 0 -s --path-as-is --connect-timeout ' .. APT.options.timeout.value .. ' --max-redirs 0 ' .. APT.IPv46 .. ' ' .. 339 'curl -I --retry 0 -s --path-as-is --connect-timeout ' .. APT.options.timeout.value .. ' --max-redirs 0 ' .. APT.IPv46 .. ' ' ..
290 IP .. ' ' .. '-o /dev/null -D results/"HEADERS_' .. fname .. '" ' .. 340 IP .. ' ' .. '-o /dev/null -D results/"HEADERS_' .. fname .. '" ' ..
291 hdr .. ' -w "#%{http_code} %{ssl_verify_result} %{url_effective}\\n" ' .. PU.scheme .. '://' .. host .. PU.path .. ' >>results/"STATUS_' .. fname .. '"' 341 hdr .. ' -w "#%{http_code} %{ssl_verify_result} %{url_effective}\\n" ' .. PU.scheme .. '://' .. host .. PU.path .. ' >>results/"STATUS_' .. fname .. '"'
292 ):Nice():log():Do().status 342 ):timeout(APT.options.maxtime.value * 2.0):Nice():log():Do().status
293 if 0 < r then 343 if 0 < r then
294 APT.tested(PU.scheme, 'Redirects', host) 344 APT.tested(PU.scheme, 'Redirects', host)
295 else 345 else
@@ -315,7 +365,7 @@ checkHEAD = function (host, URL, r, retry, sanity)
315 if 0 ~= status then 365 if 0 ~= status then
316 local msg = curlStatus[status] 366 local msg = curlStatus[status]
317 if nil == msg then msg = "UNKNOWN CURL STATUS CODE!" end 367 if nil == msg then msg = "UNKNOWN CURL STATUS CODE!" end
318 if (28 == status) or (7 == status) then 368 if (128+9 == status) or (124 == status) or (28 == status) or (7 == status) then
319 T(spcd .. spcd .. "TIMEOUT " .. timeouts + 1 .. ", retry " .. retry + 1 .. ' ' .. APT.lnk(URL), PU.scheme, sanity, host) 369 T(spcd .. spcd .. "TIMEOUT " .. timeouts + 1 .. ", retry " .. retry + 1 .. ' ' .. APT.lnk(URL), PU.scheme, sanity, host)
320 timeouts = timeouts + 1 370 timeouts = timeouts + 1
321 else 371 else
@@ -406,7 +456,7 @@ checkHEAD = function (host, URL, r, retry, sanity)
406 local pth = path:match('^(.*/pool/).*$') 456 local pth = path:match('^(.*/pool/).*$')
407 if nil ~= pth then table.insert(APT.results[PU.scheme].redirects, pu.host .. "/" .. pth) else E(spcd .. spcd .. 'Odd redirect path ' .. path) end 457 if nil ~= pth then table.insert(APT.results[PU.scheme].redirects, pu.host .. "/" .. pth) else E(spcd .. spcd .. 'Odd redirect path ' .. path) end
408 I(spcd .. spcd .. "Now checking redirected host " .. u .. ' &nbsp; for &nbsp; ' .. APT.lnk(URL) .. arw .. APT.lnk(location), host) 458 I(spcd .. spcd .. "Now checking redirected host " .. u .. ' &nbsp; for &nbsp; ' .. APT.lnk(URL) .. arw .. APT.lnk(location), host)
409 APT.exe(downloadLock .. "REDIR-" .. check .. ".log.txt" .. " ./apt-panopticon.lua " .. extraArgs .. ' ' .. pu.host .. "/" .. path .. " " .. file):Nice():log():fork() 459 APT.exe(downloadLock .. "REDIR-" .. check .. ".log.txt" .. " ./apt-panopticon.lua " .. extraArgs .. ' ' .. pu.host .. "/" .. path .. " " .. file):timeout(APT.options.maxtime.value * 2.0):Nice():log():fork(pu.host)
410 D(spcd .. 'logging to ' .. APT.logName(pu.host, nil, file)[2]) 460 D(spcd .. 'logging to ' .. APT.logName(pu.host, nil, file)[2])
411 APT.tested(PU.scheme, 'Redirects', host) 461 APT.tested(PU.scheme, 'Redirects', host)
412 end 462 end
@@ -454,7 +504,7 @@ local checkFiles = function (host, ip, path, file)
454 if checkTimeouts(host, "https", ip .. path .. "/" .. s) then return end 504 if checkTimeouts(host, "https", ip .. path .. "/" .. s) then return end
455 end 505 end
456 end 506 end
457 for i, s in pairs(releases) do 507 for i, s in pairs(APT.releases) do
458 for j, k in pairs(releaseFiles) do 508 for j, k in pairs(releaseFiles) do
459 if repoExists(s .. k) then 509 if repoExists(s .. k) then
460 if checkTimeouts(host, "http", ip .. path .. "/merged/dists/" .. s .. '/' .. k) then return end 510 if checkTimeouts(host, "http", ip .. path .. "/merged/dists/" .. s .. '/' .. k) then return end
@@ -493,7 +543,7 @@ checkHost = function (orig, host, path, ip, file)
493 else 543 else
494 if orig == host then 544 if orig == host then
495 I("Testing mirror " .. orig .. "" .. file) 545 I("Testing mirror " .. orig .. "" .. file)
496 APT.exe("./apt-panopticon.lua " .. sendArgs .. " -o " .. orig .. path .. " " .. file):Nice():log():fork() 546 APT.exe("./apt-panopticon.lua " .. sendArgs .. " -o " .. orig .. path .. " " .. file):timeout(APT.options.maxtime.value * 2.0):Nice():log():fork(orig)
497 D('logging to ' .. APT.logName(ph.host, nil, file)[2]) 547 D('logging to ' .. APT.logName(ph.host, nil, file)[2])
498 else D("checkHost " .. orig .. arw .. host) end 548 else D("checkHost " .. orig .. arw .. host) end
499 end 549 end
@@ -568,7 +618,7 @@ local downloads = function(host, URL, meta, release, list)
568 return 618 return
569 end 619 end
570 else 620 else
571 for i, s in pairs(releases) do 621 for i, s in pairs(APT.releases) do
572 for j, k in pairs(releaseFiles) do 622 for j, k in pairs(releaseFiles) do
573 if repoExists(s .. k) then 623 if repoExists(s .. k) then
574 addDownload(host, URL, f, s, k) 624 addDownload(host, URL, f, s, k)
@@ -577,12 +627,16 @@ local downloads = function(host, URL, meta, release, list)
577 end 627 end
578 end 628 end
579 f:close() 629 f:close()
580 APT.exe(cm):Nice():log():fork() 630 APT.exe(cm):timeout(APT.options.maxtime.value * 2.0):Nice():log():fork(host)
581 D('logging to <a href="' .. log .. '">' .. log .. '</a>, with <a href="' .. files .. '">these files</a>') 631 D('logging to <a href="' .. log .. '">' .. log .. '</a>, with <a href="' .. files .. '">these files</a>')
582end 632end
583 633
584 634
585local validateURL = function(m) 635local validateURL = function(m)
636 if "http://" == m.BaseURL:sub(1, 7) then
637 W("HTTP at beginning of BaseURL in mirror_list.txt! " .. m.BaseURL, "", "", m.FQDN)
638 m.BaseURL = m.BaseURL:sub(1, -2)
639 end
586 if " " == m.BaseURL:sub(-1, -1) then 640 if " " == m.BaseURL:sub(-1, -1) then
587 W("space at end of BaseURL in mirror_list.txt! " .. m.BaseURL, "", "", m.FQDN) 641 W("space at end of BaseURL in mirror_list.txt! " .. m.BaseURL, "", "", m.FQDN)
588 m.BaseURL = m.BaseURL:sub(1, -2) 642 m.BaseURL = m.BaseURL:sub(1, -2)
@@ -594,8 +648,8 @@ local validateURL = function(m)
594 local p = url.parse("http://" .. m.BaseURL) 648 local p = url.parse("http://" .. m.BaseURL)
595 if nil == p.path then p.path = '' end 649 if nil == p.path then p.path = '' end
596 if nil ~= p.port then p.authority = authority .. ':' .. p.port end 650 if nil ~= p.port then p.authority = authority .. ':' .. p.port end
597 if nil == m.FDQN then W("Something wrong in FDQN from mirror_list.txt! nil", "", "", p.authority) else 651 if nil == m.FQDN then W("Something wrong in FQDN from mirror_list.txt! nil", "", "", p.authority) else
598 if m.FQDN ~= p.authority then W("Something wrong in FDQN from mirror_list.txt! " .. m.FDQN, "", "", p.authority) end 652 if m.FQDN ~= p.authority then W("Something wrong in FQDN from mirror_list.txt! " .. m.FQDN, "", "", p.authority) end
599 end 653 end
600 if nil == m.BaseURL then W("Something wrong in BaseURL from mirror_list.txt! nil", "", "", p.authority) else 654 if nil == m.BaseURL then W("Something wrong in BaseURL from mirror_list.txt! nil", "", "", p.authority) else
601 if m.BaseURL ~= (p.authority .. p.path) then W("Something wrong in BaseURL from mirror_list.txt! " .. m.BaseURL, "", "", p.authority) end 655 if m.BaseURL ~= (p.authority .. p.path) then W("Something wrong in BaseURL from mirror_list.txt! " .. m.BaseURL, "", "", p.authority) end
@@ -678,7 +732,7 @@ local postParse = function(host, list)
678 if APT.options.referenceSite.value == host then 732 if APT.options.referenceSite.value == host then
679 if nil ~= list then 733 if nil ~= list then
680 local sem = 'results/NEW_' .. list.out .. '_%s.txt' 734 local sem = 'results/NEW_' .. list.out .. '_%s.txt'
681 for i, n in pairs(releases) do 735 for i, n in pairs(APT.releases) do
682 local f = sem:format(n) 736 local f = sem:format(n)
683 if APT.checkFile(f .. '.tmp') then 737 if APT.checkFile(f .. '.tmp') then
684 os.execute('mv ' .. f .. '.tmp ' .. f) 738 os.execute('mv ' .. f .. '.tmp ' .. f)
@@ -691,7 +745,7 @@ local postParse = function(host, list)
691end 745end
692 746
693local parseDebs = function(host) 747local parseDebs = function(host)
694 for i, n in pairs(releases) do 748 for i, n in pairs(APT.releases) do
695 local inFile = 'results/NEW_debs_' .. n .. '.txt' 749 local inFile = 'results/NEW_debs_' .. n .. '.txt'
696 local nfile, e = io.open(inFile, "r") 750 local nfile, e = io.open(inFile, "r")
697 if nil == nfile then W("opening " .. inFile .. " file - " .. e) else 751 if nil == nfile then W("opening " .. inFile .. " file - " .. e) else
@@ -733,7 +787,7 @@ end
733 787
734local parsePackages = function(host) 788local parsePackages = function(host)
735 local list = {inf = 'Packages', parser = parseDebs, out = 'debs', files = {}, nextf = ''} 789 local list = {inf = 'Packages', parser = parseDebs, out = 'debs', files = {}, nextf = ''}
736 for i, n in pairs(releases) do 790 for i, n in pairs(APT.releases) do
737 local inFile = 'results/NEW_' .. list.inf .. '_' .. n .. '.txt' 791 local inFile = 'results/NEW_' .. list.inf .. '_' .. n .. '.txt'
738 local outFile = 'results/NEW_' .. list.out .. '_' .. n .. '.txt' 792 local outFile = 'results/NEW_' .. list.out .. '_' .. n .. '.txt'
739 if APT.options.referenceSite.value == host then 793 if APT.options.referenceSite.value == host then
@@ -755,6 +809,7 @@ local parsePackages = function(host)
755 local Pp, e = io.open('results/' .. host .. '/merged/dists/'.. n .. dir .. 'Packages.parsed', "w+") 809 local Pp, e = io.open('results/' .. host .. '/merged/dists/'.. n .. dir .. 'Packages.parsed', "w+")
756 if nil == Pp then W('opening results/' .. host .. '/merged/dists/'.. n .. dir .. 'Packages.parsed' .. ' file - ' .. e) else 810 if nil == Pp then W('opening results/' .. host .. '/merged/dists/'.. n .. dir .. 'Packages.parsed' .. ' file - ' .. e) else
757 local pp = {} 811 local pp = {}
812-- TODO - FIX - check if this file exists first.
758 for l in io.lines('results/' .. host .. '/merged/dists/'.. n .. dir .. 'Packages') do 813 for l in io.lines('results/' .. host .. '/merged/dists/'.. n .. dir .. 'Packages') do
759 if "Package: " == l:sub(1, 9) then 814 if "Package: " == l:sub(1, 9) then
760 if 0 ~= #pp then 815 if 0 ~= #pp then
@@ -786,12 +841,12 @@ local parsePackages = function(host)
786 ' | grep -E "^\\+" | grep -Ev "^\\+\\+\\+|^---" >>results/NEW_' .. list.out .. '_TMP_' .. n .. '.txt') 841 ' | grep -E "^\\+" | grep -Ev "^\\+\\+\\+|^---" >>results/NEW_' .. list.out .. '_TMP_' .. n .. '.txt')
787 for i, s in pairs(referenceDebs) do 842 for i, s in pairs(referenceDebs) do
788 if 0 == APT.exe('grep -q "' .. s:sub(8, -1) .. '" results/OLD_' .. list.out .. '_' .. n .. '.txt'):log():Do().status then 843 if 0 == APT.exe('grep -q "' .. s:sub(8, -1) .. '" results/OLD_' .. list.out .. '_' .. n .. '.txt'):log():Do().status then
789 print('Reference package is out of date (' .. n .. ') - ' .. s) 844 print('Reference package is out of date from ' .. host .. ' (' .. n .. ') - ' .. s)
790 end 845 end
791 end 846 end
792 for i, s in pairs(referenceDevs) do 847 for i, s in pairs(referenceDevs) do
793 if 0 == APT.exe('grep -q "' .. s:sub(8, -1) .. '" results/OLD_' .. list.out .. '_' .. n .. '.txt'):log():Do().status then 848 if 0 == APT.exe('grep -q "' .. s:sub(8, -1) .. '" results/OLD_' .. list.out .. '_' .. n .. '.txt'):log():Do().status then
794 print('Reference package is out of date (' .. n .. ') - ' .. s) 849 print('Reference package is out of date from ' .. host .. ' (' .. n .. ') - ' .. s)
795 end 850 end
796 end 851 end
797 else 852 else
@@ -839,13 +894,13 @@ local parseRelease = function(host)
839 local list = {inf = 'Release', parser = parsePackages, out = 'Packages', files = {}, nextf = 'debs'} 894 local list = {inf = 'Release', parser = parsePackages, out = 'Packages', files = {}, nextf = 'debs'}
840 local updated = false 895 local updated = false
841 local now = tonumber(os.date('%s')) 896 local now = tonumber(os.date('%s'))
842 for i, n in pairs(releases) do 897 for i, n in pairs(APT.releases) do
843 for l, o in pairs(releaseFiles) do 898 for l, o in pairs(releaseFiles) do
844 if repoExists(i .. o) then 899 if repoExists(i .. o) then
845 postDownload(host, n, o) 900 postDownload(host, n, o)
846 if (".gpg" == o:sub(-4, -1)) and (APT.checkFile('results/' .. host .. '/merged/dists/' .. n .. '/' .. o)) then 901 if (".gpg" == o:sub(-4, -1)) and (APT.checkFile('results/' .. host .. '/merged/dists/' .. n .. '/' .. o)) then
847 if APT.testing("Integrity") then 902 if APT.testing("Integrity") then
848 local status = APT.exe( "gpgv --keyring /usr/share/keyrings/devuan-keyring.gpg results/" .. host .. "/merged/dists/" .. n .. '/' .. o .. 903 local status = APT.exe( "gpgv --keyring " .. keyring .. " results/" .. host .. "/merged/dists/" .. n .. '/' .. o ..
849 " results/" .. host .. "/merged/dists/" .. n .. '/' .. o:sub(1, -5)):Nice():noErr():log():Do().status 904 " results/" .. host .. "/merged/dists/" .. n .. '/' .. o:sub(1, -5)):Nice():noErr():log():Do().status
850 if 0 ~= status then E("GPG check failed for " .. host .. "/merged/dists/" .. n .. '/' .. o, "http", "Integrity", host) end 905 if 0 ~= status then E("GPG check failed for " .. host .. "/merged/dists/" .. n .. '/' .. o, "http", "Integrity", host) end
851-- TODO - should check the PGP sig of InRelease as well. 906-- TODO - should check the PGP sig of InRelease as well.
@@ -922,7 +977,7 @@ end
922 977
923local parseStart = function(host) 978local parseStart = function(host)
924 local list = {inf = '', parser = parseRelease, out = 'Release', files = {}, nextf = 'Packages'} 979 local list = {inf = '', parser = parseRelease, out = 'Release', files = {}, nextf = 'Packages'}
925 for i, n in pairs(releases) do 980 for i, n in pairs(APT.releases) do
926 local outFile = 'results/NEW_' .. list.out .. '_' .. n .. '.txt' 981 local outFile = 'results/NEW_' .. list.out .. '_' .. n .. '.txt'
927 for l, o in pairs(releaseFiles) do 982 for l, o in pairs(releaseFiles) do
928 if repoExists(n .. o) then 983 if repoExists(n .. o) then
@@ -991,6 +1046,7 @@ os.execute('sleep 1') -- Wait for things to start up before checking for them.
991 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to devuan.bio.lmu.de (141.84.43.19) port 80 (#0) 1046 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to devuan.bio.lmu.de (141.84.43.19) port 80 (#0)
992 curl: (22) The requested URL returned error: 404 Not Found 1047 curl: (22) The requested URL returned error: 404 Not Found
993]] 1048]]
1049 local trace = {}
994 local min, max, spd = 999999999999, 0 1050 local min, max, spd = 999999999999, 0
995 local num = '[%d%.]+[kM]?' 1051 local num = '[%d%.]+[kM]?'
996 if APT.checkFile(f) then 1052 if APT.checkFile(f) then
@@ -1022,7 +1078,7 @@ os.execute('sleep 1') -- Wait for things to start up before checking for them.
1022 1078
1023 if (APT.options.referenceSite.value ~= host) and ('' ~= list.nextf) then 1079 if (APT.options.referenceSite.value ~= host) and ('' ~= list.nextf) then
1024 local sem = 'results/NEW_' .. list.nextf .. '_%s.txt' 1080 local sem = 'results/NEW_' .. list.nextf .. '_%s.txt'
1025 for i, n in pairs(releases) do 1081 for i, n in pairs(APT.releases) do
1026 local f = sem:format(n) 1082 local f = sem:format(n)
1027 while not APT.checkFile(f) do 1083 while not APT.checkFile(f) do
1028 D('*&lt;* About to yield coroutine while waiting on - not APT.checkFile(' .. f .. ')') 1084 D('*&lt;* About to yield coroutine while waiting on - not APT.checkFile(' .. f .. ')')
@@ -1066,7 +1122,12 @@ if 0 < #arg then
1066 I("Starting tests for " .. arg[1] .. " with these tests - " .. table.concat(APT.options.tests.value, ", ")) 1122 I("Starting tests for " .. arg[1] .. " with these tests - " .. table.concat(APT.options.tests.value, ", "))
1067 APT.mirrors = loadfile("results/mirrors.lua")() 1123 APT.mirrors = loadfile("results/mirrors.lua")()
1068 APT.results = APT.padResults(APT.results) 1124 APT.results = APT.padResults(APT.results)
1069 if APT.origin or APT.redir then APT.results["IPs"] = gatherIPs(pu.host) end 1125 if APT.origin or APT.redir then
1126 if "" == pu.host then
1127 print("Empty pu.host name! " .. pu.host)
1128 end
1129 APT.results["IPs"] = gatherIPs(pu.host)
1130 end
1070 if nil ~= arg[2] then I(" &nbsp; Using IP " .. arg[2]); ip = arg[2] end 1131 if nil ~= arg[2] then I(" &nbsp; Using IP " .. arg[2]); ip = arg[2] end
1071 if nil ~= arg[3] then I(" &nbsp; Using file " .. arg[3]); end 1132 if nil ~= arg[3] then I(" &nbsp; Using file " .. arg[3]); end
1072 1133
@@ -1081,15 +1142,17 @@ if 0 < #arg then
1081 APT.allpairs(ips, 1142 APT.allpairs(ips,
1082 function(k, v) 1143 function(k, v)
1083 if v == "A" then 1144 if v == "A" then
1084 if APT.testing("IPv4") then APT.exe('./apt-panopticon.lua ' .. sendArgs .. ' -4 ' .. pu.host .. path .. ' ' .. k .. ' ' .. file):Nice():log():fork() end 1145 if APT.testing("IPv4") then APT.exe('./apt-panopticon.lua ' .. sendArgs .. ' -4 ' .. pu.host .. path .. ' ' .. k .. ' ' .. file):timeout(APT.options.maxtime.value * 2.0):Nice():log():fork(pu.host) end
1085 elseif v == "AAAA" then 1146 elseif v == "AAAA" then
1086 if APT.testing("IPv6") then APT.exe('./apt-panopticon.lua ' .. sendArgs .. ' -6 ' .. APT.IPv46 .. ' ' .. pu.host .. path .. ' ' .. k .. ' ' .. file):Nice():log():fork() end 1147 if APT.testing("IPv6") then APT.exe('./apt-panopticon.lua ' .. sendArgs .. ' -6 ' .. APT.IPv46 .. ' ' .. pu.host .. path .. ' ' .. k .. ' ' .. file):timeout(APT.options.maxtime.value * 2.0):Nice():log():fork(pu.host) end
1087 end 1148 end
1088 D('logging to ' .. APT.logName(pu.host, k, file)[2]) 1149 D('logging to ' .. APT.logName(pu.host, k, file)[2])
1089 end 1150 end
1090 ) 1151 )
1091 else 1152 else
1092 E("no IPs for " .. pu.host) 1153 E("no IPs for " .. pu.host)
1154 APT.logPost()
1155 return
1093 end 1156 end
1094 end 1157 end
1095 1158
@@ -1108,6 +1171,7 @@ if 0 < #arg then
1108 checkFiles(pu.host, pu.host, pu.path:sub(1, -1), file); 1171 checkFiles(pu.host, pu.host, pu.path:sub(1, -1), file);
1109 end 1172 end
1110 else 1173 else
1174 if "-6" == APT.IPv46 then arg[2] = '[' .. arg[2] .. ']' end
1111 checkHost(pu.host, pu.host, pu.path, arg[2], arg[3]) 1175 checkHost(pu.host, pu.host, pu.path, arg[2], arg[3])
1112 end 1176 end
1113 1177
@@ -1178,16 +1242,15 @@ else
1178 while 1 <= APT.checkExes("apt-panopticon.lua " .. sendArgs) do os.execute("sleep 5") end 1242 while 1 <= APT.checkExes("apt-panopticon.lua " .. sendArgs) do os.execute("sleep 5") end
1179 1243
1180 local APT_args = APT.args 1244 local APT_args = APT.args
1181 local APT_logFile = APT.logFile
1182 local debians = {} 1245 local debians = {}
1183 local srvs = io.popen('ls -1 results/*.lua') 1246 local srvs = APT.readCmd('ls -1 results/*.lua')
1184 for l in srvs:lines() do 1247 for ii,l in ipairs(srvs) do
1185 local hst = l:sub(9, -5) 1248 local hst = l:sub(9, -5)
1186 if nil ~= l:find('_R%.lua') then hst = hst:sub(1, -3) end 1249 if nil ~= l:find('_R%.lua') then hst = hst:sub(1, -3) end
1187 if (hst:find('_') == nil) and (nil == APT.mirrors[hst]) then 1250 if (hst:find('_') == nil) and (nil == APT.mirrors[hst]) then
1188 local ips = loadfile(l)().IPs 1251 local ips = loadfile(l)().IPs
1189 if nil ~= ips then 1252 if nil ~= ips then
1190 debians[hst] = {Country = '', FDQN = hst, Active = 'yes', Rate = '', BaseURL = hst, Protocols = {http = true, https = true}, Bandwidth = '', IPs = ips} 1253 debians[hst] = {Country = '', FQDN = hst, Active = 'yes', Rate = '', BaseURL = hst, Protocols = {http = true, https = true}, Bandwidth = '', IPs = ips}
1191 local baseFiles = {} 1254 local baseFiles = {}
1192 local IPfiles = {} 1255 local IPfiles = {}
1193 for i, a in pairs(ips) do 1256 for i, a in pairs(ips) do
@@ -1198,8 +1261,8 @@ else
1198 end 1261 end
1199 end 1262 end
1200 end 1263 end
1201 local files = io.popen('ls -1 results/LOG_' .. hst .. '_*.html') 1264 local files = APT.readCmd('ls -1 results/LOG_' .. hst .. '_*.html')
1202 for ll in files:lines() do 1265 for iii,ll in ipairs(files) do
1203 local dn = false 1266 local dn = false
1204 for i, a in pairs(ips) do 1267 for i, a in pairs(ips) do
1205 if type(a) == 'table' then 1268 if type(a) == 'table' then
@@ -1220,6 +1283,7 @@ else
1220 end 1283 end
1221 1284
1222 local combine = function(ip, a) 1285 local combine = function(ip, a)
1286 local APT_logFile = APT.logFile
1223 if not APT.logOpen(hst, ip) then 1287 if not APT.logOpen(hst, ip) then
1224 print('PROBLEM OPENING LOG FILE ' .. hst .. ' ' .. ip) 1288 print('PROBLEM OPENING LOG FILE ' .. hst .. ' ' .. ip)
1225 else 1289 else
@@ -1231,8 +1295,8 @@ else
1231 if ln:match('^' .. os.date('!%Y%-%m%-%d ') .. '.*$') then APT.logFile:write(ln .. '\n') end -- %F isn't good enough, coz we have to escape the '-'. 1295 if ln:match('^' .. os.date('!%Y%-%m%-%d ') .. '.*$') then APT.logFile:write(ln .. '\n') end -- %F isn't good enough, coz we have to escape the '-'.
1232 end 1296 end
1233 end 1297 end
1298 APT.logPost()
1234 end 1299 end
1235 APT.logPost()
1236 APT.args = APT_args 1300 APT.args = APT_args
1237 APT.logFile = APT_logFile 1301 APT.logFile = APT_logFile
1238 end 1302 end
diff --git a/laggers b/laggers
new file mode 100755
index 0000000..c5f30ee
--- /dev/null
+++ b/laggers
@@ -0,0 +1,3 @@
1#!/bin/bash
2echo "apt-panopticon processes still running -"
3ps ax -o pid,args --sort args | grep -E 'apt-panopticon\.lua | curl | dig ' | grep -v -E 'flock -n |grep -E |sh -c |timeout -k '
diff --git a/update_apt-panopticon b/update_apt-panopticon
index b70f4c3..969cc8f 100755
--- a/update_apt-panopticon
+++ b/update_apt-panopticon
@@ -1,16 +1,55 @@
1#!/bin/bash 1#!/bin/bash
2 2
3cd /var/www/html/apt-panopticon/apt-panopticon_cgp 3PANOPATH="/var/www/html/apt-panopticon"
4#git pull > /dev/null 4#KEEPDAYS=$((2 * 30))
5#chown -R mirrors:www-data * 5
6cd /var/www/html/apt-panopticon/apt-panopticon 6cd ${PANOPATH}/apt-panopticon_cgp
7#git pull > /dev/null 7if [ -d .git ] ; then
8#chown -R mirrors:www-data * 8 git pull > /dev/null
9 9 chown -hR www-data:www-data *
10if [ ! -f apt-panopticon.lock ] ; then 10fi
11 rm ../results; ln -s apt-panopticon/results_old ../results 11cd ${PANOPATH}/apt-panopticon
12 flock -n apt-panopticon.lock ./apt-panopticon.lua && rm apt-panopticon.lock 12if [ -d .git ] ; then
13 rm ../results; ln -s apt-panopticon/results ../results 13 git pull > /dev/null
14 chown -hR www-data:www-data *
15fi
16
17# Check if the lock file still exists.
18if [ -f apt-panopticon.lock ] ; then
19 # Check if it's still running.
20 ps ax -eo pid,args | grep "apt-panopticon.lua" | grep -v "grep apt-panopticon.lua" | while read line ; do touch apt-panopticon.running ; exit ; done
21 if [ -f apt-panopticon.running ] ; then
22 echo "Previous apt-panopticon still running, exiting."
23 echo "Previous apt-panopticon still running, exiting."
24 ./laggers
25 rm apt-panopticon.running
26 exit 1
27 fi
28 echo "Crashed apt-panopticon detected, removing stale lock file."
29 echo "Crashed apt-panopticon detected, removing stale lock file."
30 ./laggers
31 rm apt-panopticon.lock
32fi
33
34# Clean up any mess left over from failed runs.
35find results_* -maxdepth 2 ! -name "pkgmaster.devuan.org" -name "*.*" -type d -print0 | xargs -0rt /bin/rm -fr
36
37if [ "z" != "z${KEEPDAYS}" ] ; then
38 # Remove old results.
39 find . -daystart -maxdepth 2 -name "stamp" -type f ! -mtime $((0 - ${KEEPDAYS})) -printf "%h\0" | xargs -0rt /bin/rm -fr
40 find . -daystart -maxdepth 2 -name "results_*.tar.xz" -type f ! -mtime $((0 - ${KEEPDAYS})) -print0 | xargs -0rt /bin/rm -f
41 find . -maxdepth 1 -name "results_*" -type d -empty -print0 | xargs -0rt /bin/rm -fr
14fi 42fi
15 43
16#chown -R mirrors:www-data /var/www/html/SledjHamr/apt-panopticon/results 44rm ../results; ln -s apt-panopticon/results_old ../results
45flock -n apt-panopticon.lock ionice -c3 nice -n 19 timeout --kill-after=20.0 --foreground 8.5m ./apt-panopticon.lua && rm apt-panopticon.lock
46if [ -f apt-panopticon.lock ] ; then
47 echo "apt-panopticon timed out."
48 ./laggers
49fi
50rm ../results; ln -s apt-panopticon/results ../results
51
52chown -hR www-data:www-data *
53
54# Clean up any mess left over from THIS failed run.
55find results_* -maxdepth 2 ! -name "pkgmaster.devuan.org" -name "*.*" -type d -print0 | xargs -0rt /bin/rm -fr