Использовать PHP для создания, редактирования и удаления заданий crontab?

116

Можно ли использовать PHP для создания, редактирования и удаления заданий crontab?

Я знаю, как вывести список текущих заданий crontab пользователя Apache:

$output = shell_exec('crontab -l');
echo $output;

Но как добавить задание cron с PHP? 'crontab -e' просто откроет текстовый редактор, и вам придется вручную отредактировать записи перед сохранением файла.

А как удалить задание cron с PHP? Опять же, вам нужно сделать это вручную с помощью crontab -e.

С такой строкой задания:

$job = '0 */2 * * * /usr/bin/php5 /home/user1/work.php';

Как мне добавить его в список заданий crontab с помощью PHP?

datasn.io
источник
2
возможное дублирование заданий Cron с использованием php и нескольких других
Гордон
14
(подсказка) crontab - это просто файл
Гордон
1
@ Гордон, спасибо. Я знаю, что все является файлом, но хранят ли они задания crontab по одному и тому же пути в разных дистрибутивах? Плюс нужно было бы получить пользователя Apache, например www-data, и иметь привилегии root?
datasn.io
Я не уверен, изменяется ли путь в разных дистрибутивах, но вы делаете все возможное, чтобы сделать путь настраиваемым значением в вашем коде и затем установить его во время выполнения. Что касается пользователя и разрешений: у каждого пользователя может быть crontab, который запускает задания с правами, назначенными этому пользователю, так что это индивидуально для настройки вашей системы.
Гордон
Также см stackoverflow.com/q/3186471/632951
Pacerier

Ответы:

133

использование команды crontab

