mirror of
https://github.com/unraid/webgui.git
synced 2026-01-14 21:50:24 -06:00
Don't anonymize system share names (such as appdata,domains,isos,system), this will make it easier to find the right file when troubleshooting system shares.
231 lines
12 KiB
PHP
Executable File
231 lines
12 KiB
PHP
Executable File
#!/usr/bin/php -q
|
|
<?PHP
|
|
/* Copyright 2005-2017, Lime Technology
|
|
* Copyright 2012-2017, 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.
|
|
*/
|
|
?>
|
|
<?
|
|
$opt = getopt('a',['all']);
|
|
$all = isset($opt['a']) || isset($opt['all']);
|
|
$zip = $all ? $argv[2] : $argv[1];
|
|
$cli = empty($zip);
|
|
$get = "/var/local/emhttp";
|
|
$var = file_exists("$get/var.ini") ? parse_ini_file("$get/var.ini") : [];
|
|
|
|
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
|
|
$folders = ['/boot','/boot/config','/boot/config/plugins','/boot/extra','/boot/syslinux','/var/log','/var/log/plugins','/var/log/packages','/tmp'];
|
|
|
|
function anonymize($text,$select) {
|
|
global $all;
|
|
if ($all) return $text;
|
|
switch ($select) {
|
|
case 1:
|
|
$rows = explode("\n", $text);
|
|
foreach ($rows as &$row) {
|
|
if (!preg_match("/\b(disk|cache|parity|flash)\d*\b/", $row)) {
|
|
$row = preg_replace("/^(\s*\[\S).*(\S\])( => Array)$/","$1..$2$3",$row);
|
|
$row = preg_replace("/^(\s*\[(name|nameOrig|comment|flashGUID|regGUID|regTo|readList|writeList|csrf_token)\] => \S).*(\S)$/","$1..$3",$row);
|
|
}
|
|
}
|
|
return implode("\n", $rows);
|
|
case 2:
|
|
$name = basename($text,'.cfg');
|
|
$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";
|
|
}
|
|
}
|
|
|
|
if ($cli) {
|
|
// script is called from CLI
|
|
echo "Starting diagnostics collection... ";
|
|
exec("mkdir -p /boot/logs");
|
|
$server = isset($var['NAME']) ? str_replace(' ','_',strtolower($var['NAME'])) : 'tower';
|
|
$date = date('Ymd-Hi');
|
|
$diag = "$server-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]}";
|
|
}
|
|
// create folder structure
|
|
exec("mkdir -p ".escapeshellarg("/$diag/system")." ".escapeshellarg("/$diag/config")." ".escapeshellarg("/$diag/logs")." ".escapeshellarg("/$diag/shares")." ".escapeshellarg("/$diag/smart")." ".escapeshellarg("/$diag/qemu"));
|
|
// get utilization of running processes
|
|
exec("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']);
|
|
// copy ini variables
|
|
foreach (glob("$get/*.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);
|
|
}
|
|
// individual commands execution (suppress errors)
|
|
exec("lscpu 2>/dev/null|todos >".escapeshellarg("/$diag/system/lscpu.txt"));
|
|
exec("lsscsi -vgl 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsscsi.txt"));
|
|
exec("lspci -knn 2>/dev/null|todos >".escapeshellarg("/$diag/system/lspci.txt"));
|
|
exec("lsusb 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsusb.txt"));
|
|
exec("free -mth 2>/dev/null|todos >".escapeshellarg("/$diag/system/memory.txt"));
|
|
exec("ps -auxf --sort=-pcpu 2>/dev/null|todos >".escapeshellarg("/$diag/system/ps.txt"));
|
|
exec("lsof -Pni 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsof.txt"));
|
|
exec("lsmod|sort 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsmod.txt"));
|
|
exec("df -h 2>/dev/null|todos >".escapeshellarg("/$diag/system/df.txt"));
|
|
exec("ifconfig -a -s 2>/dev/null|grep -Po '^(eth|bond)[0-9]+'", $ports);
|
|
exec("dmidecode -qt2|awk -F: '/^\tManufacturer:/{m=\$2};/^\tProduct Name:/{p=\$2} END{print m\" -\"p}' 2>/dev/null|todos >".escapeshellarg("/$diag/system/motherboard.txt"));
|
|
exec("dmidecode -qt0 2>/dev/null|todos >>".escapeshellarg("/$diag/system/motherboard.txt"));
|
|
// create ethernet information information (suppress errors)
|
|
foreach ($ports as $port) {
|
|
exec("ethtool ".escapeshellarg($port)." 2>/dev/null|todos >>".escapeshellarg("/$diag/system/ethtool.txt"));
|
|
file_put_contents("/$diag/system/ethtool.txt", "\r\n", FILE_APPEND);
|
|
exec("ethtool -i ".escapeshellarg($port)." 2>/dev/null|todos >>".escapeshellarg("/$diag/system/ethtool.txt"));
|
|
file_put_contents("/$diag/system/ethtool.txt", "--------------------------------\r\n", FILE_APPEND);
|
|
}
|
|
exec("ifconfig -a 2>/dev/null|todos >".escapeshellarg("/$diag/system/ifconfig.txt"));
|
|
// create system information (suppress errors)
|
|
exec("find /sys/kernel/iommu_groups/ -type l 2>/dev/null|todos >".escapeshellarg("/$diag/system/iommu_groups.txt"));
|
|
exec("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)) exec("echo -ne ".escapeshellarg("\r\n$folder\r\n")." >>".escapeshellarg($dest).";ls -l ".escapeshellarg($folder)."|todos >>".escapeshellarg("$dest")); else exec("echo -ne ".escapeshellarg("\r\n$folder\r\nfolder does not exist\r\n")." >>".escapeshellarg("$dest"));
|
|
}
|
|
// copy configuration files (suppress errors)
|
|
exec("cp /boot/config/*.{cfg,conf,dat} /boot/config/go ".escapeshellarg("/$diag/config")." 2>/dev/null");
|
|
// anonymize configuration files
|
|
if (!$all) exec("sed -ri 's/^((disk|flash)(Read|Write)List.*=\")[^\"]+/\\1.../' ".escapeshellarg("/$diag/config/*.cfg")." 2>/dev/null");
|
|
|
|
// don't anonymize system share names
|
|
$vardomain = file_exists('/boot/config/domain.cfg') ? parse_ini_file('/boot/config/domain.cfg') : [];
|
|
$vardocker = file_exists('/boot/config/docker.cfg') ? parse_ini_file('/boot/config/docker.cfg') : [];
|
|
$showshares = [];
|
|
$showshares[] = current(array_slice(explode('/',$vardomain['IMAGE_FILE']), 3, 1)).'.cfg';
|
|
$showshares[] = current(array_slice(explode('/',$vardomain['DOMAINDIR']), 3, 1)).'.cfg';
|
|
$showshares[] = current(array_slice(explode('/',$vardomain['MEDIADIR']), 3, 1)).'.cfg';
|
|
$showshares[] = current(array_slice(explode('/',$vardomain['DISKDIR']), 3, 1)).'.cfg';
|
|
$showshares[] = current(array_slice(explode('/',$vardocker['DOCKER_IMAGE_FILE']), 3, 1)).'.cfg';
|
|
$showshares[] = current(array_slice(explode('/',$vardocker['DOCKER_APP_CONFIG_PATH']), 3, 1)).'.cfg';
|
|
$showshares[] = current(array_slice(explode('/',$vardocker['DOCKER_HOME']), 3, 1)).'.cfg';
|
|
|
|
// copy share information (anonymize if applicable)
|
|
$files = glob("/boot/config/shares/*.cfg");
|
|
foreach ($files as $file) {
|
|
if (in_array(basename($file),$showshares)) {
|
|
$dest = "/$diag/shares/".basename($file);
|
|
} else {
|
|
$dest = anonymize("/$diag/shares/".basename($file),2);
|
|
}
|
|
@copy($file, $dest);
|
|
if (!$all) exec("sed -ri 's/^(share(Comment|ReadList|WriteList)=\")[^\"]+/\\1.../' ".escapeshellarg($dest)." 2>/dev/null");
|
|
}
|
|
// create default user shares information
|
|
$shares = file_exists("$get/shares.ini") ? parse_ini_file("$get/shares.ini", true) : [];
|
|
foreach ($shares as $share) {
|
|
$name = $share['name'];
|
|
if (!in_array("/boot/config/shares/$name.cfg",$files)) file_put_contents(anonymize("/$diag/shares/$name.cfg",2),"# This share has default settings.\r\n");
|
|
}
|
|
// copy syslog information (anonymize if applicable)
|
|
$max = 2*1024*1024; //=2MB
|
|
foreach (glob("/var/log/syslog*") as $file) {
|
|
$log = "/$diag/logs/".basename($file);
|
|
exec("todos <".escapeshellarg($file)." >".escapeshellarg("$log.txt"));
|
|
if (!$all) {
|
|
unset($titles,$rows);
|
|
exec("grep -Po 'logger: moving \"\K[^\"]+' ".escapeshellarg("$log.txt")." 2>/dev/null|sort|uniq", $titles);
|
|
exec("sed -ri 's|\b\S+@\S+\.\S+\b|xxx@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"));
|
|
exec("sed -ri 's|(host: \").+(\.unraid\.net:[0-9]+\")|\\1hash\\2|;s|(referrer: \"https?://).+(\.unraid\.net)|\\1hash\\2|' ".escapeshellarg("$log.txt"));
|
|
foreach ($titles as $mover) {
|
|
$title = "/{$mover[0]}..".substr($mover,-1)."/...";
|
|
exec("sed -ri 's|(logger: [.>cr].*)[ /]$mover/.*$|\\1 file: $title|' ".escapeshellarg("$log.txt")." 2>/dev/null");
|
|
}
|
|
exec("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++) exec("sed -ri '$row s|(cache_dirs: \S).*(\S)|\\1..\\2|' ".escapeshellarg("$log.txt")." 2>/dev/null");
|
|
}
|
|
if (basename($file)=='syslog' && filesize($file)>=$max) exec("tail -n 200 ".escapeshellarg("$log.txt")." >".escapeshellarg("$log.last200.txt"));
|
|
exec("truncate -s '<$max' ".escapeshellarg("$log.txt"));
|
|
}
|
|
// copy docker information (if existing)
|
|
$max = 1*1024*1024; //=1MB
|
|
$docker = "/var/log/docker.log";
|
|
if (file_exists($docker)) {
|
|
$log = "/$diag/logs/docker";
|
|
exec("todos <$docker >".escapeshellarg("$log.txt"));
|
|
if (filesize($docker)>=$max) {
|
|
exec("tail -n 200 ".escapeshellarg("$log.txt")." >".escapeshellarg("$log.last200.txt"));
|
|
exec("truncate -s '<$max' ".escapeshellarg("$log.txt"));
|
|
}
|
|
}
|
|
// copy libvirt information (if existing)
|
|
$libvirtd = "/var/log/libvirt/libvirtd.log";
|
|
if (file_exists($libvirtd)) {
|
|
$log = "/$diag/logs/libvirt";
|
|
exec("todos <$libvirtd >".escapeshellarg("$log.txt"));
|
|
if (filesize($libvirtd)>=$max) {
|
|
exec("tail -n 200 ".escapeshellarg("$log.txt")." >".escapeshellarg("$log.last200.txt"));
|
|
exec("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');
|
|
exec("todos <".escapeshellarg($file)." >".escapeshellarg("$log.txt"));
|
|
if (filesize($file)>=$max) {
|
|
exec("tail -n 200 ".escapeshellarg("$log.txt")." >".escapeshellarg("$log.last200.txt"));
|
|
exec("truncate -s '<$max' ".escapeshellarg("$log.txt"));
|
|
}
|
|
}
|
|
} else
|
|
file_put_contents("/$diag/qemu/no qemu log files","");
|
|
// create SMART reports (suppress errors)
|
|
$disks = file_exists("$get/disks.ini") ? parse_ini_file("$get/disks.ini", true) : [];
|
|
include_once "$docroot/webGui/include/CustomMerge.php";
|
|
include_once "$docroot/webGui/include/Wrappers.php";
|
|
exec("ls -l /dev/disk/by-id/[asun]* 2>/dev/null|sed '/-part/d;s|^.*/by-id/[^-]*-||;s|-> ../../||;s|:|-|'", $devices);
|
|
foreach ($devices as $device) {
|
|
list($name,$port) = explode(' ',$device);
|
|
$diskName = ''; $type = '';
|
|
foreach ($disks as $find) {
|
|
if ($find['device']==$port) {
|
|
$diskName = $find['name'];
|
|
$type = get_value($find,'smType','');
|
|
get_ctlr_options($type, $find);
|
|
$port = $find['smDevice'] ?? $port;
|
|
break;
|
|
}
|
|
}
|
|
$port = port_name($port);
|
|
exec("smartctl -x $type ".escapeshellarg("/dev/$port")." 2>/dev/null|todos >".escapeshellarg("/$diag/smart/$name-$date $diskName ($port).txt"));
|
|
}
|
|
// create cache pool information
|
|
if (is_dir('/mnt/cache') && strpos($disks['cache']['fsType'],'btrfs')!==false) {
|
|
exec("/sbin/btrfs filesystem usage /mnt/cache 2>/dev/null|todos >".escapeshellarg("/$diag/system/btrfs-usage.txt"));
|
|
}
|
|
// create installed plugin information
|
|
$plugins = glob("/var/log/plugins/*.plg");
|
|
foreach ($plugins as $plugin) {
|
|
$installedPlugins .= basename($plugin)." - ".exec("plugin version ".escapeshellarg($plugin))."\r\n";
|
|
}
|
|
$installedPlugins = $installedPlugins ?: "No additional Plugins Installed";
|
|
file_put_contents("/$diag/system/plugins.txt",$installedPlugins);
|
|
|
|
// create resulting zip file and remove temp folder
|
|
exec("zip -qmr ".escapeshellarg($zip)." ".escapeshellarg("/$diag"));
|
|
if ($cli) echo "done.\nZIP file '$zip' created.\n";
|
|
?>
|