#!/usr/bin/php -q 0 ? (($val || $last) ? ($val.' '.$word.($val!=1?'s':'').($last ?'':', ')) : '') : ''; } function my_temp($value) { global $display; if ($value=='*') return ' - standby'; $unit = _var($display,'unit','C'); return ' - active '.($unit=='F' ? fahrenheit($value) : str_replace('.',_var($display,'number','.,')[0], $value)).' '.$unit; } function my_disk($name) { return ucfirst(preg_replace('/(\d+)$/',' $1',$name)); } function my_scale($value, &$unit, $precision = NULL) { global $display; $scale = _var($display,'scale',-1); $number = _var($display,'number','.,'); $units = ['B','KB','MB','GB','TB','PB']; if ($scale==0 && $precision===NULL) { $unit = ''; return number_format($value, 0, $number[0], ($value>=10000 ? $number[1] : '')); } else { $base = $value ? floor(log($value, 1000)) : 0; if ($scale>0 && $base>$scale) $base = $scale; $value = round($value/pow(1000, $base), $precision===NULL ? 2 : $precision); if ($value>=1000 && $scale<0) { $value = 1; $base++; } $unit = $units[$base]; return number_format($value, $precision===NULL ? (($value-intval($value)==0 || $value>=100) ? 0 : ($value>=10 ? 1 : 2)) : $precision, $number[0], ($value>=10000 ? $number[1] : '')); } } function my_check($time,$speed) { if (!$time) return 'unavailable (no parity-check entries logged)'; $days = floor($time/86400); $hmss = $time-$days*86400; $hour = floor($hmss/3600); $mins = floor($hmss/60)%60; $secs = $hmss%60; return plus($days,'day',($hour|$mins|$secs)==0).plus($hour,'hour',($mins|$secs)==0).plus($mins,'minute',$secs==0).plus($secs,'second',true).". Average speed: $speed"; } function my_time($time) { global $display; $date = my_date(_var($display,'date').(_var($display,'date')!='%c' ? ", "._var($display,'time') : ""), $time); $now = new DateTime("@".intval(time()/86400)*86400); $last = new DateTime("@".intval($time/86400)*86400); $days = date_diff($last,$now)->format('%a'); switch (true) { case ($days<0): return $date; case ($days==0): return "$date (today)"; case ($days==1): return "$date (yesterday)"; default: return "$date ($days days ago)"; } } function my_clock($time) { if (!$time) return 'less than a minute'; $days = floor($time/1440); $hour = floor($time/60)%24; $mins = $time%60; return plus($days,'day',($hour|$mins)==0).plus($hour,'hour',$mins==0).plus($mins,'minute',true); } function my_array(&$disk) { global $data,$display,$error0,$error1,$error2,$error3; $name = _var($disk,'name'); [$hotNVME,$maxNVME] = _var($disk,'transport')=='nvme' ? get_nvme_info(_var($disk,'device'),'temp') : [-1,-1]; $hot = _var($disk,'hotTemp',-1)>=0 ? $disk['hotTemp'] : ($hotNVME>=0 ? $hotNVME : (_var($disk,'rotational',1)==0 && $display['hotssd']>=0 ? $display['hotssd'] : $display['hot'])); $max = _var($disk,'maxTemp',-1)>=0 ? $disk['maxTemp'] : ($maxNVME>=0 ? $maxNVME : (_var($disk,'rotational',1)==0 && $display['maxssd']>=0 ? $display['maxssd'] : $display['max'])); if (strpos(_var($disk,'status'),'_NP')!==false) return false; $temp = _var($disk,'temp'); if ($max>0 && $temp>=$max) { $fail = ' (disk is overheated'; $error0++; } elseif ($hot>0 && $temp>=$hot) { $fail = ' (disk is hot'; $error1++; } else { $fail = ''; } if (_var($disk,'numErrors',0)>0) { if ($fail) $fail .= ', '; else $fail = ' ('; $fail .= 'disk has read errors'; $error2++; } if ($fail) $fail .= ')'; $status = $fail ? ' [NOK]' : ' [OK]'; $color = strtok(_var($disk,'color'),'-'); if ($color=='red'||$color=='yellow') {$error3++; $status = ' ['.str_replace(['NP_','_'],['',' '],_var($disk,'status')).']';} $info = _var($disk,'id')." ("._var($disk,'device').")"; if ($info==" ()") $info = 'No device identification present'; $data[] = my_disk($name)." - $info".my_temp($temp).$fail.$status; return true; } // generate report of array devices foreach ($disks as $disk) if (_var($disk,'type')=='Parity') $parity |= my_array($disk); foreach ($disks as $disk) if (_var($disk,'type')=='Data') my_array($disk); foreach ($disks as $disk) if (_var($disk,'type')=='Cache') $pools |= my_array($disk); $size = count($data); // generate parity report $data[] = ''; $mdResync = _var($var,'mdResync',0); $action = preg_split('/\s+/',_var($var,'mdResyncAction')); if ($mdResync>0) { $mdResyncPos = _var($var,'mdResyncPos',0); $mdResyncDb = _var($var,'mdResyncDb',0); $mdResyncDt = _var($var,'mdResyncDt',0); switch ($action[0]) { case "recon": $mode = $action[1]=='P' ? 'Parity-Sync' : 'Data-Rebuild'; break; case "check": $mode = count($action)>1 ? 'Parity-Check' : 'Read-Check'; break; case "clear": $mode = 'Disk-Clear'; break; default : $mode = 'Unknown'; break; } $data[] = $mode." in progress."; $data[] = "Total size: ".my_scale($mdResync*1024, $unit)." $unit"; $data[] = "Elapsed time: ".my_clock(floor((time()-_var($var,'sbUpdated',0))/60)); $data[] = "Current position: ".my_scale($mdResyncPos*1024, $unit)." $unit (".number_format(($mdResyncPos/($mdResync/100+1)),1,$unraid['display']['number'][0],'')." %)"; $data[] = "Estimated speed: ".my_scale($mdResyncDb/$mdResyncDt*1024, $unit, 1)." $unit/sec"; $data[] = "Estimated finish: ".my_clock(round(((($mdResyncDt*(($mdResync-$mdResyncPos)/($mdResyncDb/100+1)))/100)/60),0)); $data[] = "Sync errors ".(_var($var,'mdResyncCorr',0)==0 ? 'detected: ' : 'corrected: ')._var($var,'sbSyncErrs',0); } else { $sbSynced = _var($var,'sbSynced',0); $sbSynced2 = _var($var,'sbSynced2',0); $sbSyncErrs = _var($var,'sbSyncErrs',0); if (_var($var,'sbSyncExit',0)!=0) { $data[] = "Last check incomplete on ".my_time($sbSynced2).", finding $sbSyncErrs error".($sbSyncErrs==1?'.':'s.'); $data[] = "Error code: ".$var['sbSyncExit']; } elseif ($sbSynced==0) { $data[] = "Parity has not been checked yet"; } elseif ($sbSynced2>0) { if ($action[0]=='recon') { $data[] = $action[1]=='P' ? 'Parity is invalid' : 'Data-Rebuild is invalid'; } else { $data[] = 'Parity is valid'; } $duration = Max($sbSynced2-$sbSynced,1); $speed = my_scale(_var($var,'mdResyncSize',0)*1024/$duration,$unit,1)." $unit/s"; $data[] = "Last checked on ".my_time($sbSynced2).", finding $sbSyncErrs error".($sbSyncErrs==1?'.':'s.'); $data[] = "Duration: ".my_check($duration,$speed); } } $word = $size==1 ? "" : "including "; $warn = ($error0 || $error3) ? "alert" : (($error1 || $error2) ? "warning" : "normal"); $stat = $warn=="normal" ? "[PASS]" : "[FAIL]"; $info = "Array has $size disk".($size==1 ? "" : "s").($parity ? " ({$word}parity".($pools ? " & pools)" : ")") : ($pools ? " ({$word}pools)" : "")); $message = implode('\n', $data); $subject = "Notice [$server] - array health report $stat"; exec("$script -s ".escapeshellarg($subject)." -d ".escapeshellarg("$info")." -m ".escapeshellarg("$message")." -i ".escapeshellarg("$warn $output")." -l '/Main'"); exit(0); ?>