mirror of
https://github.com/unraid/webgui.git
synced 2025-12-31 14:40:36 -06:00
838 lines
37 KiB
PHP
Executable File
838 lines
37 KiB
PHP
Executable File
#!/usr/bin/php -q
|
|
<?PHP
|
|
/* Copyright 2005-2023, Lime Technology
|
|
* Copyright 2012-2023, Bergware International.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License version 2,
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*/
|
|
?>
|
|
<?
|
|
// if called from webgui:
|
|
// anonymous: diagnostics '/usr/local/emhttp/tower-diagnostics-20230130-1546.zip'
|
|
// all data: diagnostics -a '/usr/local/emhttp/tower-diagnostics-20230130-1546.zip'
|
|
// if called from cli:
|
|
// anonymous: diagnostics
|
|
// all data: diagnostics -a
|
|
|
|
$opt = getopt('a',['all']);
|
|
$all = isset($opt['a']) || isset($opt['all']);
|
|
$zip = $all ? ($argv[2]??'') : ($argv[1]??'');
|
|
$cli = empty($zip);
|
|
|
|
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
|
require_once "$docroot/webGui/include/Helpers.php";
|
|
require_once "$docroot/webGui/include/Wrappers.php";
|
|
require_once "$docroot/webGui/include/publish.php";
|
|
|
|
if (is_file('/boot/syslinux/syslinux.cfg')) {
|
|
$bootenv = '/boot/syslinux';
|
|
} elseif (is_file('/boot/grub/grub.cfg')) {
|
|
$bootenv = '/boot/grub';
|
|
}
|
|
|
|
$folders = ['/boot','/boot/config','/boot/config/plugins','/boot/config/firmware',$bootenv,'/var/log','/var/log/plugins','/boot/extra','/var/log/packages','/var/lib/pkgtools/packages','/tmp'];
|
|
|
|
// global variables
|
|
$path = "/var/local/emhttp";
|
|
$var = (array)@parse_ini_file("$path/var.ini");
|
|
$disks = (array)@parse_ini_file("$path/disks.ini",true);
|
|
$pools = pools_filter($disks);
|
|
|
|
require_once "$docroot/webGui/include/CustomMerge.php";
|
|
|
|
function write(...$messages){
|
|
foreach ($messages as $message) {
|
|
publish('diagnostics', $message,1,false);
|
|
}
|
|
}
|
|
|
|
// Add error logging function
|
|
function log_error($message, $command = '') {
|
|
global $diag;
|
|
$error_log = "/$diag/logs/diagnostics.error.log";
|
|
$timestamp = date('Y-m-d H:i:s');
|
|
$log_message = "[$timestamp] $message";
|
|
if ($command) {
|
|
$log_message .= " (Command: $command)";
|
|
}
|
|
file_put_contents($error_log, $log_message . "\r\n", FILE_APPEND);
|
|
}
|
|
|
|
// Modify run function to include error logging
|
|
function run($cmd, &$save=null, $timeout=30) {
|
|
global $cli,$diag;
|
|
// output command for display
|
|
write($cmd);
|
|
// execute command with timeout of 30s
|
|
exec("LC_ALL=en_US.UTF-8 timeout -s9 $timeout $cmd 2>&1", $save, $return_code);
|
|
if ($return_code !== 0) {
|
|
log_error("Command failed with return code $return_code", $cmd);
|
|
}
|
|
return implode("\n",$save);
|
|
}
|
|
|
|
function newline($file) {
|
|
$tmp_file = "/tmp/".basename($file);
|
|
copy($file, $tmp_file);
|
|
exec("/usr/bin/todos < ".escapeshellarg($tmp_file)." > ".escapeshellarg($file));
|
|
unlink($tmp_file);
|
|
}
|
|
|
|
function shareDisks($share) {
|
|
return str_replace(',',', ',exec("shopt -s dotglob; getfattr --no-dereference --absolute-names --only-values -n system.LOCATIONS ".escapeshellarg("/mnt/user/$share")." 2>/dev/null") ?: "");
|
|
}
|
|
|
|
function anonymize($text, $select) {
|
|
global $all,$var,$pools,$customShares;
|
|
if ($all) return $text;
|
|
switch ($select) {
|
|
case 1:
|
|
// remove any stray references to the GUID that may wind up in .ini files (notably Unassigned Devices)
|
|
$guid = explode('-',_var($var,'regGUID'));
|
|
$text = str_replace(end($guid),"...",$text);
|
|
$rows = explode("\n", $text);
|
|
$pool = implode('|',$pools) ?: 'cache';
|
|
$regex = "/\b((disk|$pool|parity|cpu|eth|dev)[0-9]+)|(smart|flash|flashbackup|$pool|parity|cpu{$customShares})\b/";
|
|
foreach ($rows as &$row) {
|
|
if (!preg_match($regex, $row)) {
|
|
$row = preg_replace("/^(\s*\[\S).*(\S\])( => Array)$/","$1..$2$3",$row);
|
|
$row = preg_replace("/^(\s*\[(cachePool|name|nameOrig|comment|flashGUID|regGUID|regTo|readList|writeList|csrf_token|NGINX_DEFAULTURL|NGINX_CERTNAME|NGINX_LANFQDN|NGINX_WANFQDN|NGINX_WANIP)\] => \S).*(\S)$/","$1..$3",$row);
|
|
$row = preg_replace('/(\[(USERNAME|PASSWORD)\] =>).*/','$1 removed',$row);
|
|
}
|
|
}
|
|
return implode("\n", $rows);
|
|
case 2:
|
|
// anonymize share configuration name - make it unique
|
|
$name = basename($text,'.cfg');
|
|
if (!in_array($name,$pools)) {
|
|
$len = strlen($name);
|
|
if ($len>2) {
|
|
$dash = str_repeat('-',$len-2);
|
|
$name = preg_replace("/^(\S).*(\S)/","$1$dash$2",$name);
|
|
$i = 1;
|
|
while (file_exists(dirname($text)."/$name.cfg")) {$name = substr($name,0,$len)." ($i)"; $i++;}
|
|
}
|
|
}
|
|
return dirname($text)."/$name.cfg";
|
|
}
|
|
}
|
|
|
|
function maskIP($file) {
|
|
global $all;
|
|
|
|
if ($all) return;
|
|
|
|
// anonymize public IPv4 addresses
|
|
$rfc1918 = "(127|10|172\.1[6-9]|172\.2[0-9]|172\.3[0-1]|192\.168)((\.[0-9]{1,3}){2,3}([/\" .]|$))";
|
|
run("sed -ri 's/([\"\[ ]){$rfc1918}/\\1@@@\\2\\3/g; s/([\"\[ ][0-9]{1,3}\.)([0-9]{1,3}\.){2}([0-9]{1,3})([/\" .]|$)/\\1XXX.XXX.\\3\\4/g; s/@@@//g' ".escapeshellarg($file));
|
|
|
|
// Anonymize IPv6 addresses without brackets
|
|
run("sed -ri 's/(([0-9a-f]{1,4}:){4})(([0-9a-f]{1,4}:){3}|:)([0-9a-f]{1,4})([ .:/]|$)/\\1XXXX:XXXX:XXXX:\\5\\6/g' ".escapeshellarg($file));
|
|
|
|
// Anonymize IPv6 addresses with brackets
|
|
run("sed -ri 's/(\[([0-9a-f]{1,4}:){4})(([0-9a-f]{1,4}:){3}|:)([0-9a-f]{1,4})(\])([ .:/]|$)/\\1XXXX:XXXX:XXXX:\\5\\6/g' ".escapeshellarg($file));
|
|
|
|
// Handle any remaining edge cases, e.g., addresses with subnet masks
|
|
run("sed -ri 's/(([0-9a-f]{1,4}:){4})(([0-9a-f]{1,4}:){3}|:)([0-9a-f]{1,4})(\/[0-9]{1,3})([ .:/]|$)/\\1XXXX:XXXX:XXXX:\\5\\7/g' ".escapeshellarg($file));
|
|
}
|
|
|
|
function download_url($url, $path="", $bg=false, $timeout=15) {
|
|
$ch = curl_init();
|
|
curl_setopt_array($ch,[
|
|
CURLOPT_URL => $url,
|
|
CURLOPT_FRESH_CONNECT => true,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_CONNECTTIMEOUT => 10,
|
|
CURLOPT_TIMEOUT => $timeout,
|
|
CURLOPT_ENCODING => "",
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_FOLLOWLOCATION => true
|
|
]);
|
|
$out = curl_exec($ch);
|
|
curl_close($ch);
|
|
if ($path) file_put_contents($path,$out);
|
|
return $out ?: false;
|
|
}
|
|
|
|
function geturls_certdetails($file, $hostname, $ip="") {
|
|
// called by the geturls() function
|
|
// best to ensure the file exists before calling this function
|
|
if (!file_exists($file)) return ['', '', ''];
|
|
// read the cert
|
|
$data = null;
|
|
exec("/usr/bin/openssl x509 -noout -subject -nameopt multiline -in ".escapeshellarg($file), $data);
|
|
$data = implode("\n", $data);
|
|
// determine cn
|
|
preg_match('/ *commonName *= (.*)/', $data, $matches);
|
|
$cn = trim($matches[1]??'');
|
|
if (strpos($cn, ".myunraid.net") !== false) {
|
|
$type = 'myunraid.net';
|
|
$iphost = str_replace('.','-',$ip);
|
|
// anonymize ip portion of hostname if not a private ip
|
|
$priv_iphost = (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) ? "ipaddress" : $iphost;
|
|
// anonymize myunraid.net hash
|
|
$cn_priv = preg_replace('/\*\.([a-f0-9]*)\.myunraid\.net/', "{$priv_iphost}.hash.myunraid.net", $cn);
|
|
// replace wildcard with ip
|
|
$cn = str_replace('*', $iphost, $cn);
|
|
} elseif (strpos($cn, ".unraid.net") !== false) {
|
|
$type = 'unraid.net';
|
|
// anonymize unraid.net hash
|
|
$cn_priv = preg_replace('/.*\.unraid\.net/', 'hash.unraid.net', $cn);
|
|
} else {
|
|
// replace wildcard with hostname
|
|
$cn = str_replace('*', $hostname, $cn);
|
|
$cn_priv = $cn;
|
|
if (strpos($data, "Self-signed") !== false){
|
|
$type = 'self-signed';
|
|
} else {
|
|
$type = 'user-provided';
|
|
}
|
|
}
|
|
return [$cn, $cn_priv, $type];
|
|
}
|
|
|
|
function geturls_checkhost($host, $hostpriv, $expectedip, $dnsserver) {
|
|
// called by the geturls() function
|
|
// dns lookups will fail if there is no TLD or if it is ".local", so skip it
|
|
if (strpos($host, '.') === false || strpos($host, '.local') !== false) return '';
|
|
$result = @dns_get_record($host, DNS_A);
|
|
$ip = ($result) ? $result[0]['ip'] : '';
|
|
if ($ip == '') return " ERROR: When using DNS server {$dnsserver}, the host {$hostpriv} does not resolve.\n";
|
|
if ($ip != $expectedip) {
|
|
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) $ip = "[redacted]";
|
|
if (filter_var($expectedip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) $expectedip = "[redacted]";
|
|
return " ERROR: When using DNS server {$dnsserver}, {$hostpriv} resolves to {$ip}. It should resolve to {$expectedip}\n";
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function geturls() {
|
|
global $var,$path;
|
|
extract(@parse_ini_file("$path/network.ini",true));
|
|
$nginx = @parse_ini_file("$path/nginx.ini");
|
|
$internalip = $internalip_priv = $internalip_msg = _var($eth0,'IPADDR:0');
|
|
$dnsserver = _var($eth0,'DNS_SERVER1');
|
|
if (filter_var($internalip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
|
|
$internalip_priv = "ipaddress";
|
|
$internalip_msg = "redacted (FYI - this system has a routable IP address, ensure it is behind a firewall)";
|
|
}
|
|
$host_tld_msg = _var($var,'LOCAL_TLD') ? '' : '[blank] (FYI - a blank TLD can cause issues for Mac and Linux clients)';
|
|
$isLegacyCert = preg_match('/.*\.unraid\.net$/',_var($nginx,'NGINX_CERTNAME'));
|
|
$rebindtesturl = $isLegacyCert ? "rebindtest.unraid.net" : "rebindtest.myunraid.net";
|
|
$rebindtestdomain = $isLegacyCert ? "unraid.net" : "myunraid.net";
|
|
$rebindip = "192.168.42.42";
|
|
$rebindtest_ip = exec("host -4 $rebindtesturl 2>/dev/null|sed -n 's/.*has address //p'");
|
|
$rebind_msg = ($rebindtest_ip != $rebindip) ? "is enabled, $rebindtestdomain urls will not work" : "is disabled, $rebindtestdomain urls will work";
|
|
// show raw data from config files
|
|
$urls = '';
|
|
$urls .= "Server Name: "._var($var,'NAME','tower')."\n";
|
|
$urls .= "Local TLD: "._var($var,'LOCAL_TLD').$host_tld_msg."\n";
|
|
$urls .= "HTTP port: "._var($var,'PORT',80)."\n";
|
|
$urls .= "HTTPS port: "._var($var,'PORTSSL',443)."\n";
|
|
$urls .= "Internal IP: {$internalip_msg}\n";
|
|
$urls .= "DNS 1: {$dnsserver}\n";
|
|
$urls .= "USE SSL: "._var($var,'USE_SSL','no')."\n";
|
|
$urls .= "DNS Rebinding Protection {$rebind_msg} on this network\n\n";
|
|
$urls .= "Available URLs:\n (the URL marked with an asterisk is the primary url for this server)\n";
|
|
// calculate variables
|
|
$cert_path = "/boot/config/ssl/certs/";
|
|
$host_name = _var($var,'NAME','tower');
|
|
$host_tld = _var($var,'LOCAL_TLD') ? ".{$var['LOCAL_TLD']}" : '';
|
|
$use_ssl = _var($var,'USE_SSL','no');
|
|
$http_port = _var($var,'PORT',80)!=80 ? ":{$var['PORT']}" : '';
|
|
$https_port = _var($var,'PORTSSL',443)!=443 ? ":{$var['PORTSSL']}" : '';
|
|
$https_1_cert = "{$host_name}_unraid_bundle.pem";
|
|
$https_2_cert = 'certificate_bundle.pem';
|
|
$http_primary = $https_1_primary = $https_2_primary = $http_msg = $https_1_msg = $https_2_msg = '';
|
|
$expected_host = "{$host_name}{$host_tld}";
|
|
switch ($use_ssl) {
|
|
case "no":
|
|
$http_primary = '*';
|
|
break;
|
|
case "yes":
|
|
$https_1_primary = '*';
|
|
$http_msg = "\n (this will redirect to the primary url)";
|
|
break;
|
|
case "auto":
|
|
$http_msg = "\n (this will redirect to the primary url)";
|
|
$https_1_msg = "\n (this will redirect to the primary url)";
|
|
$https_2_primary = '*';
|
|
break;
|
|
}
|
|
// calculate http ip url
|
|
$http_ip_url = "http://{$internalip_priv}{$http_port}";
|
|
$urls .= "HTTP IP url: {$http_ip_url}{$http_msg}\n";
|
|
// calculate http url
|
|
$http_url = "http://{$expected_host}{$http_port}";
|
|
$urls .= "{$http_primary}HTTP url: {$http_url}{$http_msg}\n";
|
|
$urls .= geturls_checkhost($expected_host, $expected_host, $internalip, $dnsserver);
|
|
// calculate https url - self-signed or user-provided in tower_unraid_bundle.pem
|
|
// this is available when USE_SSL != no, and the certificate file exists
|
|
if ($use_ssl != "no" && file_exists("{$cert_path}{$https_1_cert}")) {
|
|
[$https_1_host, $https_1_hostpriv, $https_1_type] = geturls_certdetails("{$cert_path}{$https_1_cert}", $host_name);
|
|
$https_1_url = "https://{$https_1_hostpriv}{$https_port}";
|
|
$urls .= "{$https_1_primary}HTTPS url 1 ($https_1_type): {$https_1_url}{$https_1_msg}\n";
|
|
$urls .= geturls_checkhost($https_1_host, $https_1_hostpriv, $internalip, $dnsserver);
|
|
if (strtolower($https_1_host) != strtolower($expected_host)) {
|
|
$urls .= " ERROR: the certificate Subject CN in {$https_1_cert} should be {$expected_host}\n";
|
|
}
|
|
} else {
|
|
// add a note that this url is not configured
|
|
$urls .= "HTTPS url 1 (undefined): https://{$expected_host}{$https_port}\n (this url is not configured, it will not work)\n";
|
|
$urls .= geturls_checkhost($expected_host, $expected_host, $internalip, $dnsserver);
|
|
}
|
|
// calculate https url for certificate_bundle.pem
|
|
// this is available if the certificate file exists, regardless of the USE_SSL setting
|
|
// this is usually a (my)unraid.net LE cert, but it can also be a user-provided cert
|
|
if (file_exists("{$cert_path}{$https_2_cert}")) {
|
|
[$https_2_host, $https_2_hostpriv, $https_2_type] = geturls_certdetails("{$cert_path}{$https_2_cert}", $host_name, $internalip);
|
|
$https_2_url = "https://{$https_2_hostpriv}{$https_port}";
|
|
$urls .= "{$https_2_primary}HTTPS url 2 ({$https_2_type}): {$https_2_url}{$https_2_msg}\n";
|
|
$urls .= geturls_checkhost($https_2_host, $https_2_hostpriv, $internalip, $dnsserver);
|
|
if (strpos($https_2_host, ".unraid.net") === false && strpos($https_2_host, ".myunraid.net") === false && strtolower($https_2_host) != strtolower($expected_host)) {
|
|
$urls .= " ERROR: the certificate Subject CN in {$https_2_cert} should be {$expected_host}\n";
|
|
}
|
|
}
|
|
if ($use_ssl != "no") {
|
|
$telnet_disabled = _var($var,'USE_TELNET')=="no" ? " (disabled)" : "";
|
|
$ssh_disabled = _var($var,'USE_SSH')=="no" ? " (disabled)" : "";
|
|
$urls .= "\nTip: if DNS goes down and you lose access to the webgui, use telnet{$telnet_disabled}, ";
|
|
$urls .= "ssh{$ssh_disabled}, or a local keyboard/monitor to run:\n";
|
|
$urls .= " use_ssl no\n";
|
|
$urls .= "to enable 'HTTP IP url' and make 'HTTP url' the primary url for the system. ";
|
|
if ($use_ssl == "auto") {
|
|
$urls .= "Or:\n";
|
|
$urls .= " use_ssl yes\n";
|
|
$urls .= "to make 'HTTPS url 1' the primary.";
|
|
}
|
|
$urls .= "\nOnce DNS has been restored, navigate to Settings -> Management Access and set 'Use SSL' back to '$use_ssl'\n";
|
|
}
|
|
// get a list of the certificate files on the flash drive
|
|
$dirlisting[0] = "{$cert_path}";
|
|
if (file_exists($cert_path)) {
|
|
exec("ls -l ".escapeshellarg($cert_path), $dirlisting);
|
|
} else {
|
|
$dirlisting[1] = "Directory not found";
|
|
}
|
|
$urls .= "\n\n".implode("\n", $dirlisting)."\n";
|
|
return str_replace("\n", "\r\n", $urls);
|
|
}
|
|
|
|
// anonymize individual syslog files
|
|
function anonymize_syslog($file) {
|
|
global $diag, $all;
|
|
$max = 2*1024*1024; //=2MB
|
|
$log = "/$diag/logs/".basename($file);
|
|
run("todos <".escapeshellarg($file)." >".escapeshellarg("$log.txt"));
|
|
if (!$all) {
|
|
unset($titles,$rows);
|
|
run("grep -Po 'file: \K[^\"\\x27]+' ".escapeshellarg("$log.txt")." 2>/dev/null|sort|uniq", $titles);
|
|
run("sed -ri 's|\b\S+@\S+\.\S+\b|email@removed.com|;s|\b(username\|password)([=:])\S+\b|\\1\\2xxx|;s|(GUID: \S)\S+(\S) |\\1..\\2 |;s|(moving \"\S\|\"/mnt/user/\S).*(\S)\"|\\1..\\2\"|' ".escapeshellarg("$log.txt"));
|
|
run("sed -ri 's|(server: ).+(\.(my)?unraid\.net(:[0-9]+)?,)|\\1hash\\2|;s|(host: \").+(\.(my)?unraid\.net(:[0-9]+)?\")|\\1hash\\2|;s|(referrer: \"https?://).+(\.(my)?unraid\.net)|\\1hash\\2|' ".escapeshellarg("$log.txt"));
|
|
maskIP("$log.txt");
|
|
foreach ($titles as $mover) {
|
|
if (!$mover) continue;
|
|
$title = "/{$mover[0]}..".substr($mover,-1)."/...";
|
|
run("sed -i 's/".str_replace("/","\/",$mover)."/".str_replace("/","\/",$title)."/g' ".escapeshellarg("$log.txt"));
|
|
//run("sed -ri 's|(file: [.>cr].*)[ /]$mover/.*$|\\1 file: $title|' ".escapeshellarg("$log.txt"));
|
|
}
|
|
run("grep -n ' cache_dirs: -' ".escapeshellarg("$log.txt")." 2>/dev/null|cut -d: -f1", $rows);
|
|
for ($i = 0; $i < count($rows); $i += 2) for ($row = $rows[$i]+1; $row < $rows[$i+1]; $row++) run("sed -ri '$row s|(cache_dirs: \S).*(\S)|\\1..\\2|' ".escapeshellarg("$log.txt"));
|
|
}
|
|
// replace consecutive repeated lines in syslog
|
|
run("awk -b -i inplace '{if(s!=substr($0,17)){if(x>0)print\"### [PREVIOUS LINE REPEATED \"x\" TIMES] ###\r\";print;x=0}else{x++}s=substr($0,17)}END{if(x>0)print\"### [PREVIOUS LINE REPEATED \"x\" TIMES] ###\r\"}' ".escapeshellarg("$log.txt"));
|
|
// remove SHA256 hashes
|
|
run("sed -ri 's/(SHA256:).+[^\s\b]/SHA256:***REMOVED***/gm' ".escapeshellarg("$log.txt"));
|
|
// truncate syslog if too big
|
|
if (basename($file)=='syslog' && filesize($file)>=$max) run("tail -n 200 ".escapeshellarg("$log.txt")." >".escapeshellarg("$log.last200.txt"));
|
|
run("truncate -s '<$max' ".escapeshellarg("$log.txt"));
|
|
}
|
|
|
|
// diagnostics start
|
|
run("mkdir -p /boot/logs");
|
|
|
|
if ($cli) {
|
|
// script is called from CLI
|
|
echo "Starting diagnostics collection... ";
|
|
$server = isset($var['NAME']) ? str_replace(' ','_',strtolower($var['NAME'])) : 'tower';
|
|
$date = date('Ymd-Hi');
|
|
|
|
$safeMode = (_var($var,'safeMode') == 'yes') ? "-safemode" : "";
|
|
$diag = "$server$safeMode-diagnostics-$date";
|
|
$zip = "/boot/logs/$diag.zip";
|
|
} else {
|
|
// script is called from GUI
|
|
$diag = basename($zip, '.zip');
|
|
$split = explode('-', $diag);
|
|
$date = "{$split[2]}-{$split[3]}";
|
|
}
|
|
|
|
// Run Fix Common Problems if present and results are old / not present
|
|
if ( is_file("/usr/local/emhttp/plugins/fix.common.problems/scripts/scan.php") ) {
|
|
if ( ! is_file("/tmp/fix.common.problems/errors.json") || (time() - filemtime("/tmp/fix.common.problems/errors.json")) > 86400) {
|
|
run("/usr/local/emhttp/plugins/fix.common.problems/scripts/scan.php diagnostics",$ignore,60);
|
|
}
|
|
}
|
|
|
|
// don't anonymize system share names
|
|
$vardomain = (array)@parse_ini_file('/boot/config/domain.cfg');
|
|
$vardocker = (array)@parse_ini_file('/boot/config/docker.cfg');
|
|
$showshares = [];
|
|
$customShares = '';
|
|
if (!empty($vardomain['IMAGE_FILE'])) $showshares[] = current(array_slice(explode('/',$vardomain['IMAGE_FILE']),3,1));
|
|
if (!empty($vardomain['DOMAINDIR'])) $showshares[] = current(array_slice(explode('/',$vardomain['DOMAINDIR']),3,1));
|
|
if (!empty($vardomain['MEDIADIR'])) $showshares[] = current(array_slice(explode('/',$vardomain['MEDIADIR']),3,1));
|
|
if (!empty($vardomain['DISKDIR'])) $showshares[] = current(array_slice(explode('/',$vardomain['DISKDIR']),3,1));
|
|
if (!empty($vardocker['DOCKER_IMAGE_FILE'])) $showshares[] = current(array_slice(explode('/',$vardocker['DOCKER_IMAGE_FILE']),3,1));
|
|
if (!empty($vardocker['DOCKER_APP_CONFIG_PATH'])) $showshares[] = current(array_slice(explode('/',$vardocker['DOCKER_APP_CONFIG_PATH']),3,1));
|
|
if (!empty($vardocker['DOCKER_HOME'])) $showshares[] = current(array_slice(explode('/',$vardocker['DOCKER_HOME']),3,1));
|
|
|
|
foreach ($showshares as $showme) if ($showme) $customShares .= "|$showme";
|
|
|
|
// create folder structure
|
|
run("mkdir -p ".escapeshellarg("/$diag/system")." ".escapeshellarg("/$diag/config")." ".escapeshellarg("/$diag/logs")." ".escapeshellarg("/$diag/shares")." ".escapeshellarg("/$diag/smart")." ".escapeshellarg("/$diag/qemu")." ".escapeshellarg("/$diag/xml"));
|
|
|
|
// get utilization of running processes
|
|
run("top -bn1 -o%CPU 2>/dev/null|todos >".escapeshellarg("/$diag/system/top.txt"));
|
|
|
|
// make Unraid version reference
|
|
$unraid = parse_ini_file('/etc/unraid-version');
|
|
file_put_contents("/$diag/unraid-".$unraid['version'].".txt",$unraid['version']."\r\n");
|
|
|
|
// add bz*.sha256 values
|
|
run("tail /boot/bz*.sha256 >> ".escapeshellarg("/$diag/unraid-".$unraid['version'].".txt"));
|
|
|
|
// Get the previous version of Unraid from the previous directory on flash
|
|
$changes = '/boot/previous/changes.txt';
|
|
|
|
if (file_exists($changes)) {
|
|
exec("head -n4 $changes",$rows);
|
|
foreach ($rows as $row) {
|
|
$i = stripos($row, 'version');
|
|
if ($i !== false) {
|
|
[$version,$date] = explode(' ', trim(substr($row,$i+7)));
|
|
break;
|
|
}
|
|
}
|
|
$previous_version = "Previous Version: ".$version;
|
|
file_put_contents("/$diag/unraid-".$unraid['version'].".txt", "\r\n".$previous_version."\r\n", FILE_APPEND);
|
|
} else {
|
|
file_put_contents("/$diag/unraid-".$unraid['version'].".txt", "\r\nNo Previous Version Found\r\n", FILE_APPEND);
|
|
}
|
|
|
|
// copy ini variables
|
|
foreach (glob("$path/*.ini") as $file) {
|
|
$ini = basename($file,".ini");
|
|
// skip users file in anonymized mode
|
|
if ($all || $ini != "users") file_put_contents("/$diag/system/vars.txt",preg_replace(["/\n/","/^Array/"],["\r\n",$ini],anonymize(print_r(parse_ini_file($file,true),true),1)),FILE_APPEND);
|
|
}
|
|
|
|
// Create loads.txt
|
|
$cpuload = run("uptime")." Cores: ".run("nproc")."\r\n".(string)@file_get_contents("$path/cpuload.ini")."\r\n";
|
|
$loadTxt = [];
|
|
if (file_exists("$path/diskload.ini")){
|
|
$diskload = file("$path/diskload.ini");
|
|
foreach ($diskload as $loadLine) {
|
|
$load = explode('=',$loadLine);
|
|
foreach ($disks as $disk) {
|
|
if ($load[0]==_var($disk,'device')) {
|
|
$loadTxt[] = _var($disk,'device')." ("._var($disk,'name').")=".trim($load[1]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
file_put_contents("/$diag/system/loads.txt",$cpuload.implode("\r\n",$loadTxt));
|
|
|
|
// individual commands execution (suppress errors)
|
|
run("lscpu 2>/dev/null|todos >".escapeshellarg("/$diag/system/lscpu.txt"));
|
|
run("lsscsi -vgl 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsscsi.txt"));
|
|
run("lspci -knn 2>/dev/null|todos >".escapeshellarg("/$diag/system/lspci.txt"));
|
|
run("lspci -vv 2>/dev/null| awk -b '/ASPM/{print $0}' RS=|grep -P '(^[a-z0-9:.]+|ASPM |Disabled;|Enabled;)'|todos >".escapeshellarg("/$diag/system/aspm-status.txt"));
|
|
run("lsusb 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsusb.txt"));
|
|
run("free -mth 2>/dev/null|todos >".escapeshellarg("/$diag/system/memory.txt"));
|
|
run("lsof -Pni 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsof.txt"));
|
|
run("lsmod|sort 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsmod.txt"));
|
|
run("df -h 2>/dev/null|todos >".escapeshellarg("/$diag/system/df.txt"));
|
|
run("ip -br a|awk '/^(eth|bond)[0-9]+ /{print \$1}'|sort",$ports);
|
|
run("dmidecode -qt2|awk -F: '/^\tManufacturer:/{m=\$2};/^\tProduct Name:/{p=\$2} END{print m\" -\"p}' 2>/dev/null|todos >".escapeshellarg("/$diag/system/motherboard.txt"));
|
|
run("dmidecode -qt0 2>/dev/null|todos >>".escapeshellarg("/$diag/system/motherboard.txt"));
|
|
run("cat /proc/meminfo 2>/dev/null|todos >".escapeshellarg("/$diag/system/meminfo.txt"));
|
|
run("dmidecode --type 17 2>/dev/null|todos >>".escapeshellarg("/$diag/system/meminfo.txt"));
|
|
|
|
// mask IP addresses in lsof.txt
|
|
maskIP("/$diag/system/lsof.txt");
|
|
|
|
// create ethernet information information (suppress errors)
|
|
foreach ($ports as $port) {
|
|
run("ethtool ".escapeshellarg($port)." 2>/dev/null|todos >>".escapeshellarg("/$diag/system/ethtool.txt"));
|
|
file_put_contents("/$diag/system/ethtool.txt", "\r\n", FILE_APPEND);
|
|
run("ethtool -i ".escapeshellarg($port)." 2>/dev/null|todos >>".escapeshellarg("/$diag/system/ethtool.txt"));
|
|
file_put_contents("/$diag/system/ethtool.txt", "--------------------------------\r\n", FILE_APPEND);
|
|
}
|
|
run("ip -br a|todos >".escapeshellarg("/$diag/system/ifconfig.txt"));
|
|
maskIP("/$diag/system/ifconfig.txt");
|
|
|
|
// create system information (suppress errors)
|
|
run("find /sys/kernel/iommu_groups/ -type l 2>/dev/null|sort -V|todos >".escapeshellarg("/$diag/system/iommu_groups.txt"));
|
|
run("todos </proc/cmdline >".escapeshellarg("/$diag/system/cmdline.txt"));
|
|
|
|
// create folder structure listing
|
|
$dest = "/$diag/system/folders.txt";
|
|
foreach ($folders as $folder) {
|
|
if (is_dir($folder)) run("echo -ne ".escapeshellarg("\r\n$folder\r\n")." >>".escapeshellarg($dest).";ls -l ".escapeshellarg($folder)."|todos >>".escapeshellarg("$dest")); else run("echo -ne ".escapeshellarg("\r\n$folder\r\nfolder does not exist\r\n")." >>".escapeshellarg("$dest"));
|
|
}
|
|
|
|
// copy configuration files
|
|
if (glob("/boot/config/*.cfg")) {
|
|
run("cp -- /boot/config/*.cfg ".escapeshellarg("/$diag/config"));
|
|
}
|
|
if (glob("/boot/config/*.conf")) {
|
|
run("cp -- /boot/config/*.conf ".escapeshellarg("/$diag/config"));
|
|
}
|
|
if (glob("/boot/config/*.dat")) {
|
|
run("cp -- /boot/config/*.dat ".escapeshellarg("/$diag/config"));
|
|
}
|
|
|
|
// handle go files
|
|
foreach (['/boot/config/go', '/boot/config/go.safemode'] as $go) {
|
|
if (file_exists($go)) {
|
|
$dest = "/$diag/config/" . basename($go) . ".txt";
|
|
run("cp " . escapeshellarg($go) . " " . escapeshellarg($dest));
|
|
|
|
// anonymize go file
|
|
if (!$all) {
|
|
run("sed -i -e '/password/c ***line removed***' -e '/user/c ***line removed***' -e '/pass/c ***line removed***' " . escapeshellarg($dest));
|
|
}
|
|
}
|
|
}
|
|
|
|
// anonymize configuration files
|
|
if (!$all) {
|
|
run("find ".escapeshellarg("/$diag/config")." -name '*.cfg' -exec sed -ri 's/^((disk|flash)(Read|Write)List.*=\")[^\"]+/\\1.../' {} \\;");
|
|
// anonymize IP addresses
|
|
maskIP("/$diag/config/network.cfg");
|
|
// anonymize wireless credentials
|
|
if (file_exists("/$diag/config/wireless.cfg")) {
|
|
run("sed -ri 's/^((USERNAME|PASSWORD)=\")[^\"]+/\\1.../' ".escapeshellarg("/$diag/config/wireless.cfg"));
|
|
}
|
|
}
|
|
// include listening interfaces
|
|
run("$docroot/webGui/scripts/show_interfaces ip|tr ',' '\n' >".escapeshellarg("/$diag/config/listen.txt"));
|
|
run("$docroot/webGui/scripts/error_interfaces|sed 's/<i.*i>//' >>".escapeshellarg("/$diag/config/listen.txt"));
|
|
maskIP("/$diag/config/listen.txt");
|
|
|
|
// copy share information (anonymize if applicable)
|
|
$files = glob("/boot/config/shares/*.cfg");
|
|
$shareDisk = [];
|
|
foreach ($files as $file) {
|
|
$dest = "/$diag/shares/".basename($file);
|
|
$share = basename($file,'.cfg');
|
|
if (!in_array($share,$showshares)) $dest = anonymize($dest,2);
|
|
@copy($file, $dest);
|
|
if (!$all) run("sed -ri 's/^(share(Comment|ReadList|WriteList)=\")[^\"]+/\\1.../' ".escapeshellarg($dest));
|
|
$home = shareDisks($share);
|
|
$home = $home ? "# Share exists on $home\r\n" : "# Share does not exist\r\n";
|
|
$shareDisk[] = str_pad(basename($dest,'.cfg'),34).str_pad(exec("grep -m1 'shareUseCache' ".escapeshellarg($file)),24).$home;
|
|
file_put_contents($dest,$home.file_get_contents($dest));
|
|
}
|
|
file_put_contents("/$diag/shares/shareDisks.txt",implode($shareDisk));
|
|
|
|
// create default user shares information
|
|
$shares = (array)@parse_ini_file("$path/shares.ini", true);
|
|
foreach ($shares as $share) {
|
|
$name = _var($share,'name');
|
|
if ($name && !in_array("/boot/config/shares/$name.cfg",$files)) {
|
|
$home = shareDisks($name);
|
|
$home = $home ? "# Share exists on $home\r\n" : "# Share does not exist\r\n";
|
|
$file = anonymize("/$diag/shares/$name.cfg",2);
|
|
file_put_contents($file,"# This share has default settings.\r\n".$home);
|
|
file_put_contents("/$diag/shares/shareDisks.txt",str_pad(basename($file,'.cfg'),34).str_pad('shareUseCache="no"',24).$home,FILE_APPEND);
|
|
}
|
|
}
|
|
|
|
// copy pools information (anonymize)
|
|
$files = glob("/boot/config/pools/*.cfg");
|
|
@mkdir("/$diag/config/pools");
|
|
foreach ($files as $file) {
|
|
$dest = anonymize("/$diag/config/pools/".basename($file),2);
|
|
@copy($file,$dest);
|
|
}
|
|
|
|
// copy modprobe information
|
|
$files = glob("/boot/config/modprobe.d/*.conf");
|
|
if ($files) {
|
|
@mkdir("/$diag/config/modprobe.d");
|
|
foreach ($files as $file) {
|
|
$dest = "/$diag/config/modprobe.d/".basename($file);
|
|
@copy($file,$dest);
|
|
}
|
|
}
|
|
|
|
// copy cutom udev rules information
|
|
$files = glob("/boot/config/udev/*");
|
|
if ($files) {
|
|
@mkdir("/$diag/config/udev");
|
|
foreach ($files as $file) {
|
|
$dest = "/$diag/config/udev/".basename($file);
|
|
@copy($file,$dest);
|
|
}
|
|
}
|
|
|
|
// copy docker information (if existing)
|
|
$max = 1*1024*1024; //=1MB
|
|
$docker = "/var/log/docker.log";
|
|
if (file_exists($docker)) {
|
|
$log = "/$diag/logs/docker";
|
|
run("todos <$docker >".escapeshellarg("$log.txt"));
|
|
if (filesize($docker)>=$max) {
|
|
run("tail -n 200 ".escapeshellarg("$log.txt")." >".escapeshellarg("$log.last200.txt"));
|
|
run("truncate -s '<$max' ".escapeshellarg("$log.txt"));
|
|
}
|
|
}
|
|
|
|
// create SMART reports (suppress errors)
|
|
run("ls -l /dev/disk/by-id/[asun]* 2>/dev/null|sed '/-part/d;s|^.*/by-id/[^-]*-||;s|-> ../../||;s|:|-|'", $devices);
|
|
foreach ($devices as $device) {
|
|
[$name,$port] = array_pad(explode(' ',$device),2,'');
|
|
$diskName = $type = '';
|
|
foreach ($disks as $find) {
|
|
if (_var($find,'device')==$port) {
|
|
$diskName = _var($find,'name');
|
|
$type = get_value($find,'smType','');
|
|
get_ctlr_options($type, $find);
|
|
$port = _var($find,'smDevice',$port);
|
|
break;
|
|
}
|
|
}
|
|
$port = port_name($port);
|
|
$status = _var($find,'status')=="DISK_OK" ? "" : " - "._var($find,'status');
|
|
run("smartctl -x $type ".escapeshellarg("/dev/$port")." 2>/dev/null|todos >".escapeshellarg("/$diag/smart/$name-$date $diskName ($port)$status.txt"));
|
|
}
|
|
|
|
// create btrfs pool information
|
|
foreach ($pools as $pool) {
|
|
if (strpos(_var($disks[$pool],'fsType'),'btrfs')!==false) {
|
|
$dev = _var($disks[$pool],'device');
|
|
run("echo 'Pool: $pool'|todos >>".escapeshellarg("/$diag/system/btrfs-usage.txt"));
|
|
run("/sbin/btrfs filesystem usage -T /mnt/$pool 2>/dev/null|todos >>".escapeshellarg("/$diag/system/btrfs-usage.txt"));
|
|
newline("/$diag/system/btrfs-usage.txt");
|
|
run("/sbin/btrfs filesystem show /dev/{$dev}p1 2>/dev/null|todos >>".escapeshellarg("/$diag/system/btrfs-usage.txt"));
|
|
newline("/$diag/system/btrfs-usage.txt");
|
|
}
|
|
}
|
|
|
|
// create zfs pool information
|
|
run("/usr/sbin/zpool status 2>/dev/null|todos >>".escapeshellarg("/$diag/system/zfs-info.txt"));
|
|
newline("/$diag/system/zfs-info.txt");
|
|
// sometimes hangs, temporary disabled
|
|
//run("/usr/sbin/zpool import 2>/dev/null|todos >>".escapeshellarg("/$diag/system/zfs-info.txt"));
|
|
|
|
// create installed plugin information
|
|
$pluginList = json_decode(download_url("https://raw.githubusercontent.com/Squidly271/AppFeed/master/pluginList.json"),true);
|
|
$installedPlugins = "";
|
|
if (!$pluginList) $installedPlugins = "Could not download current plugin versions\r\n\r\n";
|
|
$plugins = glob("/var/log/plugins/*.plg");
|
|
foreach ($plugins as $plugin) {
|
|
$plgVer = run("plugin version ".escapeshellarg($plugin));
|
|
$plgURL = run("plugin pluginURL ".escapeshellarg($plugin));
|
|
$installedPlugins .= basename($plugin)." - $plgVer";
|
|
if ($pluginList && empty($pluginList[$plgURL]) && basename($plugin) !== "unRAIDServer.plg")
|
|
$installedPlugins .= " (Unknown to Community Applications)";
|
|
if (!empty($pluginList[$plgURL]['blacklist']))
|
|
$installedPlugins .= " (Blacklisted)";
|
|
if (!empty($pluginList[$plgURL]['deprecated']) || (!empty($pluginList[$plgURL]['dmax']) && version_compare($pluginList[$plgURL]['dmax'],$unraid['version'],"<")))
|
|
$installedPlugins .= " (Deprecated)";
|
|
if (!empty($pluginList[$plgURL]['version']) && $pluginList[$plgURL]['version'] > $plgVer)
|
|
$installedPlugins .= " (Update available: {$pluginList[$plgURL]['version']})";
|
|
elseif (!empty($pluginList[$plgURL]))
|
|
$installedPlugins .= " (Up to date)";
|
|
if (!empty($pluginList[$plgURL]['max']) && version_compare($pluginList[$plgURL]['max'],$unraid['version'],"<"))
|
|
$installedPlugins .= " (Incompatible)";
|
|
if (!empty($pluginList[$plgURL]['min']) && version_compare($pluginList[$plgURL]['min'],$unraid['version'],">"))
|
|
$installedPlugins .= " (Incompatible)";
|
|
$installedPlugins .= "\r\n";
|
|
}
|
|
$installedPlugins = $installedPlugins ?: "No additional Plugins Installed";
|
|
file_put_contents("/$diag/system/plugins.txt",$installedPlugins);
|
|
|
|
// determine urls
|
|
file_put_contents("/$diag/system/urls.txt",geturls());
|
|
|
|
// copy libvirt information (if existing)
|
|
$libvirtd = "/var/log/libvirt/libvirtd.log";
|
|
if (file_exists($libvirtd)) {
|
|
$log = "/$diag/logs/libvirt";
|
|
run("todos <$libvirtd >".escapeshellarg("$log.txt"));
|
|
if (filesize($libvirtd)>=$max) {
|
|
run("tail -n 200 ".escapeshellarg("$log.txt")." >".escapeshellarg("$log.last200.txt"));
|
|
run("truncate -s '<$max' ".escapeshellarg("$log.txt"));
|
|
}
|
|
}
|
|
|
|
// copy VMs information (if existing)
|
|
$qemu = glob("/var/log/libvirt/qemu/*.log*");
|
|
if ($qemu) {
|
|
foreach ($qemu as $file) {
|
|
$log = "/$diag/qemu/".basename($file,'.log');
|
|
run("todos <".escapeshellarg($file)." >".escapeshellarg("$log.txt"));
|
|
if (filesize($file)>=$max) {
|
|
run("tail -n 200 ".escapeshellarg("$log.txt")." >".escapeshellarg("$log.last200.txt"));
|
|
run("truncate -s '<$max' ".escapeshellarg("$log.txt"));
|
|
}
|
|
}
|
|
} else {
|
|
file_put_contents("/$diag/qemu/no qemu log files","");
|
|
}
|
|
|
|
// copy VM XML config files
|
|
if (glob("/etc/libvirt/qemu/*.xml")) {
|
|
run("cp -- /etc/libvirt/qemu/*.xml ".escapeshellarg("/$diag/xml"));
|
|
}
|
|
|
|
// anonymize MAC OSK info
|
|
$all_xml = glob("/$diag/xml/*.xml");
|
|
foreach ($all_xml as $xml) {
|
|
run("sed -ri 's/(,osk=).+/\\1.../' ".escapeshellarg("$xml"));
|
|
run("sed -ri 's/(passwd=).+/\\1.../' ".escapeshellarg("$xml"));
|
|
}
|
|
|
|
// copy syslog information (anonymize if applicable)
|
|
foreach (glob("/var/log/syslog*") as $file) {
|
|
anonymize_syslog($file);
|
|
}
|
|
foreach (glob("/boot/logs/syslog-previous*") as $file) {
|
|
anonymize_syslog($file);
|
|
}
|
|
|
|
// copy dhcplog
|
|
$dhcplog = "/var/log/dhcplog";
|
|
if (file_exists($dhcplog)) {
|
|
$log = "/$diag/logs/dhcplog.txt";
|
|
run("todos <$dhcplog >".escapeshellarg($log));
|
|
maskIP($log);
|
|
}
|
|
|
|
// copy phplog
|
|
$phplog = "/var/log/phplog";
|
|
if (file_exists($phplog)) {
|
|
$log = "/$diag/logs/phplog.txt";
|
|
run("todos <$phplog >".escapeshellarg($log));
|
|
}
|
|
|
|
// copy graphql-api.log
|
|
$graphql = "/var/log/graphql-api.log";
|
|
if (file_exists($graphql)) {
|
|
$log = "/$diag/logs/graphql-api.txt";
|
|
run("todos <$graphql >".escapeshellarg($log));
|
|
}
|
|
|
|
// copy vfio-pci log
|
|
$vfiopci = "/var/log/vfio-pci";
|
|
if (file_exists($vfiopci)) {
|
|
$log = "/$diag/logs/vfio-pci.txt";
|
|
run("todos <$vfiopci >".escapeshellarg($log));
|
|
}
|
|
|
|
// copy wg-quick log
|
|
$wgquick = '/var/log/wg-quick.log';
|
|
if (file_exists($wgquick)) {
|
|
$log = "/$diag/logs/wg-quick.txt";
|
|
run("todos <$wgquick >".escapeshellarg($log));
|
|
}
|
|
|
|
// generate testparm.txt
|
|
$testparm = run("testparm -s 2>/dev/null");
|
|
if (!$all)
|
|
$testparm = preg_replace("/(?<=\[.)(.*)(?=.\])|(?<=(write list = .)|(comment = .)|(valid users = .)|(path = \/mnt\/addons\/.)|(path = \/mnt\/remotes\/.)|(path = \/mnt\/disks\/.)|(path = \/mnt\/user\/.)).*(?=.)/","...",$testparm);
|
|
file_put_contents("/$diag/system/testparm.txt",str_replace("\n","\r\n",$testparm));
|
|
maskIP("/$diag/system/testparm.txt");
|
|
|
|
// copy ntp.conf
|
|
copy("/etc/ntp.conf", "/$diag/system/ntp.txt");
|
|
maskIP("/$diag/system/ntp.txt");
|
|
newline("/$diag/system/ntp.txt");
|
|
|
|
// copy sshd_config
|
|
copy("/etc/ssh/sshd_config", "/$diag/system/sshd.txt");
|
|
maskIP("/$diag/system/sshd.txt");
|
|
newline("/$diag/system/sshd.txt");
|
|
|
|
// copy servers.conf
|
|
copy("/etc/nginx/conf.d/servers.conf", "/$diag/system/servers.conf.txt");
|
|
maskIP("/$diag/system/servers.conf.txt");
|
|
run("sed -Ei 's/[01234567890abcdef]+\.((my)?unraid\.net)/hash.\\1/gm;t' ".escapeshellarg("/$diag/system/servers.conf.txt"));
|
|
run("sed -Ei 's/\.[^\.]*\.ts\.net/\.magicdns\.ts\.net/gm' ".escapeshellarg("/$diag/system/servers.conf.txt"));
|
|
newline("/$diag/system/servers.conf.txt");
|
|
|
|
// show installed patches
|
|
@copy("/tmp/unraid.patch/installedUpdates.json","/$diag/system/installed_patches.txt");
|
|
|
|
// BEGIN - third party plugins diagnostics
|
|
// list third party packages in /boot/config/plugins/*/packages/
|
|
run("ls -lA /boot/config/plugins/*/packages/*/ 2>/dev/null|todos >>".escapeshellarg("/$diag/system/thirdparty_packages.txt"));
|
|
|
|
// list va-api compatible devices
|
|
if (is_dir("/dev/dri/")) run("ls -lA /sys/class/drm/*/device/driver 2>/dev/null|todos >>".escapeshellarg("/$diag/system/drm.txt")); else null;
|
|
|
|
// list dvb adapters
|
|
if (is_dir("/dev/dvb/")) run("ls -lA /sys/class/dvb/*/device/driver 2>/dev/null|todos >>".escapeshellarg("/$diag/system/dvb.txt")); else null;
|
|
|
|
// generate nvidia diagnostics
|
|
if (is_file("/usr/bin/nvidia-smi")) run("/usr/bin/nvidia-smi --query 2>/dev/null|todos >>".escapeshellarg("/$diag/system/nvidia-smi.txt")); else null;
|
|
|
|
// add gpu_statistics gpujson
|
|
if (is_file("/boot/config/plugins/gpustat.plg")) run("cat /tmp/gpujson 2>/dev/null|todos >>".escapeshellarg("/$diag/system/gpujson.txt")); else null;
|
|
|
|
// generate lxc diagnostics
|
|
if (is_dir("/boot/config/plugins/lxc")) {
|
|
run("mkdir -p ".escapeshellarg("/$diag/lxc"));
|
|
$lxc_path = run("cat /boot/config/plugins/lxc/lxc.conf 2>/dev/null| cut -d '=' -f2");
|
|
run("tail -n +1 $lxc_path/*/config 2>/dev/null|todos >>".escapeshellarg("/$diag/lxc/container_configurations.txt"));
|
|
run("cat /boot/config/plugins/lxc/plugin.cfg 2>/dev/null|todos >>".escapeshellarg("/$diag/lxc/plugin.cfg"));
|
|
run("cat /boot/config/plugins/lxc/lxc.conf 2>/dev/null|todos >>".escapeshellarg("/$diag/lxc/lxc.conf"));
|
|
run("cat /boot/config/plugins/lxc/default.conf 2>/dev/null|todos >>".escapeshellarg("/$diag/lxc/default.conf"));
|
|
run("lxc-checkconfig 2>/dev/null|todos >>".escapeshellarg("/$diag/lxc/checkconfig.txt"));
|
|
// remove username and token
|
|
run("sed -i -e '/LXC_GITHUB_USER/c ***line removed***' -e '/LXC_GITHUB_TOKEN/c ***line removed***' ".escapeshellarg("/$diag/lxc/plugin.cfg"));
|
|
} else {
|
|
null;
|
|
}
|
|
|
|
// generate iscsi target diagnostics
|
|
if (is_file("/boot/config/plugins/iSCSIgui.plg")) {
|
|
run("mkdir -p ".escapeshellarg("/$diag/iscsi"));
|
|
run("targetcli ls 2>/dev/null|todos >>".escapeshellarg("/$diag/iscsi/iscsi-target.txt"));
|
|
} else {
|
|
null;
|
|
}
|
|
|
|
// generate iscsi initiator diagnostics
|
|
if (is_file("/boot/config/plugins/iscsi-initiator.plg")) {
|
|
run("mkdir -p ".escapeshellarg("/$diag/iscsi"));
|
|
run("cat /boot/config/plugins/iscsi-initiator/initiatorname.cfg 2>/dev/null|todos >>".escapeshellarg("/$diag/iscsi/initiatorname.cfg"));
|
|
run("cat /boot/config/plugins/iscsi-initiator/iscsid.conf 2>/dev/null|todos >>".escapeshellarg("/$diag/iscsi/iscsid.conf"));
|
|
run("cat /boot/config/plugins/iscsi-initiator/targets.cfg 2>/dev/null|todos >>".escapeshellarg("/$diag/iscsi/targets.cfg"));
|
|
} else {
|
|
null;
|
|
}
|
|
// END - third party plugins diagnostics
|
|
|
|
// create resulting zip file and remove temp folder
|
|
run("zip -qmr ".escapeshellarg($zip)." ".escapeshellarg("/$diag"));
|
|
if ($cli) {
|
|
echo "done.\nZIP file '$zip' created.\n";
|
|
} else {
|
|
copy($zip,"/boot/logs/".basename($zip));
|
|
}
|
|
|
|
// signal we are DONE
|
|
write('_DONE_','');
|
|
?>
|