implmented cron in open
This commit is contained in:
parent
831ed2570d
commit
57a0249982
|
@ -0,0 +1,331 @@
|
|||
<?php
|
||||
/**
|
||||
* Extension to schedule tasks on Pandora FMS Console
|
||||
*
|
||||
* @category Extensions
|
||||
* @package Pandora FMS
|
||||
* @subpackage Enterprise
|
||||
* @version 1.0.0
|
||||
* @license See below
|
||||
*
|
||||
* ______ ___ _______ _______ ________
|
||||
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
|
||||
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
|
||||
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
|
||||
*
|
||||
* ============================================================================
|
||||
* Copyright (c) 2005-2023 Pandora FMS
|
||||
* Please see https://pandorafms.com/community/ for full contribution list
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation for version 2.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
if (enterprise_installed() === true) {
|
||||
enterprise_include_once('/include/functions_cron.php');
|
||||
} else {
|
||||
include_once $config['homedir'].'/include/functions_cron_task.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class to run scheduled tasks in cron extension
|
||||
*/
|
||||
class DiscoveryConsoleTask
|
||||
{
|
||||
public const SCHEDULES = [
|
||||
'no',
|
||||
'hourly',
|
||||
'daily',
|
||||
'weekly',
|
||||
'monthly',
|
||||
'yearly',
|
||||
'custom',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve scheduled tasks given filters.
|
||||
*
|
||||
* @param array $filter Tasks filtered.
|
||||
*
|
||||
* @return array List of scheduled tasks.
|
||||
*/
|
||||
public function list(array $filter)
|
||||
{
|
||||
$tasks = db_get_all_rows_filter(
|
||||
'tuser_task_scheduled INNER JOIN tuser_task ON tuser_task.id = tuser_task_scheduled.id_user_task',
|
||||
$filter,
|
||||
'tuser_task_scheduled.*'
|
||||
);
|
||||
|
||||
if ($tasks === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$tasks = array_map(
|
||||
function ($item) {
|
||||
$item['args'] = unserialize($item['args']);
|
||||
return $item;
|
||||
},
|
||||
$tasks
|
||||
);
|
||||
|
||||
return $tasks;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Should execute task.
|
||||
*
|
||||
* @param array $task Info task.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function shouldTaskRun($task)
|
||||
{
|
||||
global $config;
|
||||
|
||||
if (isset($config['reporting_console_enable']) === true
|
||||
&& (bool) $config['reporting_console_enable'] === true
|
||||
) {
|
||||
$task_info = db_get_row('tuser_task', 'id', $task['id_user_task']);
|
||||
|
||||
if (isset($config['reporting_console_node']) === true
|
||||
&& (bool) $config['reporting_console_node'] === true
|
||||
) {
|
||||
if (($task_info['function_name'] !== 'cron_task_generate_report_by_template'
|
||||
&& $task_info['function_name'] !== 'cron_task_generate_report'
|
||||
&& $task_info['function_name'] !== 'cron_task_save_report_to_disk')
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (($task_info['function_name'] === 'cron_task_generate_report_by_template'
|
||||
|| $task_info['function_name'] === 'cron_task_generate_report'
|
||||
|| $task_info['function_name'] === 'cron_task_save_report_to_disk')
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Manage scheduled tasks.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
global $config;
|
||||
global $pandora_version;
|
||||
|
||||
// Maintenance tasks for tconsole table.
|
||||
// Must do at every Cron execution.
|
||||
if (isset($config['id_console']) === true && $config['id_console'] > 0) {
|
||||
$console_exists = db_get_row('tconsole', 'id_console', $config['id_console']);
|
||||
if ($console_exists === false) {
|
||||
db_process_sql_insert(
|
||||
'tconsole',
|
||||
[
|
||||
'id_console' => $config['id_console'],
|
||||
'description' => $config['console_description'],
|
||||
'version' => $pandora_version,
|
||||
'console_type' => ($config['reporting_console_node'] === true) ? 1 : 0,
|
||||
'timezone' => $config['timezone'],
|
||||
'public_url' => $config['public_url'],
|
||||
]
|
||||
);
|
||||
} else {
|
||||
db_process_sql_update(
|
||||
'tconsole',
|
||||
[
|
||||
'description' => $config['console_description'],
|
||||
'timezone' => $config['timezone'],
|
||||
'public_url' => $config['public_url'],
|
||||
'console_type' => (int) $config['reporting_console_node'],
|
||||
'version' => $pandora_version,
|
||||
],
|
||||
[
|
||||
'id_console' => $config['id_console'],
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Maintenance task: schedule task 'cron_task_start_gotty' if not defined yet.
|
||||
// Must do at every Cron execution.
|
||||
$user_function_task_id = db_get_value_sql('SELECT id FROM `tuser_task_scheduled` WHERE `args` LIKE "%cron_task_start_gotty%"');
|
||||
|
||||
if ($user_function_task_id === false) {
|
||||
$this->schedule(
|
||||
'cron_task_call_user_function',
|
||||
[
|
||||
0 => 'cron_task_start_gotty',
|
||||
'function_name' => 'cron_task_start_gotty',
|
||||
'internal' => 1,
|
||||
],
|
||||
'daily',
|
||||
0,
|
||||
0,
|
||||
strtotime('tomorrow')
|
||||
);
|
||||
}
|
||||
|
||||
// Maintenance task: check whether start GoTTY SSH and Telnet processes are running and start otherwise.
|
||||
// Must do at every Cron execution.
|
||||
cron_task_start_gotty(false);
|
||||
|
||||
// Do not output anything until is completed. There're session
|
||||
// operations inside cron_task_run function.
|
||||
ob_start();
|
||||
|
||||
if (cron_task_lock() === false) {
|
||||
// Cannot continue. Locked.
|
||||
echo ob_get_clean();
|
||||
exit;
|
||||
}
|
||||
|
||||
$time = get_system_time();
|
||||
$scheduled_tasks = db_get_all_rows_in_table('tuser_task_scheduled');
|
||||
if (!$scheduled_tasks) {
|
||||
$scheduled_tasks = [];
|
||||
}
|
||||
|
||||
/*
|
||||
Watch out! First_execution corresponds to next_execution the name
|
||||
of the bbdd is maintained to ensure integrity.
|
||||
*/
|
||||
|
||||
foreach ($scheduled_tasks as $task) {
|
||||
$params = unserialize($task['args']);
|
||||
if ($this->shouldTaskRun($task) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($task['scheduled'] == 'no') {
|
||||
if (($params['first_execution']) < $time) {
|
||||
echo date('Y/m/d H:i:s').' Execute once time cron task: ';
|
||||
echo $task['id'];
|
||||
echo "\n\n";
|
||||
cron_task_run($task['id']);
|
||||
// The task was not scheduled and was executed once.
|
||||
db_process_sql_delete(
|
||||
'tuser_task_scheduled',
|
||||
['id' => $task['id']]
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (($params['first_execution']) < $time) {
|
||||
echo date('Y/m/d H:i:s').' EXECUTED CRON TASK: '.$task['id'];
|
||||
echo "\n";
|
||||
echo "\n";
|
||||
cron_task_run($task['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dump to output.
|
||||
echo ob_get_clean();
|
||||
|
||||
// Release the lock.
|
||||
cron_task_release_lock();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Schedules a discovery console task to be executed by cron.
|
||||
*
|
||||
* @param string $function_name Name of the function:
|
||||
* cron_task_generate_report
|
||||
* cron_task_generate_report_by_template
|
||||
* cron_task_save_report_to_disk
|
||||
* cron_task_do_backup
|
||||
* cron_task_execute_custom_script
|
||||
* cron_task_save_xml_report_to_disk
|
||||
* cron_task_feedback_send_mail
|
||||
* cron_task_generate_csv_log.
|
||||
* @param array $arguments Task execution arguments (if needed).
|
||||
* @param string $schedule Task schedule options:
|
||||
* 'no',
|
||||
* 'hourly',
|
||||
* 'daily',
|
||||
* 'weekly',
|
||||
* 'monthly',
|
||||
* 'yearly',
|
||||
* 'custom'.
|
||||
* @param integer $group_id Group id (0 => all).
|
||||
* @param string|null $id_user User id, if null, current user.
|
||||
* @param integer|null $time_start When to start, if null, now.
|
||||
*
|
||||
* @return boolean Sucessfully scheduled or not.
|
||||
*/
|
||||
public function schedule(
|
||||
string $function_name,
|
||||
array $arguments=[],
|
||||
string $schedule='no',
|
||||
int $group_id=0,
|
||||
?string $id_user=null,
|
||||
?int $time_start=null
|
||||
) {
|
||||
global $config;
|
||||
|
||||
if ($id_user === null) {
|
||||
$id_user = $config['id_user'];
|
||||
}
|
||||
|
||||
$idUserTask = db_get_value(
|
||||
'id',
|
||||
'tuser_task',
|
||||
'function_name',
|
||||
$function_name
|
||||
);
|
||||
|
||||
if ($idUserTask === false) {
|
||||
// Failed to identify function.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (in_array($schedule, self::SCHEDULES) === false) {
|
||||
// Failed to schedule. Not a valid schedule option.
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($time_start === null) {
|
||||
$time_start = strtotime('now');
|
||||
}
|
||||
|
||||
// Params for send mail with cron.
|
||||
$parameters = array_merge(
|
||||
$arguments,
|
||||
[ 'first_execution' => $time_start ]
|
||||
);
|
||||
|
||||
// Values insert task cron.
|
||||
$task = [
|
||||
'id_usuario' => $id_user,
|
||||
'id_user_task' => $idUserTask,
|
||||
'args' => serialize($parameters),
|
||||
'scheduled' => $schedule,
|
||||
'id_grupo' => $group_id,
|
||||
];
|
||||
|
||||
$result = db_process_sql_insert(
|
||||
'tuser_task_scheduled',
|
||||
$task
|
||||
);
|
||||
|
||||
return ($result !== false);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,623 @@
|
|||
<?php
|
||||
/**
|
||||
* Schedule tasks on Pandora FMS Console
|
||||
*
|
||||
* @category library
|
||||
* @package Pandora FMS
|
||||
* @subpackage cron
|
||||
* @version 1.0.0
|
||||
* @license See below
|
||||
*
|
||||
* ______ ___ _______ _______ ________
|
||||
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
|
||||
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
|
||||
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
|
||||
*
|
||||
* ============================================================================
|
||||
* Copyright (c) 2005-2023 Pandora FMS
|
||||
* Please see https://pandorafms.com/community/ for full contribution list
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation for version 2.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* ============================================================================
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Generate a lock system to avoid multiple executions.
|
||||
*
|
||||
* @param string $lockfile Filename to use as lock.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function cron_lock(string $lockfile)
|
||||
{
|
||||
global $config;
|
||||
|
||||
if (empty($lockfile) === true) {
|
||||
$lockfile = 'cron.lock';
|
||||
}
|
||||
|
||||
$ignore_lock = 0;
|
||||
// Lock to prevent multiple instances of the cron extension.
|
||||
$lock = $config['attachment_store'].'/'.$lockfile;
|
||||
if (file_exists($lock) === true) {
|
||||
// Lock file exists.
|
||||
$read_PID = file_get_contents($lock);
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
|
||||
// Windows check.
|
||||
$processes = explode("\n", shell_exec('tasklist.exe'));
|
||||
$ignore_lock = 1;
|
||||
foreach ($processes as $process) {
|
||||
if (empty($process) === true
|
||||
|| strpos('===', $process) === 0
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$matches = false;
|
||||
preg_match('/(.*?)\s+(\d+).*$/', $process, $matches);
|
||||
$pid = $matches[2];
|
||||
|
||||
if ((int) $pid === (int) $read_PID) {
|
||||
$ignore_lock = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Linux check.
|
||||
if (file_exists('/proc/'.$read_PID) === true) {
|
||||
// Process with a pid = $pid is running.
|
||||
// CRON already running: [$read_PID].
|
||||
$ignore_lock = 0;
|
||||
} else {
|
||||
// CRON process [$read_PID] does not exist.
|
||||
// process not found, ignore $lock.
|
||||
$ignore_lock = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// The lock automatically expires after 24 hours.
|
||||
$lock_mtime = filemtime($lock);
|
||||
if (($ignore_lock === 0 )
|
||||
&& ($lock_mtime !== false && $lock_mtime + SECONDS_1DAY > time())
|
||||
) {
|
||||
// Locked!
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to get a lock from DB.
|
||||
$dblock = db_get_lock($config['dbname'].'.'.$lockfile);
|
||||
if ($dblock !== 1) {
|
||||
// Locked!
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store PID in lock file.
|
||||
$PID = getmypid();
|
||||
echo 'CRON running ['.$PID."]\n";
|
||||
file_put_contents($lock, $PID);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if CRON.task is available to start.
|
||||
*
|
||||
* @return boolean True, available. False not available.
|
||||
*/
|
||||
function cron_task_lock()
|
||||
{
|
||||
return cron_lock('cron.lock');
|
||||
}
|
||||
|
||||
/**
|
||||
* Release CRON.task lock
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function cron_task_release_lock()
|
||||
{
|
||||
global $config;
|
||||
|
||||
// Release DB lock.
|
||||
$dblock = db_release_lock($config['dbname'].'.cron.lock');
|
||||
unlink($config['attachment_store'].'/cron.lock');
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates target schedule time
|
||||
*
|
||||
* @param string $scheduled_time Desired scheduled time.
|
||||
* @param integer $custom_data Custom scheduled time.
|
||||
* @param integer|null $timestamp Custom timestamp.
|
||||
*
|
||||
* @return integer amount of time.
|
||||
*/
|
||||
function cron_get_scheduled_time(
|
||||
string $scheduled_time,
|
||||
int $custom_data=0,
|
||||
$timestamp=null
|
||||
) {
|
||||
if ($scheduled_time == 'no') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($scheduled_time == 'hourly') {
|
||||
return SECONDS_1HOUR;
|
||||
}
|
||||
|
||||
if ($scheduled_time == 'daily') {
|
||||
return SECONDS_1DAY;
|
||||
}
|
||||
|
||||
if ($scheduled_time == 'weekly') {
|
||||
return SECONDS_1WEEK;
|
||||
}
|
||||
|
||||
if ($scheduled_time == 'monthly') {
|
||||
$month = (($timestamp === null) ? date('m') : date('m', $timestamp));
|
||||
$year = (($timestamp === null) ? date('Y') : date('Y', $timestamp));
|
||||
|
||||
$days_month = (cal_days_in_month(
|
||||
CAL_GREGORIAN,
|
||||
$month,
|
||||
$year
|
||||
) * SECONDS_1DAY);
|
||||
|
||||
return $days_month;
|
||||
}
|
||||
|
||||
if ($scheduled_time == 'yearly') {
|
||||
return SECONDS_1YEAR;
|
||||
}
|
||||
|
||||
if ($scheduled_time == 'custom') {
|
||||
return $custom_data;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run scheduled task.
|
||||
*
|
||||
* @param integer $id_user_task Task to be run.
|
||||
* @param boolean $force_run Force run.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function cron_task_run(
|
||||
int $id_user_task,
|
||||
bool $force_run=false
|
||||
) {
|
||||
global $config;
|
||||
|
||||
if (isset($config['id_console']) === true && $config['id_console'] > 0) {
|
||||
$sql = sprintf(
|
||||
'SELECT *
|
||||
FROM tuser_task_scheduled
|
||||
WHERE id=%d AND id_console IN (0, %d)',
|
||||
$id_user_task,
|
||||
$config['id_console']
|
||||
);
|
||||
|
||||
$task_scheduled = db_get_row_sql($sql);
|
||||
|
||||
if ($task_scheduled !== false) {
|
||||
db_process_sql_update(
|
||||
'tconsole',
|
||||
['last_execution' => time()],
|
||||
['id_console' => $config['id_console']]
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$filter = [
|
||||
'id' => $id_user_task,
|
||||
'id_console' => 0,
|
||||
];
|
||||
|
||||
$task_scheduled = db_get_row_filter('tuser_task_scheduled', $filter, false);
|
||||
}
|
||||
|
||||
$args = unserialize($task_scheduled['args']);
|
||||
|
||||
if (enterprise_installed() === false
|
||||
&& isset($args['function_name']) === true
|
||||
&& $args['function_name'] !== 'cron_task_start_gotty'
|
||||
) {
|
||||
// Only cron_task_start_gotty is allowed to run in non enterprise environments.
|
||||
return;
|
||||
}
|
||||
|
||||
if (enterprise_installed() === true) {
|
||||
$task = db_get_row('tuser_task', 'id', $task_scheduled['id_user_task']);
|
||||
} else {
|
||||
$task = [
|
||||
'name' => 'Call PHP function',
|
||||
'function_name' => 'cron_task_call_user_function',
|
||||
];
|
||||
}
|
||||
|
||||
// Register shutdown function in case of fatal error, like.
|
||||
register_shutdown_function('cron_task_handle_error', $task_scheduled, $task, $force_run);
|
||||
|
||||
if (is_metaconsole() && !defined('METACONSOLE')) {
|
||||
define('METACONSOLE', 1);
|
||||
}
|
||||
|
||||
if (! function_exists($task['function_name'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the task is disable, not run.
|
||||
if ((bool) $task_scheduled['enabled'] === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (session_status() === PHP_SESSION_DISABLED) {
|
||||
return;
|
||||
}
|
||||
|
||||
$old_user = '';
|
||||
if (isset($config['id_user']) === false) {
|
||||
$config['id_user'] = $task_scheduled['id_usuario'];
|
||||
}
|
||||
|
||||
$old_user = $config['id_user'];
|
||||
|
||||
$old_session_id = session_id();
|
||||
$new_session_id = 'cron-'.uniqid();
|
||||
|
||||
// Simulate user login.
|
||||
session_id($new_session_id);
|
||||
session_start();
|
||||
$_SESSION['id_usuario'] = $config['id_user'];
|
||||
session_write_close();
|
||||
|
||||
set_time_limit(0);
|
||||
|
||||
|
||||
if ($task['function_name'] == 'cron_task_generate_report_by_template'
|
||||
|| $task['function_name'] == 'cron_task_generate_report'
|
||||
) {
|
||||
// If empty agent position, add it.
|
||||
if (!isset($args[1])) {
|
||||
array_splice($args, 1, 0, '');
|
||||
}
|
||||
|
||||
$args[] = $task_scheduled['scheduled'];
|
||||
}
|
||||
|
||||
call_user_func_array(
|
||||
$task['function_name'],
|
||||
array_merge(array_values(($args ?? [])), [$id_user_task])
|
||||
);
|
||||
|
||||
if (session_status() === PHP_SESSION_ACTIVE) {
|
||||
@session_destroy();
|
||||
}
|
||||
|
||||
session_id($old_session_id);
|
||||
session_start();
|
||||
|
||||
$config['id_user'] = $old_user;
|
||||
$sql = '';
|
||||
$sql2 = '';
|
||||
|
||||
if (!$force_run) {
|
||||
$period = cron_get_scheduled_time(
|
||||
$task_scheduled['scheduled'],
|
||||
$task_scheduled['custom_data']
|
||||
);
|
||||
$old_args = unserialize($task_scheduled['args']);
|
||||
if ($period > 3600) {
|
||||
$array_explode = explode(
|
||||
':',
|
||||
date('H:i', $old_args['first_execution'])
|
||||
);
|
||||
$hora_en_segundos = (($array_explode[0] * 3600 ) + ($array_explode[1] * 60));
|
||||
|
||||
$array_explode_period = explode(
|
||||
':',
|
||||
date('H:i', ($old_args['first_execution'] + $period))
|
||||
);
|
||||
$hora_en_segundos2 = (($array_explode_period[0] * 3600 ) + ($array_explode_period[1] * 60));
|
||||
|
||||
if ($hora_en_segundos !== $hora_en_segundos2) {
|
||||
$period = ($period + ($hora_en_segundos - $hora_en_segundos2));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
/*
|
||||
Calculate the number of periods between last execution and
|
||||
current time.
|
||||
*/
|
||||
|
||||
$num_of_periods = 0;
|
||||
if ($period !== 0) {
|
||||
$num_of_periods = ceil(
|
||||
(time() - $old_args['first_execution']) / $period
|
||||
);
|
||||
}
|
||||
|
||||
if ($task_scheduled['scheduled'] == 'monthly') {
|
||||
$updated_time = $old_args['first_execution'];
|
||||
|
||||
// Update updated_time adding the period for each month individually since it is a variable value depending on the number of days a month has.
|
||||
while ($num_of_periods > 0) {
|
||||
// Get days of current month.
|
||||
$monthly_period = cron_get_scheduled_time(
|
||||
'monthly',
|
||||
$task_scheduled['custom_data'],
|
||||
$updated_time
|
||||
);
|
||||
$updated_time += $monthly_period;
|
||||
$num_of_periods--;
|
||||
}
|
||||
|
||||
$old_args['first_execution'] = $updated_time;
|
||||
} else if ($task_scheduled['scheduled'] == 'weekly') {
|
||||
$weekly_schedule = json_decode(io_safe_output($old_args['weekly_schedule']), true);
|
||||
if (empty($weekly_schedule) !== true) {
|
||||
$datetime = new DateTime('tomorrow');
|
||||
$nameday = strtolower($datetime->format('l'));
|
||||
$continue = true;
|
||||
while ($continue === true) {
|
||||
if (isset($weekly_schedule[$nameday]) === true) {
|
||||
$weekly_date = $datetime->format('Y-m-d');
|
||||
$weekly_time = $weekly_schedule[$nameday][0]['start'];
|
||||
$old_args['first_execution'] = strtotime($weekly_date.' '.$weekly_time);
|
||||
|
||||
$continue = false;
|
||||
} else {
|
||||
$datetime->modify('+1 day');
|
||||
$nameday = strtolower($datetime->format('l'));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Add it to next execution.
|
||||
$old_args['first_execution'] += ($period * $num_of_periods);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// If some error (ex $period=0) next execution=current time+period.
|
||||
$old_args['first_execution'] = (time() + $period);
|
||||
}
|
||||
|
||||
$new_args = serialize($old_args);
|
||||
}
|
||||
|
||||
if ($config['timesource'] == 'sql') {
|
||||
$sql = sprintf(
|
||||
'UPDATE tuser_task_scheduled
|
||||
SET last_run=UNIX_TIMESTAMP()
|
||||
WHERE id=%d',
|
||||
$id_user_task
|
||||
);
|
||||
} else {
|
||||
$sql = sprintf(
|
||||
'UPDATE tuser_task_scheduled
|
||||
SET last_run= %d
|
||||
WHERE id=%d',
|
||||
time(),
|
||||
$id_user_task
|
||||
);
|
||||
}
|
||||
|
||||
if (!$force_run) {
|
||||
$sql2 = "UPDATE tuser_task_scheduled
|
||||
SET args = '".$new_args."'
|
||||
WHERE id=".$id_user_task;
|
||||
}
|
||||
|
||||
db_process_sql($sql);
|
||||
db_process_sql($sql2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execuytes custom function defined in PHP.
|
||||
*
|
||||
* @param string $function_name Name to execute.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function cron_task_call_user_function(string $function_name)
|
||||
{
|
||||
global $config;
|
||||
include_once $config['homedir'].'/vendor/autoload.php';
|
||||
|
||||
call_user_func($function_name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check whether GoTTY SSH and Telnet processes are running and start otherwise.
|
||||
*
|
||||
* @param boolean $restart_mode Restart the processes if running.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function cron_task_start_gotty(bool $restart_mode=true)
|
||||
{
|
||||
global $config;
|
||||
|
||||
if (empty($config['gotty_ssh_addr']) === true
|
||||
&& empty($config['gotty_telnet_addr']) === true
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
include_once $config['homedir'].'/include/functions_config.php';
|
||||
|
||||
// Check prev SSH process running and kill it.
|
||||
if (empty($config['restart_gotty_ssh_next_cron_port']) === false) {
|
||||
config_update_value('restart_gotty_ssh_next_cron_port', '');
|
||||
|
||||
$prevProcessRunningSSH = shell_exec("pgrep -f 'pandora_gotty.*-p ".$config['restart_gotty_ssh_next_cron_port']."'");
|
||||
|
||||
if (!empty($prevProcessRunningSSH)) {
|
||||
shell_exec("pkill -f 'pandora_gotty.*-p ".$config['restart_gotty_ssh_next_cron_port']."'");
|
||||
}
|
||||
}
|
||||
|
||||
// Check if prev Telnet process running and kill it.
|
||||
if (empty($config['restart_gotty_telnet_next_cron_port']) === false) {
|
||||
config_update_value('restart_gotty_telnet_next_cron_port', '');
|
||||
|
||||
$prevProcessRunningTelnet = shell_exec("pgrep -f 'pandora_gotty.*-p ".$config['restart_gotty_telnet_next_cron_port']."'");
|
||||
|
||||
if (!empty($prevProcessRunningTelnet)) {
|
||||
shell_exec("pkill -f 'pandora_gotty.*-p ".$config['restart_gotty_telnet_next_cron_port']."'");
|
||||
}
|
||||
}
|
||||
|
||||
// Check if pandora_gotty is running on the configured port.
|
||||
$processRunningSSH = shell_exec("pgrep -f 'pandora_gotty.*-p ".$config['gotty_ssh_port']."'");
|
||||
$processRunningTelnet = shell_exec("pgrep -f 'pandora_gotty.*-p ".$config['gotty_telnet_port']."'");
|
||||
|
||||
$start_ssh_proc = true;
|
||||
$start_telnet_proc = true;
|
||||
|
||||
if (empty($config['gotty_ssh_addr']) === true) {
|
||||
$start_ssh_proc = false;
|
||||
}
|
||||
|
||||
if (empty($config['gotty_telnet_addr']) === true) {
|
||||
$start_telnet_proc = false;
|
||||
}
|
||||
|
||||
if (!empty($processRunningSSH)) {
|
||||
// Process is running.
|
||||
if ($restart_mode === true || $start_ssh_proc === false) {
|
||||
// Stop the process for restarting.
|
||||
shell_exec("pkill -f 'pandora_gotty.*-p ".$config['gotty_ssh_port']."'");
|
||||
} else {
|
||||
// Prevent starting if already running and must not be restarted.
|
||||
$start_ssh_proc = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($processRunningTelnet)) {
|
||||
// Process is running.
|
||||
if ($restart_mode === true
|
||||
|| empty($config['restart_gotty_telnet_next_cron_port']) === false
|
||||
|| $start_telnet_proc === false
|
||||
) {
|
||||
// Restart GoTTY if it is intended to be restarted specifically, port has changed, or address was changed to an empty value.
|
||||
if (empty($config['restart_gotty_telnet_next_cron_port']) === false) {
|
||||
$telnet_port_kill = $config['restart_gotty_telnet_next_cron_port'];
|
||||
config_update_value('restart_gotty_telnet_next_cron_port', '');
|
||||
} else {
|
||||
$telnet_port_kill = $config['gotty_telnet_port'];
|
||||
}
|
||||
|
||||
// Stop the process for restarting.
|
||||
shell_exec("pkill -f 'pandora_gotty.*-p ".$telnet_port_kill."'");
|
||||
} else {
|
||||
// Prevent starting if already running and must not be restarted.
|
||||
$start_telnet_proc = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($start_ssh_proc === false && $start_telnet_proc === false) {
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
if ($start_ssh_proc === true) {
|
||||
$logFilePathSSH = $config['homedir'].'/log/gotty_ssh_cron_tmp.log';
|
||||
shell_exec('touch '.$logFilePathSSH);
|
||||
|
||||
// Start pandora_gotty and capture the output.
|
||||
$command_ssh = '/usr/bin/nohup /usr/bin/pandora_gotty --config /etc/pandora_gotty/pandora_gotty.conf -p '.$config['gotty_ssh_port'].' ssh > '.$logFilePathSSH.' 2>&1 &';
|
||||
shell_exec($command_ssh);
|
||||
}
|
||||
|
||||
if ($start_telnet_proc === true) {
|
||||
$logFilePathTelnet = $config['homedir'].'/log/gotty_telnet_cron_tmp.log';
|
||||
shell_exec('touch '.$logFilePathTelnet);
|
||||
|
||||
// Start pandora_gotty and capture the output.
|
||||
$command_telnet = '/usr/bin/nohup /usr/bin/pandora_gotty --config /etc/pandora_gotty/pandora_gotty.conf -p '.$config['gotty_telnet_port'].' telnet > '.$logFilePathTelnet.' 2>&1 &';
|
||||
shell_exec($command_telnet);
|
||||
}
|
||||
|
||||
$ssh_hash_read = false;
|
||||
$telnet_hash_read = false;
|
||||
|
||||
// Maximum wait time (seconds).
|
||||
$maxWaitTime = 2;
|
||||
|
||||
// Wait for content to appear in the log file.
|
||||
$startTime = time();
|
||||
|
||||
// Workaround to wait until process inputs data in the log.
|
||||
while (time() - $startTime < $maxWaitTime) {
|
||||
if ($start_ssh_proc === true) {
|
||||
// Read command output.
|
||||
$log_content_ssh = file_get_contents($logFilePathSSH);
|
||||
}
|
||||
|
||||
if ($start_ssh_proc === true
|
||||
&& !empty($log_content_ssh)
|
||||
&& $ssh_hash_read === false
|
||||
) {
|
||||
// Extract the URL from the output.
|
||||
if (preg_match('/.*?HTTP server is listening at:\s+(\S+)/', $log_content_ssh, $matches)) {
|
||||
$url = $matches[1];
|
||||
|
||||
// Extract the hash.
|
||||
$parts = explode('/', $url);
|
||||
$hash = array_slice($parts, -2, 1)[0];
|
||||
|
||||
config_update_value('gotty_ssh_connection_hash', $hash);
|
||||
}
|
||||
|
||||
unlink($logFilePathSSH);
|
||||
|
||||
$ssh_hash_read = true;
|
||||
}
|
||||
|
||||
if ($start_telnet_proc === true) {
|
||||
// Read command output.
|
||||
$log_content_telnet = file_get_contents($logFilePathTelnet);
|
||||
}
|
||||
|
||||
if ($start_telnet_proc === true
|
||||
&& !empty($log_content_telnet)
|
||||
&& $telnet_hash_read === false
|
||||
) {
|
||||
// Extract the URL from the output.
|
||||
if (preg_match('/.*?HTTP server is listening at:\s+(\S+)/', $log_content_telnet, $matches)) {
|
||||
$url = $matches[1];
|
||||
|
||||
// Extract the hash.
|
||||
$parts = explode('/', $url);
|
||||
$hash = array_slice($parts, -2, 1)[0];
|
||||
|
||||
config_update_value('gotty_telnet_connection_hash', $hash);
|
||||
}
|
||||
|
||||
unlink($logFilePathTelnet);
|
||||
|
||||
$telnet_hash_read = true;
|
||||
}
|
||||
|
||||
if (($start_ssh_proc === false || $ssh_hash_read === true)
|
||||
&& ($start_telnet_proc === false || $telnet_hash_read === true)
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Sleep for a short interval before checking again.
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue