| Server IP : 202.61.199.114 / Your IP : 216.73.217.139 Web Server : nginx/1.22.1 System : Linux de.arni-solutions.de 6.1.0-49-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.174-1 (2026-05-26) x86_64 User : web20 ( 1018) PHP Version : 8.4.23 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /var/www/clients/client2/arni-solutions.de/web/crm/cli/ |
Upload File : |
<?php
/**
* ArNi CRM – Cron-Logging-Shim.
*
* Wird aus /etc/cron.d/arni-crm aufgerufen und umhüllt verwaltete Cronjobs, um
* geplante Ausführungen MIT Startzeit, Dauer, Exit-Code und Ausgabe (STDOUT/STDERR)
* in der CRM-DB zu protokollieren. Aufruf-Form:
*
* /usr/bin/php cli/cron_run.php <jobId> <base64-Befehl> <base64-Arbeitsverzeichnis> <timeoutSek>
*
* Prinzipien:
* - Der eigentliche Befehl wird IMMER ausgeführt; Logging-Fehler (DB nicht erreichbar,
* keine Leserechte auf die Config etc.) brechen die Ausführung NIE ab.
* - Echter STDOUT/STDERR und Exit-Code werden durchgereicht (MAILTO etc. bleibt intakt).
* - Kein Session-/Bootstrap-Overhead (läuft als beliebiger Job-Benutzer).
*/
if (PHP_SAPI !== 'cli') { fwrite(STDERR, "CLI only\n"); exit(2); }
$jobId = isset($argv[1]) ? (int)$argv[1] : 0;
$cmd = isset($argv[2]) ? base64_decode($argv[2]) : '';
$cwd = isset($argv[3]) ? base64_decode($argv[3]) : '';
$timeout = isset($argv[4]) ? (int)$argv[4] : 3600;
if ($cmd === '') { fwrite(STDERR, "cron_run: leerer Befehl\n"); exit(2); }
if ($timeout < 1) $timeout = 1;
if ($timeout > 86400) $timeout = 86400;
/** Best-effort DB-Verbindung ohne Bootstrap/Session. */
$pdo = null; $prefix = 'crm_';
try {
$cfg = @require __DIR__ . '/../config/config.php';
if (is_array($cfg) && !empty($cfg['db'])) {
$d = $cfg['db'];
$prefix = isset($cfg['app']['table_prefix']) ? $cfg['app']['table_prefix'] : 'crm_';
$dsn = sprintf('mysql:host=%s;dbname=%s;charset=%s', $d['host'], $d['name'], isset($d['charset']) ? $d['charset'] : 'utf8mb4');
$pdo = new PDO($dsn, $d['user'], $d['pass'], [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES => false]);
}
} catch (\Throwable $e) { $pdo = null; }
$runsTbl = $prefix . 'server_cronjob_runs';
$jobsTbl = $prefix . 'server_cronjobs';
$start = date('Y-m-d H:i:s');
$t0 = microtime(true);
$runId = 0;
if ($pdo) {
try {
$st = $pdo->prepare('INSERT INTO ' . $runsTbl . ' (cronjob_id,server_id,started_at,status,`trigger`,created_at) VALUES (?,?,?,?,?,?)');
$st->execute([$jobId, 1, $start, 'running', 'scheduled', $start]);
$runId = (int)$pdo->lastInsertId();
} catch (\Throwable $e) { $runId = 0; }
}
// --- Befehl ausführen (mit timeout, im Arbeitsverzeichnis) ---
$full = ($cwd !== '' ? 'cd ' . escapeshellarg($cwd) . ' && ' : '') . $cmd;
$shell = '/usr/bin/timeout -k 5 ' . $timeout . 's /bin/bash -c ' . escapeshellarg($full);
$out = ''; $err = ''; $exit = 1;
$desc = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']];
$p = @proc_open($shell, $desc, $pipes);
if (is_resource($p)) {
$out = stream_get_contents($pipes[1]); fclose($pipes[1]);
$err = stream_get_contents($pipes[2]); fclose($pipes[2]);
$exit = proc_close($p);
} else {
$err = 'cron_run: konnte Prozess nicht starten';
}
$dur = round(microtime(true) - $t0, 2);
$status = ($exit === 124 || $exit === 137) ? 'timeout' : ((int)$exit === 0 ? 'success' : 'failed');
if ($pdo && $runId) {
try {
$pdo->prepare('UPDATE ' . $runsTbl . ' SET finished_at=?,duration=?,status=?,exit_code=?,stdout=?,stderr=? WHERE id=?')
->execute([date('Y-m-d H:i:s'), $dur, $status, $exit, mb_substr($out, 0, 200000), mb_substr($err, 0, 200000), $runId]);
$pdo->prepare('UPDATE ' . $jobsTbl . ' SET last_run_at=?,last_status=?,last_exit_code=? WHERE id=?')
->execute([$start, $status, $exit, $jobId]);
$a = $pdo->prepare('SELECT AVG(duration) FROM ' . $runsTbl . " WHERE cronjob_id=? AND status<>'running' AND duration IS NOT NULL");
$a->execute([$jobId]);
$pdo->prepare('UPDATE ' . $jobsTbl . ' SET avg_runtime=? WHERE id=?')->execute([round((float)$a->fetchColumn(), 2), $jobId]);
} catch (\Throwable $e) { /* Logging best-effort */ }
}
// echten Output + Exit durchreichen
if ($out !== '') fwrite(STDOUT, $out);
if ($err !== '') fwrite(STDERR, $err);
exit($exit === null ? 1 : (int)$exit);