['enabled' => true] in config/config.php", $cli); } // Over HTTP the fetcher may hang up on its own timeout long before the work is // done; finish the slice in hand either way rather than leaving a half-written // buffer behind. set_time_limit is not honoured everywhere and nothing relies on // it — cron.max_seconds is what actually bounds the run. ignore_user_abort(true); @set_time_limit(0); // One invocation at a time. A gallery slower to archive than the cron interval // would otherwise pile invocations up behind itself. $lock = fopen(cron_lock_file(), 'c'); if ($lock === false || !flock($lock, LOCK_EX | LOCK_NB)) { if (!$quiet) { echo "already running; nothing to do\n"; } exit; } try { $run = cron_run_all(); } finally { flock($lock, LOCK_UN); fclose($lock); } json_write(cron_state_file(), [ 'last_run_at' => time(), 'duration' => round($run['duration'], 1), 'jobs' => $run['jobs'], 'remaining' => $run['remaining'], ]); if ($run['jobs'] !== [] && function_exists('manageClientLog')) { manageClientLog('INFO', 'Cron run finished', [ 'jobs' => $run['jobs'], 'duration' => round($run['duration'], 1), 'remaining' => $run['remaining'], ]); } if ($quiet) { exit; } foreach ($run['jobs'] as $line) { echo $line, "\n"; } if ($run['jobs'] === []) { echo "nothing to do\n"; } if ($run['remaining'] > 0) { // Not handed to worker.php: the next tick picks it up, and the web flow is // still a second driver. A third path would add nothing. echo $run['remaining'], " gallery(s) still queued\n"; } echo 'done in ', round($run['duration'], 1), "s\n";