diff --git a/.gitignore b/.gitignore index fdd7906..c452c7f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /web/css/.sass-cache .htpasswd .htaccess +/conf/esm.config.json diff --git a/autoload.php b/autoload.php index 6487133..34cbee4 100644 --- a/autoload.php +++ b/autoload.php @@ -1,8 +1,12 @@ 7) { for (i=1; icheckUpdate(); +try{ + $Config = Config::instance(); + $update = $Config->checkUpdate(); +} +catch(Exception $e) +{ + if ($e instanceof LogicException) + { + echo $e; + die("configuration invalide"); + } +} ?> @@ -57,6 +67,17 @@ ?> +get('esm:mode') == 'cron'){ ?> +
+ %d secondes", time()-$time); + ?> + +
+ +
New version available () ! Click here to download @@ -316,7 +337,7 @@
-
+

Last login

    @@ -335,9 +356,7 @@
- - -
+

Services status

    @@ -352,10 +371,26 @@
+
+
+
+

Last SSH/SFTP login

+
    +
  • +
+
+
+ get('last_sftp_login:enable') == true): ?> + + +
+ +

Disabled

+ +
+
- - -
+

Ping

    diff --git a/js/esm.js b/js/esm.js index b61eb57..fa8f8ae 100644 --- a/js/esm.js +++ b/js/esm.js @@ -201,6 +201,35 @@ esm.getLast_login = function() { } +esm.getLast_sftp_login = function() { + + var module = 'last_sftp_login'; + + esm.reloadBlock_spin(module); + + $.get('libs/'+module+'.php', function(data) { + + var $box = $('.box#esm-'+module+' .box-content tbody'); + $box.empty(); + + for (var line in data) + { + var html = ''; + html += ''; + html += ''+data[line].user+''; + html += ''+data[line].date+''; + html += ''+data[line].src+''; + html += ''; + + $box.append(html); + } + + esm.reloadBlock_spin(module); + + }, 'json'); + +} + esm.getNetwork = function() { @@ -249,7 +278,16 @@ esm.getPing = function() { var html = ''; html += ''; html += ''+data[line].host+''; - html += ''+data[line].ping+' ms'; + + html += 'OFFLINE'; + } + else { + html += 'success">'+data[line].ping+' ms'; + } + html += '' + html += ''; $box.append(html); @@ -303,9 +341,11 @@ esm.getAll = function() { esm.getSwap(); esm.getDisk(); esm.getLast_login(); + esm.getLast_sftp_login(); esm.getNetwork(); esm.getPing(); esm.getServices(); + esm.getLastCron(); } esm.reloadBlock = function(block) { @@ -355,6 +395,21 @@ esm.reconfigureGauge = function($gauge, newValue) { $gauge.val(newValue).trigger('change'); } +esm.getLastCron = function() { + + var module = 'last_cron'; + esm.reloadBlock_spin(module); + $.get('libs/'+module+'.php', function(data) { + var $box = $('#lastCron .seconds'); + + $box.text(data); + + esm.reloadBlock_spin(module); + + }, 'json'); + +} + esm.mapping = { all: esm.getAll, @@ -365,7 +420,9 @@ esm.mapping = { swap: esm.getSwap, disk: esm.getDisk, last_login: esm.getLast_login, + last_sftp_login: esm.getLast_sftp_login, network: esm.getNetwork, ping: esm.getPing, - services: esm.getServices -}; \ No newline at end of file + services: esm.getServices, + lastCron: esm.getLastCron +}; diff --git a/libs/Utils/Config.php b/libs/Utils/Config.php index 212a227..2a13945 100644 --- a/libs/Utils/Config.php +++ b/libs/Utils/Config.php @@ -5,7 +5,17 @@ class Config public $file = null; public $config = null; - public function __construct() + private static $instance = null; + + public static function instance(){ + if (!Config::$instance) + { + Config::$instance = new Config(); + } + return Config::$instance; + } + + private function __construct() { $this->_checkPHPVersion(5.3); @@ -24,7 +34,7 @@ private function _readFile() if ($this->config == null && json_last_error() != JSON_ERROR_NONE) { - throw new \LogicException(sprintf("Failed to parse config file '%s'. Error: '%s'", basename($this->file) , json_last_error_msg())); + throw new \LogicException(sprintf("Failed to parse config file '%s'.\nError: '%s'\n", basename($this->file) , json_last_error_msg())); } } @@ -38,7 +48,9 @@ public function get($var) $tab = $this->config; $explode = explode(':', $var); - + if (!$explode) + return false; + foreach ($explode as $vartmp) { if (isset($tab[$vartmp])) @@ -47,11 +59,11 @@ public function get($var) } } - // return $tab == $this->config ? null : $tab; - return $tab; + // do not return all config if param is missing + return $tab == $this->config ? null : $tab; } - - + + /** * Returns all config variables */ @@ -80,7 +92,7 @@ public function checkUpdate() { if ($this->get('esm:check_updates') === false) return null; - + $response = null; $this_version = $this->get('esm:version'); $update_url = $this->get('esm:website').'/esm-web/update/'.$this_version; @@ -135,4 +147,4 @@ function json_last_error_msg() $error = json_last_error(); return array_key_exists($error, $errors) ? $errors[$error] : "Unknown error ({$error})"; } -} \ No newline at end of file +} diff --git a/libs/Utils/Misc.php b/libs/Utils/Misc.php index 7aab276..8d03539 100644 --- a/libs/Utils/Misc.php +++ b/libs/Utils/Misc.php @@ -2,6 +2,7 @@ class Misc { + public static $cache = true; /** * Returns human size * @@ -20,11 +21,11 @@ public static function getSize($filesize, $precision = 2) else break; } - + return round($filesize, $precision).' '.$units[$idUnit].'B'; } - - + + /** * Returns hostname * @@ -38,14 +39,14 @@ public static function getHostname() /** * Returns CPU cores number - * + * * @return int Number of cores */ public static function getCpuCoresNumber() { - if (!($num_cores = shell_exec('/bin/grep -c ^processor /proc/cpuinfo'))) + if (!($num_cores = Misc::shellexec("/bin/grep -c ^processor /proc/cpuinfo"))) { - if (!($num_cores = trim(shell_exec('/usr/bin/nproc')))) + if (!($num_cores = trim(Misc::shellexec("/usr/bin/nproc")))) { $num_cores = 1; } @@ -72,7 +73,7 @@ public static function getLanIp() /** * Seconds to human readable text * Eg: for 36545627 seconds => 1 year, 57 days, 23 hours and 33 minutes - * + * * @return string Text */ public static function getHumanTime($seconds) @@ -84,13 +85,13 @@ public static function getHumanTime($seconds) 'minute' => 60, // 'second' => 1, ); - + $parts = array(); - + foreach ($units as $name => $divisor) { $div = floor($seconds / $divisor); - + if ($div == 0) continue; else @@ -100,9 +101,9 @@ public static function getHumanTime($seconds) $parts[] = $div.' '.$name.'s'; $seconds %= $divisor; } - + $last = array_pop($parts); - + if (empty($parts)) return $last; else @@ -124,10 +125,12 @@ public static function whichCommand($cmds, $args = '', $returnWithArgs = true) foreach ($cmds as $cmd) { - if (trim(shell_exec($cmd.$args)) != '') + $res = Misc::exec($cmd.$args, $output); + //if (is_array($output) && count($output)>0) + if ($res) { $return = $cmd; - + if ($returnWithArgs) $return .= $args; @@ -144,7 +147,7 @@ public static function whichCommand($cmds, $args = '', $returnWithArgs = true) * Ex : echo 'mot'.Misc::pluralize(5); ==> prints mots * Ex : echo 'cheva'.Misc::pluralize(5, 'ux', 'l'); ==> prints chevaux * Ex : echo 'cheva'.Misc::pluralize(1, 'ux', 'l'); ==> prints cheval - * + * * @param int $nb Number * @param string $plural String for plural word * @param string $singular String for singular word @@ -195,8 +198,8 @@ public static function scanPort($host, $port, $protocol = 'tcp', $timeout = 3) $endTime = time(); - $timeDiff = $endTime - $startTime; - + $timeDiff = $endTime - $startTime; + fclose($handle); if ($timeDiff >= $timeout) @@ -207,4 +210,162 @@ public static function scanPort($host, $port, $protocol = 'tcp', $timeout = 3) return false; } -} \ No newline at end of file + + public static function exec($command, &$output, &$return_var = null) + { + $config = Config::instance(); + $output = Misc::cache($command); + //echo "on passe par Misc::exec"; + if ($output) + { + //echo "found in cache"; + return $output; + // exec + } + elseif ($config->get('esm:mode') == 'cron' && PHP_SAPI != 'cli') + { + //echo "mode CRON absent\n"; + return false; + } + else + { + //echo "On EXECUTE\n"; + if ($return_var) { + $return = exec($command, $output, $return_var); + if ($return_var != 0) + { + //echo "\n\tERROR with $command\n\n"; + header('HTTP/1.0 500 Server Error'); + return false; + } + } + else { + $return = exec($command, $output); + } + + if (isset($_SERVER['argv']) && in_array('--save', $_SERVER['argv'])) + { + $written = Misc::cache($command, $output); + } + } + return $return; + } + + public static function shellexec($command, $args = null) + { + $config = Config::instance(); + $output = Misc::cache($command.$args); + if ($output) + { + //echo "$command.$args found in cache
    "; + //var_dump($output); + return $output; + } + elseif ($config->get('esm:mode') == 'cron' && PHP_SAPI != 'cli') + { + return null; + } + else + { + $output = shell_exec($command.$args); + if (is_array($output)) + { + die("wtf output of shell_exec is an array ???"); + } + else + { + //echo "output is a string: $output"; + } + if (isset($_SERVER['argv']) && in_array('--save', $_SERVER['argv'])) + Misc::cache($command.$args, $output); + } + return $output; + } + + static public function cache($name, $data = null, $lifetime = 0) + { + if (empty($name)) + throw new Exception("invalid cache key"); + $config = Config::instance(); + $salt = $config->get('esm:salt'); + $prefix = $config->get('esm:cron_output_prefix'); + $file = $prefix.sha1($name.$salt).'.txt'; + + $dir = ROOTPATH.DIRECTORY_SEPARATOR.$config->get('esm:cron_output_path').DIRECTORY_SEPARATOR; + if ($data === NULL) + { + + if (isset($_SERVER['argv']) && in_array('--save', $_SERVER['argv'])) + { + //echo "
    \n\nCACHE REMOVED\n\n
    "; + Misc::$cache = false; + return false; + } + + + if (is_file($dir.$file)) + { + if (!Misc::$cache || !$lifetime || ((time() - filemtime($dir.$file)) < $lifetime)) + { + try + { + return unserialize(file_get_contents($dir.$file)); + } + catch(Exception $e) + { + } + } + else + { + try{ + unlink($dir.$file); + } + catch(Exception $e) + { + } + } + } + else + { + //echo "file not exists: $name ($file) \n
    "; + } + //echo "nothing found in cache for $name\n"; + return NULL; + } + $data = serialize($data); + try + { + $written = file_put_contents($dir.$file, $data, LOCK_EX); + //echo "\nWRITE for $name \n\tIN $file:\n\t\t$data\nENDOFWRITE"; + return (bool)$written; + } + catch(Exception $e) + { + return false; + } + } + + function ago($time) + { + $periods = array("second", "minute", "hour", "day", "week", "month", "year", "decade"); + $lengths = array("60","60","24","7","4.35","12","10"); + + $now = time(); + + $difference = $now - $time; + $tense = "ago"; + + for($j = 0; $difference >= $lengths[$j] && $j < count($lengths)-1; $j++) { + $difference /= $lengths[$j]; + } + + $difference = round($difference); + + if($difference != 1) { + $periods[$j].= "s"; + } + + return "$difference $periods[$j] 'ago' "; + } +} + diff --git a/libs/cpu.php b/libs/cpu.php index 993e289..b9b54af 100644 --- a/libs/cpu.php +++ b/libs/cpu.php @@ -1,6 +1,6 @@ get('cpu:cmdMaxFreq'); + if ($f = Misc::shellexec($cmd)) { $f = $f / 1000; $frequency = $f.' MHz'; @@ -62,16 +63,18 @@ } // CPU Temp -if ($Config->get('cpu:enable_temperature')) +if ($config->get('cpu:enable_temperature')) { - if (file_exists('/usr/bin/sensors') && exec('/usr/bin/sensors | grep -E "^(CPU Temp|Core 0)" | cut -d \'+\' -f2 | cut -d \'.\' -f1', $t)) + $cmd = $config->get('cpu:cmdTemperature'); + if (Misc::exec($cmd, $t)) { if (isset($t[0])) $temp = $t[0].' °C'; } else { - if (exec('cat /sys/class/thermal/thermal_zone0/temp', $t)) + $cmd = $config->get('cpu:cmdThermal'); + if (Misc::exec($cmd, $t)) { $temp = round($t[0] / 1000).' °C'; } @@ -88,4 +91,5 @@ 'temp' => $temp, ); -echo json_encode($datas); +if (!isset($_SERVER['argv']) || !in_array('--quiet', $_SERVER['argv'])) + echo json_encode($datas); diff --git a/libs/disk.php b/libs/disk.php index 6367114..9b17400 100644 --- a/libs/disk.php +++ b/libs/disk.php @@ -1,12 +1,14 @@ 7) { for (i=1; iget('disk:cmd'); +Misc::exec($cmd, $df); +if (!$df) { $datas[] = array( 'total' => 'N.A', @@ -29,7 +31,7 @@ if ($percent > 100) $percent = 100; - if (strpos($type, 'tmpfs') !== false && $Config->get('disk:show_tmpfs') === false) + if (strpos($type, 'tmpfs') !== false && $config->get('disk:show_tmpfs') === false) continue; if (!in_array($mount, $mounted_points)) @@ -44,7 +46,7 @@ 'mount' => $mount, ); - if ($Config->get('disk:show_filesystem')) + if ($config->get('disk:show_filesystem')) $datas[$key]['filesystem'] = $filesystem; } @@ -54,4 +56,5 @@ } -echo json_encode($datas); +if (!isset($_SERVER['argv']) || !in_array('--quiet', $_SERVER['argv'])) + echo json_encode($datas); diff --git a/libs/last_cron.php b/libs/last_cron.php new file mode 100644 index 0000000..0c87323 --- /dev/null +++ b/libs/last_cron.php @@ -0,0 +1,13 @@ +get('last_login:enable')) +if ($config->get('last_login:enable')) { - if (!(exec('/usr/bin/lastlog --time 365 | awk \'{ printf $1";"; for (i=4; iget('last_login:cmd'), $users))) { $datas[] = array( 'user' => 'N.A', @@ -16,7 +15,7 @@ } else { - $max = $Config->get('last_login:max'); + $max = $config->get('last_login:max'); for ($i = 1; $i < count($users) && $i <= $max; $i++) { @@ -30,4 +29,5 @@ } } -echo json_encode($datas); +if (!isset($_SERVER['argv']) || !in_array('--quiet', $_SERVER['argv'])) + echo json_encode($datas); diff --git a/libs/last_sftp_login.php b/libs/last_sftp_login.php new file mode 100644 index 0000000..a893ab3 --- /dev/null +++ b/libs/last_sftp_login.php @@ -0,0 +1,65 @@ +get('last_sftp_login:max'); + +$datas = array(); + +# 'Aug 25 10:37:48 myserver sshd[14951]: pam_unix(sshd:session): session opened for user user1 by (uid=0)' +# [a-z]\+ \d\+ [0-9:]\+ [a-z_-]\+ sshd\[\d\+]: pam_unix(sshd:session): session opened for user \(.*\) +# Sep 8 09:57:40 myserver sshd[13295]: pam_unix(sshd:session): session opened for user user2 by (uid=0) +$pattern = <<<'PATTERN' +`(?[a-z]+)\s\s? # the month + (?\d+)\s # the day + (?