7{print $1,$2,$4,$6,$9,$10}' ".escapeshellarg($smart)." 2>/dev/null", $codes); foreach ($codes as $code) { if (!$code || !is_numeric($code[0])) continue; list($id,$class,$value,$thres,$when,$raw) = explode(' ',$code); $fail = strpos($when,'FAILING_NOW')!==false; if (!$fail && !in_array($id,$events)) continue; if ($fail || ($select ? $thres>0 && $value<=$thres*$level : $raw>0)) $title .= normalize($class,$fail?$when:$raw); } if ($title) $thumb = 'alert'; else $title = "No errors reported\n"; } } $title .= "Click for context menu"; my_insert($source, ""); } function my_usage(&$source,$used) { my_insert($source, $used ? "
$used
" : "-"); } function my_temp($value,$unit) { return ($unit=='F' ? round(9/5*$value+32) : $value)." $unit"; } function my_clock($time) { if (!$time) return 'less than a minute'; $days = floor($time/1440); $hour = $time/60%24; $mins = $time%60; return plus($days,'day',($hour|$mins)==0).plus($hour,'hour',$mins==0).plus($mins,'minute',true); } function plus($val,$word,$last) { return $val>0?(($val||$last)?($val.' '.$word.($val!=1?'s':'').($last ?'':', ')):''):''; } function active_disks($disk) { return substr($disk['status'],0,7)!='DISK_NP' && preg_match('/^(Parity|Data|Cache)$/',$disk['type']); } $path = '/webGui/images'; $failed = ['FAILED','NOK']; switch ($_POST['cmd']) { case 'disk': $i = 1; $var = []; $disks = array_filter(parse_ini_file('state/disks.ini',true),'active_disks'); $devs = parse_ini_file('state/devs.ini',true); require_once "$docroot/webGui/include/CustomMerge.php"; require_once "$docroot/webGui/include/Preselect.php"; $slots = $_POST['slots']; $row1 = array_fill(0,31,''); my_insert($row1[0],'Encrypted'); $row2 = array_fill(0,31,''); my_insert($row2[0],'Active'); $row3 = array_fill(0,31,''); my_insert($row3[0],'Inactive'); $row4 = array_fill(0,31,''); my_insert($row4[0],'Unassigned'); $row5 = array_fill(0,31,''); my_insert($row5[0],'Faulty'); $row6 = array_fill(0,31,''); my_insert($row6[0],'Heat alarm'); $row7 = array_fill(0,31,''); my_insert($row7[0],'SMART status'); $row8 = array_fill(0,31,''); my_insert($row8[0],'Utilization'); $diskRow = function($n,$disk) use (&$row1,&$row2,&$row3,&$row4,&$row5,&$row6,&$row7,&$row8,$path) { if ($n>0) { if (isset($disk['luksState'])) { switch ($disk['luksState']) { case 0: $luks = ""; break; case 1: $luks = ""; break; case 2: $luks = ""; break; case 3: $luks = ""; break; default: $luks = ""; break; } } else $luks = ""; my_insert($row1[$n],$luks); $state = $disk['color']; switch ($state) { case 'grey-off': break; //ignore case 'green-on': my_insert($row2[$n],""); break; case 'green-blink': my_insert($row3[$n],""); break; case 'blue-on': case 'blue-blink': my_insert($row4[$n],""); break; default: my_insert($row5[$n],""); break;} $temp = $disk['temp']; $hot = $disk['hotTemp'] ?? $_POST['hot']; $max = $disk['maxTemp'] ?? $_POST['max']; $top = $_POST['top'] ?? 120; $heat = exceed($temp,$max,$top) ? 'max' : (exceed($temp,$hot,$top) ? 'hot' : ''); if ($heat) my_insert($row6[$n],""); else if (!strpos($state,'blink') && $temp>0) my_insert($row6[$n],"".my_temp($temp,$_POST['unit']).""); if ($disk['device'] && !strpos($state,'blink')) my_smart($row7[$n],$disk['name'],'Device'); my_usage($row8[$n],($disk['type']!='Parity' && $disk['fsStatus']=='Mounted')?(($disk['fsSize'] ? round((1-$disk['fsFree']/$disk['fsSize'])*100):0).'%'):''); } }; $devRow = function($n,$disk) use (&$row4,&$row6,&$row7,$path) { $hot = $_POST['hot']; $max = $_POST['max']; $top = $_POST['top'] ?? 120; $name = $dev['device']; $port = substr($name,-2)!='n1' ? $name : substr($name,0,-2); $smart = "state/smart/$name"; $state = exec("hdparm -C ".escapeshellarg("/dev/$port")."|grep -Po 'active|unknown'") ? 'blue-on' : 'blue-blink'; if ($state=='blue-on') my_smart($row7[$n],$name,'New'); $temp = file_exists($smart) ? exec("awk 'BEGIN{t=\"*\"} \$1==190||\$1==194{t=\$10;exit};\$1==\"Temperature:\"{t=\$2;exit} END{print t}' ".escapeshellarg($smart)) : '*'; $heat = exceed($temp,$max,$top) ? 'max' : (exceed($temp,$hot,$top) ? 'hot' : ''); if ($heat) my_insert($row6[$n],""); else if ($state=='blue-on' && $temp>0) my_insert($row6[$n],"".my_temp($temp,$_POST['unit']).""); my_insert($row4[$n],""); }; foreach ($disks as $disk) if ($disk['type']=='Parity') $diskRow($i++,$disk); foreach ($disks as $disk) if ($disk['type']=='Data') $diskRow($i++,$disk); if ($slots <= 30) { foreach ($disks as $disk) if ($disk['type']=='Cache') $diskRow($i++,$disk); foreach ($devs as $dev) $devRow($i++,$dev); } echo "".implode('',$row1).""; echo "".implode('',$row2).""; echo "".implode('',$row3).""; echo "".implode('',$row4).""; echo "".implode('',$row5).""; echo "".implode('',$row6).""; echo "".implode('',$row7).""; echo "".implode('',$row8).""; if ($slots > 30) { echo '#'; $i = 1; $row1 = array_fill(0,31,''); my_insert($row1[0],'Encrypted'); $row2 = array_fill(0,31,''); my_insert($row2[0],'Active'); $row3 = array_fill(0,31,''); my_insert($row3[0],'Inactive'); $row4 = array_fill(0,31,''); my_insert($row4[0],'Unassigned'); $row5 = array_fill(0,31,''); my_insert($row5[0],'Faulty'); $row6 = array_fill(0,31,''); my_insert($row6[0],'Heat alarm'); $row7 = array_fill(0,31,''); my_insert($row7[0],'SMART status'); $row8 = array_fill(0,31,''); my_insert($row8[0],'Utilization'); foreach ($disks as $disk) if ($disk['type']=='Cache') $diskRow($i++,$disk); foreach ($devs as $dev) $devRow($i++,$dev); echo "".implode('',$row1).""; echo "".implode('',$row2).""; echo "".implode('',$row3).""; echo "".implode('',$row4).""; echo "".implode('',$row5).""; echo "".implode('',$row6).""; echo "".implode('',$row7).""; echo "".implode('',$row8).""; } break; case 'sys': exec("grep -Po '^Mem(Total|Available):\s+\K\d+' /proc/meminfo",$memory); exec("df /boot /var/log /var/lib/docker|grep -Po '\d+%'",$sys); $mem = max(round((1-$memory[1]/$memory[0])*100),0); echo "{$mem}%#".implode('#',$sys); break; case 'fan': exec("sensors -uA 2>/dev/null|grep -Po 'fan\d_input: \K\d+'",$rpms); if ($rpms) echo implode(' RPM#',$rpms).' RPM'; break; case 'port': switch ($_POST['view']) { case 'main': $ports = explode(',',$_POST['ports']); $i = 0; foreach ($ports as $port) { $mtu = file_get_contents("/sys/class/net/$port/mtu"); if (substr($port,0,4)=='bond') { $ports[$i++] = exec("grep -Pom1 '^Bonding Mode: \K.+' ".escapeshellarg("/proc/net/bonding/$port")).", mtu $mtu"; } elseif ($port=='lo') { $ports[$i++] = str_replace('yes','loopback',exec("ethtool lo|grep -Pom1 '^\s+Link detected: \K.+'")); } else { unset($info); exec("ethtool ".escapeshellarg($port)."|grep -Po '^\s+(Speed|Duplex|Link\sdetected): \K[^U\\n]+'",$info); $ports[$i++] = (array_pop($info)=='yes' && $info[0]) ? str_replace(['M','G'],[' M',' G'],$info[0]).", ".strtolower($info[1])." duplex, mtu $mtu" : "not connected"; } } break; case 'port': exec("ifconfig -a -s|awk '/^(bond|eth|lo)[0-9]*\s/{print $3\"#\"$7}'",$ports); break; case 'link': exec("ifconfig -a -s|awk '/^(bond|eth|lo)[0-9]*\s/{print \"Errors: \"$4\"
Drops: \"$5\"
Overruns: \"$6\"#Errors: \"$8\"
Drops: \"$9\"
Overruns: \"$10}'",$ports); break; default: $ports = [];} echo implode('#',$ports); break; case 'parity': $var = parse_ini_file("state/var.ini"); $mode = ''; if (strstr($var['mdResyncAction'],"recon")) { $mode = 'Parity-Sync / Data-Rebuild'; } elseif (strstr($var['mdResyncAction'],"clear")) { $mode = 'Clearing'; } elseif ($var['mdResyncAction']=="check") { $mode = 'Read-Check'; } elseif (strstr($var['mdResyncAction'],"check")) { $mode = 'Parity-Check'; } echo "".$mode." in progress... Completed: ".number_format(($var['mdResyncPos']/($var['mdResync']/100+1)),0)." %."; echo "
Elapsed time: ".my_clock(floor((time()-$var['sbUpdated'])/60)).". Estimated finish: ".my_clock(round(((($var['mdResyncDt']*(($var['mdResync']-$var['mdResyncPos'])/($var['mdResyncDb']/100+1)))/100)/60),0)).""; break; case 'shares': $names = explode(',',$_POST['names']); switch ($_POST['com']) { case 'smb': exec("lsof /mnt/user /mnt/disk* 2>/dev/null|awk '/^smbd/ && $0!~/\.AppleD(B|ouble)/ && $5==\"REG\"'|awk -F/ '{print $4}'",$lsof); $counts = array_count_values($lsof); $count = []; foreach ($names as $name) $count[] = $counts[$name] ?? 0; echo implode('#',$count); break; case 'afp': case 'nfs': // not available break;} break;}