#!/usr/bin/env awk -f function log10(n) { return log(n)/log(10.0) } function merge_meas(val_est, unc_est, val_meas, unc_meas) { # Kalman filtering compares variances, # convert uncerainties to square units unc_est = (0.5*unc_est)^2.0 unc_meas = (0.5*unc_meas)^2.0 G_K = (unc_est)/((unc_est) + (unc_meas)) val_est = val_est + G_K*(val_meas - val_est) unc_est = (unc_est*unc_meas)/(unc_est + unc_meas) # convert unc_est back to original units unc_est = 2.0*sqrt(unc_est) return sprintf(OFMT OFS OFMT ORS, val_est, unc_est) } function sigfig(val, unc) { ordmag_val = log10(val) ordmag_unc = log10(unc) #sigfig_unc = sprintf("%.f", 6) sigfig_unc = sprintf("%.f", sqrt((ordmag_val - ordmag_unc)^2.0) + 1.0) sigfig_val = sprintf("%.f", (ordmag_val - ordmag_unc + sigfig_unc)) ofmt_val = "%." sigfig_val "g" ofmt_unc = "%." sigfig_unc "g" return sprintf(ofmt_val OFS ofmt_unc ORS, val, unc) } # function ck_boottime() { # # "sysctl kern.boottime" | getline t_kboot # close("sysctl kern.boottime") # sub("^.*\{", "", t_kboot) # sub("\}.*$", "", t_kboot) # split(t_kboot, t_kboot_arr, ",") # # for (i in t_kboot_arr) { # sub("^.*= ", "", t_kboot_arr[i]) # } # # t_kboot = sprintf(t_kboot_arr[1] "." t_kboot_arr[2]) # return t_kboot # # } function ck_uptime(t0_est, t0_unc) { t_sys_meas[1] = systime() t_sys_meas[2] = 1.0 "uptime" | getline t_up_cmd close("uptime") split(merge_meas(t_sys_meas[1], t_sys_meas[2], systime(), 1.0), t_sys_meas) # estimate (predict) uptime t_up_est[1] = t_sys_meas[1] - t0_est t_up_est[2] = t_sys_meas[2] + t0_unc # evaluate measured uptime t_up_meas[1] = 0.0 t_up_meas[2] = systime() sub("^.*up ", "", t_up_cmd) sub(", load.*$", "", t_up_cmd) split(t_up_cmd, t_up_cmd_arr, ",") for (i in t_up_cmd_arr) { # TODO: add cases for days, months, years, etc. if (t_up_cmd_arr[i] ~ /day/) { split(t_up_cmd_arr[i], days) t_up_meas[1] += 86400.0*(days[1] + 0.0) (t_up_meas[2] > 86400.0) ? t_up_meas[2] = 86400.0 : t_up_meas[2] += 0.0 } if (t_up_cmd_arr[i] ~ /hr/) { split(t_up_cmd_arr[i], hrs) t_up_meas[1] += 3600.0*(hrs[1] + 0.0) (t_up_meas[2] > 3600.0) ? t_up_meas[2] = 3600.0 : t_up_meas[2] += 0.0 } if (t_up_cmd_arr[i] ~ /min/) { split(t_up_cmd_arr[i], mins) t_up_meas[1] += (60.0*(mins[1] + 0.0)) (t_up_meas[2] > 60.0) ? t_up_meas[2] = 60.0 : t_up_meas[2] += 0.0 } if (t_up_cmd_arr[i] ~ /:/) { split(t_up_cmd_arr[i], hrs_min, ":") t_up_meas[1] += 3600.0*(hrs_min[1] + 0.0) (t_up_meas[2] > 3600.0) ? t_up_meas[2] = 3600.0 : t_up_meas[2] += 0.0 t_up_meas[1] += 60.0*(hrs_min[2] + 0.0) (t_up_meas[2] > 60.0) ? t_up_meas[2] = 60.0 : t_up_meas[2] += 0.0 } } # merge predicted and measured uptimes split(merge_meas(t_up_est[1], t_up_est[2], t_up_meas[1], t_up_meas[2]), t_up_est) # evaluate measured boot time, t0 t_boot_meas[1] = t_sys_meas[1] - t_up_meas[1] t_boot_meas[2] = t_sys_meas[2] + t_up_meas[2] # merge previous and updated boot time, t0 split(merge_meas(t0_est, t0_unc, t_boot_meas[1], t_boot_meas[2]), t_boot_est) return sigfig(t_boot_est[1], t_boot_est[2]) } BEGIN { OFMT="%.21g" pi = 4.0*atan2(1.0, 1.0) c0 = 299792458 # m/sec #print("_systime_", systime()) #print("_boottime_", ck_boottime()) # check ARGV for previous estimate if (ARGC > 0) { ARGV[1] ? t0_est[1] = ARGV[1] : t0_est[1] = 0.0 ARGV[2] ? t0_est[2] = ARGV[2] : t0_est[2] = systime() } #print("t0_est = ", t0_est[1]) #print("t_boot_unc = ", t0_est[2]) # wait (sleep) based on uncertainty # print(60.0/t0_est[2]) # check uptime, update estimate print(ck_uptime(t0_est[1], t0_est[2])) }