usage:  crontab [-u user] file
        crontab [-u user] [ -e | -l | -r ]
                (default operation is replace, per 1003.2)
        -e      (edit user's crontab)
        -l      (list user's crontab)
        -r      (delete user's crontab)
        -i      (prompt before deleting user's crontab)

Так,

$output = shell_exec('crontab -l');
file_put_contents('/tmp/crontab.txt', $output.'* * * * * NEW_CRON'.PHP_EOL);
echo exec('crontab /tmp/crontab.txt');

Вышеупомянутое может использоваться как для создания, так и для редактирования / добавления, если у пользователя есть соответствующие права на запись в файл.

Чтобы удалить задания:

echo exec('crontab -r');

Также обратите внимание, что apache работает от имени конкретного пользователя, который обычно не является пользователем root, что означает, что задания cron могут быть изменены только для пользователя apache, если пользователю apache не предоставлены crontab -uправа.

ajreal
источник
4
Разве crontab -r не удалит все задания пользователя? Есть ли способ удалить определенную строку задания в crontab пользователя? Загрузка, поиск и затем удаление найденной строки кажется единственным способом.
datasn.io
3
Вы можете использовать каналы вместо записи временного файла
realmfoo
7
Хорошее решение, но shell_exec('crontab -l')вернет только последнюю строку. Я использовал exec('crontab -l', $output). Затем сверните массив $ output в строку (с \ n в качестве клея).
Дэвид Фэрбенкс
1
@Rahul если поставщики сервера не обеспечивают оболочки команды , как system(), passthru(), shell_exec()и exec(), попробуйте с помощью панели управления , которая поставляется с хостингом, такие как CPanel или Plesk.
Raptor
3
это будет продолжать добавлять одно и то же задание каждый раз в файл. (отмечено) есть ли способ сначала удалить совпадающие вакансии, а затем написать новую?
RT
20

Недавно мы подготовили мини-проект (PHP> = 5.3) для управления файлами cron для частных и индивидуальных задач. Этот инструмент связывает файлы cron и управляет ими, чтобы вы могли использовать их, например, для каждого проекта. Доступны модульные тесты :-)

Пример из командной строки:

bin/cronman --enable /var/www/myproject/.cronfile --user www-data

Пример из API:

use php\manager\crontab\CrontabManager;

$crontab = new CrontabManager();
$crontab->enableOrUpdate('/tmp/my/crontab.txt');
$crontab->save();

Управление отдельными задачами из API:

use php\manager\crontab\CrontabManager;

$crontab = new CrontabManager();
$job = $crontab->newJob();
$job->on('* * * * *');
$job->onMinute('20-30')->doJob("echo foo");
$crontab->add($job);
$job->onMinute('35-40')->doJob("echo bar");
$crontab->add($job);
$crontab->save();

github: php-crontab-manager

Крис Сушиньски
источник
Ницца. Это, безусловно, пригодится ... при условии, что это действительно работает :)
Барака
@Pacerier, этот проект кажется мертвым и имеет некоторые проблемы. Попробуйте yzalis / crontab, который более активен.
Джефф Пакетт
10

Проверить cronjob

function cronjob_exists($command){

    $cronjob_exists=false;

    exec('crontab -l', $crontab);


    if(isset($crontab)&&is_array($crontab)){

        $crontab = array_flip($crontab);

        if(isset($crontab[$command])){

            $cronjob_exists=true;

        }

    }
    return $cronjob_exists;
}

Добавить cronjob

function append_cronjob($command){

    if(is_string($command)&&!empty($command)&&cronjob_exists($command)===FALSE){

        //add job to crontab
        exec('echo -e "`crontab -l`\n'.$command.'" | crontab -', $output);


    }

    return $output;
}

Удалить crontab

exec('crontab -r', $crontab);

пример

exec('crontab -r', $crontab);

append_cronjob('* * * * * curl -s http://localhost/cron/test1.php');

append_cronjob('* * * * * curl -s http://localhost/cron/test2.php');

append_cronjob('* * * * * curl -s http://localhost/cron/test3.php');
RafaSashi
источник
функция append_cronjob у меня не работает. Я получаю вывод '-' не существует: массив ([0] => '-' не существует. [1] => использование: файл crontab [2] => crontab [-e | -l | -r] [3] => -e (редактировать crontab пользователя) [4] => -l (выводить список crontab пользователя) [5] => -r (удалять crontab пользователя))
user1307016 05
exec ('echo -e " crontab -l\ n'. $ command. '" | crontab -', $ output); это правильно. Я не получаю crontab для www-data "-": 0: ошибки плохой минуты в файле crontab, не удается установить.
Rahul Tailwal
Crontab разделяет задания переносом строки (переводом строки). Каждое задание занимает одну строку. Следовательно, если crontab видит что-либо, кроме целого числа в первом столбце строки, он выдает ошибку «плохая минута», поскольку аргумент минуты является первым, с которым сталкивается crontab. проверить это dougv.com/2006/12/...
RafaSashi
спасибо ... как я могу использовать cron_TZ в вашем проекте ??
Салем Ахмед
5

Это должно сделать это

shell_exec("crontab -l | { cat; echo '*/1    *    *    *    *    command'; } |crontab -");
Фред
источник
5

Я попробовал решение ниже

class Crontab {

// In this class, array instead of string would be the standard input / output format.

// Legacy way to add a job:
// $output = shell_exec('(crontab -l; echo "'.$job.'") | crontab -');

static private function stringToArray($jobs = '') {
    $array = explode("\r\n", trim($jobs)); // trim() gets rid of the last \r\n
    foreach ($array as $key => $item) {
        if ($item == '') {
            unset($array[$key]);
        }
    }
    return $array;
}

static private function arrayToString($jobs = array()) {
    $string = implode("\r\n", $jobs);
    return $string;
}

static public function getJobs() {
    $output = shell_exec('crontab -l');
    return self::stringToArray($output);
}

static public function saveJobs($jobs = array()) {
    $output = shell_exec('echo "'.self::arrayToString($jobs).'" | crontab -');
    return $output; 
}

static public function doesJobExist($job = '') {
    $jobs = self::getJobs();
    if (in_array($job, $jobs)) {
        return true;
    } else {
        return false;
    }
}

static public function addJob($job = '') {
    if (self::doesJobExist($job)) {
        return false;
    } else {
        $jobs = self::getJobs();
        $jobs[] = $job;
        return self::saveJobs($jobs);
    }
}

static public function removeJob($job = '') {
    if (self::doesJobExist($job)) {
        $jobs = self::getJobs();
        unset($jobs[array_search($job, $jobs)]);
        return self::saveJobs($jobs);
    } else {
        return false;
    }
}

}

кредиты: Класс Crontab для добавления, редактирования и удаления заданий Cron

Сэм Т
источник
4

Вы можете попробовать переопределить EDITORпеременную среды чем-то вроде, edкоторое может принимать последовательность команд редактирования вместо стандартного ввода.

Альнитак
источник
3

Зависит от того, где вы храните свой crontab:

shell_exec('echo "'. $job .'" >> crontab');
thedom
источник
3

Вы можете поместить свой файл в /etc/cron.d/ в формате cron. Добавьте уникальный префикс к имени файла. Чтобы вывести список заданий cron, специфичных для скриптов, просто используйте список файлов с уникальным префиксом. Удалите файл, если хотите отключить задание.

Дмитрий Киреев
источник
Мне больше нравится это решение, потому что оно позволяет избежать манипуляций со всем файлом cron и его легко удалить, а не добавлять и удалять конкретную задачу cron в огромном файле cron.
Jovanni G
3

Хорошо ...
Попробуйте это, чтобы удалить конкретное задание cron (проверено).

<?php $output = shell_exec('crontab -l'); ?>
<?php $cron_file = "/tmp/crontab.txt"; ?>

<!-- Execute script when form is submitted -->
<?php if(isset($_POST['add_cron'])) { ?>

<!-- Add new cron job -->
<?php if(!empty($_POST['add_cron'])) { ?>
<?php file_put_contents($cron_file, $output.$_POST['add_cron'].PHP_EOL); ?>
<?php } ?>

<!-- Remove cron job -->
<?php if(!empty($_POST['remove_cron'])) { ?>
<?php $remove_cron = str_replace($_POST['remove_cron']."\n", "", $output); ?>
<?php file_put_contents($cron_file, $remove_cron.PHP_EOL); ?>
<?php } ?>

<!-- Remove all cron jobs -->
<?php if(isset($_POST['remove_all_cron'])) { ?>
<?php echo exec("crontab -r"); ?>
<?php } else { ?>
<?php echo exec("crontab $cron_file"); ?>
<?php } ?>

<!-- Reload page to get updated cron jobs -->
<?php $uri = $_SERVER['REQUEST_URI']; ?>
<?php header("Location: $uri"); ?>
<?php exit; ?>
<?php } ?>

<b>Current Cron Jobs:</b><br>
<?php echo nl2br($output); ?>

<h2>Add or Remove Cron Job</h2>
<form method="post" action="<?php $_SERVER['REQUEST_URI']; ?>">
<b>Add New Cron Job:</b><br>
<input type="text" name="add_cron" size="100" placeholder="e.g.: * * * * * /usr/local/bin/php -q /home/username/public_html/my_cron.php"><br>
<b>Remove Cron Job:</b><br>
<input type="text" name="remove_cron" size="100" placeholder="e.g.: * * * * * /usr/local/bin/php -q /home/username/public_html/my_cron.php"><br>
<input type="checkbox" name="remove_all_cron" value="1"> Remove all cron jobs?<br>
<input type="submit"><br>
</form>
Аджи Курнияван
источник
Не забудьте добавить exit;после header('Location: ...');. Кроме того, эта форма на самом деле довольно опасна, так как может добавить задание cron для «уничтожения» сервера.
Raptor
1
Примечание для новичков: на самом деле мы не заключаем каждую строку PHP в теги PHP. Один в начале PHP и, возможно, в конце будет достаточно.
ekerner 03
0

Самый простой способ - использовать команду shell_exec для выполнения сценария bash, передавая значения в качестве параметров. Оттуда вы можете управлять crontab, как и в любом другом неинтерактивном скрипте, а также убедиться, что у вас есть правильные разрешения, используя sudo и т. Д.

См. Crontab без crontab -e для получения дополнительной информации.

Codemwnci
источник
Некоторые люди могут находиться на общем хосте, поэтому это может вообще не работать.
TheRealChx101
-1

Вместо crontab вы также можете использовать очередь задач движка приложений Google . У него большая бесплатная квота, он быстрый, масштабируемый и модифицируемый.

Альфред
источник
3
Почему бы просто не использовать cronjob?
Pacerier
-1

Это просто. Вы можете сделать это curl, убедитесь, что на сервере установлен curl:

для запуска каждую минуту: * * * * * curl --request POST ' https://glassdoor.com/admin/sendBdayNotification '

        • *

    минута час день месяц неделя

Допустим, вы хотите отправлять это уведомление в 14:15 каждый день. Вы можете изменить POST / GET в зависимости от вашего API:

15 14 * * * curl --request POST 'url ur API'

Динеш Кандпал
источник