Все ленты — последние статьи

Управление Cron средствами php

Управление Cron средствами php

Для тех, кто не в курсе, cronTab, или “CronTable”, — это специальный инструмент, доступный на Linux, который облегчает планирование повторных задач, таким образом, освобождает нас от «обезьяньей работы».

В уроке мы создадим динамический класс PHP, который будет использовать безопасное подключение, и предоставит нам возможность управления cronTab!

sourse

Краткий обзор Crontab

Я думаю, никто не будет спорить с тем, что возможность автоматизировать какие-то процессы — это очень крутая и полезная вещь! Список наших возможностей стремится к бесконечности: мы можем автоматизировать поддержку базы данных SQL, отправлять электронные письма подписчикам, управлять различными задачами, анализировать работу и производительность нашего сайта, грабастать RSS ленты — cron просто великолепен!

Несмотря на то что на первый взгляд синтаксис планирования новой cron задачи может не на шутку озадачить новичка, со временем и практикой всё станет довольно-таки просто. Если коротко, то у cron задачи есть пять колонок, каждая из которых представляет хронологический 'оператор' (время запуска), и путь к самому файлу, который необходимо выполнить:


1 * * * * * home/path/to/command/the_command.sh

Как вы уже поняли, каждая из колонок представляет собой цифру (время), относящееся к той или иной задаче. Давайте рассмотрим их поподробнее:

Minutes представляют минуты данного часа, 0-59;
Hours представляют часы данного дня, 0-23;
Days представляют дни данного месяца, 1-31;
Months представляют месяцы данного года, 1-12;
Dayofweek представляет день недели, с воскресенья до субботы, в цифровой форме, как 0-6;

1 Minutes [0-59]
2 Hours [0-23]
3 Days [1-31]
4 Months [1-12]
5 Days of the Week [Numeric, 0-6]
6
7 * * * * * home/path/to/command/the_command.sh

Например, если бы кто-то хотел выполнять задачу в 0:00 в первый день каждого месяца, то это выглядело бы примерно так:
1 0 0 1 * * home/path/to/command/the_command.sh

Если бы мы хотели наметить задачу, которая бы выполнялась каждую субботу в 8:30, то мы написали бы следующий код:
1 30 8 * * 6 home/path/to/command/the_command.sh

Также существует множество операторов, которые могут использоваться для того, чтобы настроить график ещё более детально:

Запятые используются, чтобы разделять значения в любой из колонок задачи;
Тире используются, чтобы определить диапазон значений;
Звёздочка говорит о том, что нужно использовать 'все' или 'каждое' значение;

По умолчанию cronTab отправляет почтовое уведомление всякий раз, когда запланированная задача выполнена. Тем не менее, при многих обстоятельствах, это только часть того, что необходимо сделать. Мы можем легко расширить эту функциональность, переадресовывая поток данных этой команды к 'нулевому устройству' или устройству /dev/null. По сути, в нашем случае это будет файл, который отклоняет каждый идущий к нему запрос. Переадресация потока данных осуществляется с помощью оператора >. Давайте рассмотрим пример того, как мы можем переадресовать стандартный поток данных к нулевому устройству, используя cron задачу, которая будет запускаться каждую субботу в 8:30:
1 30 8 * * 6 home/path/to/command/the_command.sh >/dev/null

Вдобавок к тому, что у нас есть, если мы переадресуем поток данных к устройству, которое не существует, то наверняка нужно также переадресовать стандартные ошибки. Мы можем сделать это, просто переадресовывая их в то же место, где и должно находиться наше устройство!
1 30 8 * * 6 home/path/to/command/the_command.sh >/dev/null 2>&1
Шаг 1. Чертёж

Для того чтобы управлять cronTab при помощи PHP, мы будем нуждаться в возможности выполнять команды на удаленном сервере. К счастью, PHP предоставляет нам простой способ сделать — через библиотеку SSH2. Для тех, у кого данной библиотеки нет, придётся предпринять следующие шаги:

PHP libssh2 Установка / Конфигурация (http://www.php.net/manual/en/ssh2.installation.php)

Мы начнем наш класс с объявления четырёх приватных свойств:

$connection представляет наше подключение / ресурс;
$path представит путь для файла;
$handle представит название нашего временного cron файла;
$cron_file представляет полный путь и название временного cron файла;

Наш класс должен быть в состоянии соединиться с сервером и подтвердить подлинность пользователя, для того, чтобы только администратор мог пользоваться данной утилитой. Таким образом, мы установим связь SSH2 и подтвердим подлинность ее в пределах конструктора.

После того, как пользователь авторизуется, ему понадобится метод, который будет связан с выполнением различных команд, точнее сказать ответственным за управление задачами. Мы назовем этот метод exec (). Данный метод мы будем вызывать из других методов нашего класса, когда нам понадобится выполнить команду на удаленном сервере.

Затем, нам понадобится возможность вписать cronTab в файл — на это у нас должны быть соответствующие права. Также не нужно забывать, что мы так же должны быть в состоянии удалить этот файл, когда он нам больше не будет нужен. Итак, к нашему методу прибавляется ещё несколько файлов, таких как write_to_file () и remove_file () для добавления и удаления файлов.

Конечно, мы будем также нуждаться в возможности создавать и удалять cron задачи. Таким образом, мы определим методы append_cronjob () и remove_cronjob ().

После того, как мы удалили единственный или последний cronjob, нам понадобится возможность удалить весь cronTab вместо того, чтобы пытаться создать пустой. Для этого мы напишем метод remove_crontab (), чтобы реализовать данную функциональность.

Наконец, мы создадим два вспомогательных метода для нашего класса. Один из них будет возвращать булево значение, проверяя существование временного cron файла. Второй будет использоваться для того, чтобы показать сообщения об ошибке, если таковое возникнет в ходе работы скрипта. Мы назовем эти методы crontab_file_exists () и error_message ().
01 <?php
02
03 Class Ssh2_crontab_manager {
04
05 private $connection;
06 private $path;
07 private $handle;
08 private $cron_file;
09
10 function __construct() {…}
11
12 public function exec() {…}
13
14 public function write_to_file() {…}
15
16 public function remove_file() {…}
17
18 public function append_cronjob() {…}
19
20 public function remove_cronjob() {…}
21
22 public function remove_crontab() {…}
23
24 private function crontab_file_exists() {…}
25
26 private function error_message() {…}
27
28 }
Шаг 2. Конструктор!

Конструктор класса прежде всего будет ответственен за установление и подтверждение связи SSH2. Для этого нам потребуется четыре аргумента, у каждого из которых будет значение по умолчанию NULL:

$host: представляет IP-адрес удаленного сервера, с которым мы хотим соединиться;
$port: порт, который будет использоваться для связи SSH2;
$username: пользователь, который пытается соединиться с сервером;
$password: пароль пользователя для сервера; function __construct($host=NULL, $port=NULL, $username=NULL, $password=NULL) {…}

Первое, что нам надо определить в пределах конструктора — это свойство $this->path, которое будет хранить полный путь по умолчанию для наших временных cron файлов.

Для этого мы будем использовать волшебную константу PHP __DIR__, которая позволит нам определить путь скрипта, который мы вызываем. Однако, есть случаи, где эта константа не может быть определена, поэтому нам необходимо проверить, доступно ли нам значение из константы __DIR__.

Если значение данной константы нам недоступно, тогда путь нужно получить другим способом. Для этого мы можем воспользоваться функциями strrpos () и substr (), в которые будем передавать значение волшебной константы __FILE__, которая представит нам весь путь и название текущего файла.

Для того чтобы извлечь только путь, нам пригодится функция strrpos (), которая вернёт нам позицию слеша в значении __FILE__. Это значение, которое мы сохраним как $path_length, даст нам набор символов, не включая последний разделитель директорий.

После мы будем использовать функцию substr () для того, чтобы вырезать нужный нам фрагмент строки, а именно полный путь.

В substr () мы передадим 3 аргумента:

строку, с которой мы работаем;
начальную позицию, которая в нашем случае равна 0;
конечную позицию, которая хранится в переменной $path_length;

После выполнения данных функций у нас будет сформирован полный путь, в котором нуждается скрипт.
1 function __construct($host=NULL, $port=NULL, $username=NULL, $password=NULL)
2 {
3 $path_length = strrpos(__FILE__, "/");
4 $this->path = substr(__FILE__, 0, $path_length) . '/';
5 }

Теперь мы определим строку, которая будет присваиваться по умолчанию для временного cron файла, а затем объединим с полным путём, который вычислили раньше. Вот мы и получили то, что нам нужно.
1 function __construct($host=NULL, $port=NULL, $username=NULL, $password=NULL)
2 {
3 $path_length = strrpos(__FILE__, "/");
4 $this->path = substr(__FILE__, 0, $path_length) . '/';
5 $this->handle = 'crontab.txt';
6 $this->cron_file = "{$this->path}{$this->handle}";
7 }

После того, как мы вычислили необходимые нам значения, приступим к работе над созданием и проверкой связи с сервером. Весь этот функционал мы поместим в блок try / catch для того, чтобы иметь возможность отлавливать возникшие ошибки. В этом случае, мы можем отловить ошибки и выбросить исключение, чтобы предоставить пользователю подробную информацию о сбое.

В пределах этого блока мы сначала проверим, чтобы нам были доступны все аргументы. Для этого будем использовать функцию is_null (), которая возвращает истину или ложь. Если какой-либо из этих аргументов будет равен NULL, то мы выбросим новое исключение с соответствующим сообщением.
01 function __construct($host=NULL, $port=NULL, $username=NULL, $password=NULL)
02 {
03 $path_length = strrpos(__FILE__, "/");
04 $this->path = substr(__FILE__, 0, $path_length) . '/';
05 $this->handle = 'crontab.txt';
06 $this->cron_file = "{$this->path}{$this->handle}";
07
08 try
09 {
10 if (is_null($host) is_null($port) is_null($username) is_null($password)) throw new Exception("Please specify the host, port, username and password!");
11 }
12 catch
13 {
14
15 }
16 }

Затем, мы определим $this->connection, передав аргументы $host и $port в функцию ssh2_connect () для того, чтобы установить соединение с сервером. Данный метод возвращает false, если соединение не было установлено.

Так как мы используем нашу собственную обработку ошибок, то нам также нужно предусмотреть обработку этих сообщений. Если скрипту не удастся соединиться с сервером, то мы выбросим новое исключение с соответствующим сообщением.
01 function __construct($host=NULL, $port=NULL, $username=NULL, $password=NULL)
02 {
03 $path_length = strrpos(__FILE__, "/");
04 $this->path = substr(__FILE__, 0, $path_length) . '/';
05 $this->handle = 'crontab.txt';
06 $this->cron_file = "{$this->path}{$this->handle}";
07
08 try
09 {
10 if (is_null($host) is_null($port) is_null($username) is_null($password)) throw new Exception("Please specify the host, port, username and password!");
11
12 $this->connection = @ssh2_connect($host, $port);
13 if ( ! $this->connection) throw new Exception("The SSH2 connection could not be established.");
14 }
15 catch
16 {
17
18 }
19 }

Теперь мы попытаемся определить подлинность пользователя, используя функцию ssh2_auth_password (), в которую передадим подключение, имя пользователя и его пароль. ssh2_auth_password () также возвращает булево значение, которое характеризует результат выполнения авторизации на сервере.
01 function __construct($host=NULL, $port=NULL, $username=NULL, $password=NULL)
02 {
03 $path_length = strrpos(__FILE__, "/");
04 $this->path = substr(__FILE__, 0, $path_length) . '/';
05 $this->handle = 'crontab.txt';
06 $this->cron_file = "{$this->path}{$this->handle}";
07
08 try
09 {
10 if (is_null($host) is_null($port) is_null($username) is_null($password)) throw new Exception("Please specify the host, port, username and password!");
11
12 $this->connection = @ssh2_connect($host, $port);
13 if ( ! $this->connection) throw new Exception("The SSH2 connection could not be established.");
14
15 $authentication = @ssh2_auth_password($this->connection, $username, $password);
16 if ( ! $authentication) throw new Exception("Could not authenticate '{$username}' using password: '{$password}'.");
17 }
18 catch
19 {
20
21 }
22 }

PHP попытается найти блок catch в том случае, если возникнет какая-то ошибка во время работы скрипта, а затем создать объект исключения, который содержит много полезной информации об ошибке.

Так, в блоке catch мы будем использовать метод getMessage, для того чтобы получить и показать сообщение, определенное в исключении.

Вы, наверное, уже поняли, что мы будем показывать исключения через метод error_message (), который определим чуть позже.
01 function __construct($host=NULL, $port=NULL, $username=NULL, $password=NULL)
02 {
03 $path_length = strrpos(__FILE__, "/");
04 $this->path = substr(__FILE__, 0, $path_length) . '/';
05 $this->handle = 'crontab.txt';
06 $this->cron_file = "{$this->path}{$this->handle}";
07
08 try
09 {
10 if (is_null($host) is_null($port) is_null($username) is_null($password)) throw new Exception("Please specify the host, port, username and password!");
11
12 $this->connection = @ssh2_connect($host, $port);
13 if ( ! $this->connection) throw new Exception("The SSH2 connection could not be established.");
14
15 $authentication = @ssh2_auth_password($this->connection, $username, $password);
16 if ( ! $authentication) throw new Exception("Could not authenticate '{$username}' using password: '{$password}'.");
17 }
18 catch (Exception $e)
19 {
20 $this->error_message($e->getMessage());
21 }
22 }
Шаг 3. Выполнение множественных команд

Метод, который мы сейчас напишем, будет ответственен за выполнение команд на удаленном сервере. Это сопоставимо с ручным входом на сервер через программу PuTTY. Для того чтобы сохранить гибкую функциональность, мы сделаем методы публичными, чтобы пользователи могли выполнить любые команды, которые им необходимы для работы. Также мы сделаем возможным любое число аргументов. Эти аргументы представляют собой команды, которые будут запускаться функцией ssh2_exec ().

Итак, первая вещь, которую мы сделаем в этом методе, — это определим переменную, представляющую количество аргументов, которые передаются в метод. Мы будем использовать функцию PHP func_num_args(), для того чтобы получить это количество.
1 public function exec()
2 {
3 $argument_count = func_num_args();
4 }

Теперь, в пределах блока try, мы проверим, передают ли какие-либо аргументы в этот метод или нет. Если количество аргументов будет равно 0, то мы бросим новое исключение с соответствующим сообщением.
01 public function exec()
02 {
03 $argument_count = func_num_args();
04
05 try
06 {
07 if ( ! $argument_count) throw new Exception("There is nothing to execute, no arguments specified.");
08 }
09 catch
10 {
11
12 }
13 }

Затем, используем функцию func_get_args () для создания множества всех аргументов, которые передали в этот метод.

Используя тернарный оператор, мы определим новую переменную, $command_string, как единую строку команды в Linux, которую будем выполнять.

Если у нас действительно будут множественные команды, то мы будем использовать функцию PHP, implode(), для того чтобы разобрать множество аргументов. В функцию implode() мы передаём два аргумента: строку и разделитель. Мы отделим каждый элемент разделителем &&, который позволит нам выполнять множественные команды, последовательно, на одной линии!

Если же будет введена только одна команда, то мы определим её как $arguments [0], который будет представлять первую и единственную команду.
01 public function exec()
02 {
03 $argument_count = func_num_args();
04
05 try
06 {
07 if ( ! $argument_count) throw new Exception("There is nothing to execute, no arguments specified.");
08
09 $arguments = func_get_args();
10
11 $command_string = ($argument_count > 1) ? implode(" && ", $arguments) : $arguments[0];
12
13 }
14 catch
15 {
16
17 }
18 }

Теперь, когда все подготовительные работы завершены, мы можем попытаться выполнить их, используя функцию ssh2_exec (). Мы передадим подключение $this->connection и строку команды $command_string. После этого метод ssh2_exe() возвратит результат.

И в этом случае, мы будем использовать блок try / catch для того, чтобы иметь возможность отловить любые сообщения об ошибке. Также мы будем выбрасывать наше собственное исключение с соответствующим сообщением.
01 public function exec()
02 {
03 $argument_count = func_num_args();
04
05 try
06 {
07 if ( ! $argument_count) throw new Exception("There is nothing to execute, no arguments specified.");
08
09 $arguments = func_get_args();
10
11 $command_string = ($argument_count > 1) ? implode(" && ", $arguments) : $arguments[0];
12
13 $stream = @ssh2_exec($this->connection, $command_string);
14 if ( ! $stream) throw new Exception("Unable to execute the specified commands: {$command_string}");
15
16 }
17 catch
18 {
19
20 }
21 }

Вот именно для этого мы и написали блок try / catch! Теперь дополним это код вызовом метода error_message () для отображения ошибок!
01 public function exec()
02 {
03 $argument_count = func_num_args();
04
05 try
06 {
07 if ( ! $argument_count) throw new Exception("There is nothing to execute, no arguments specified.");
08
09 $arguments = func_get_args();
10
11 $command_string = ($argument_count > 1) ? implode(" && ", $arguments) : $arguments[0];
12
13 $stream = @ssh2_exec($this->connection, $command_string);
14 if ( ! $stream) throw new Exception("Unable to execute the specified commands: {$command_string}");
15
16 }
17 catch
18 {
19 $this->error_message($e->getMessage());
20 }
21
22 return $this;
23 }
Шаг 4. Запись cronTabв файл

Следующий метод, write_to_file (), будет ответственен за запись cronTab во временный файл или создание нового файла. Для этого нам потребуется 2 аргумента:

путь для временного файла;
имя файла, который будет создан;

С аргументами поступим точно так же, как и в нашем конструкторе, а именно — установим значения по умолчанию в NULL.
1 public function write_to_file($path=NULL, $handle=NULL)
2 {
3
4 }

Первое, что мы здесь сделаем, так это проверим при помощи метода crontab_file_exists () существует ли cron файл. Если файл действительно существует, то создавать его не нужно. Если его нет, то мы будем использовать тернарный оператор, чтобы проверить наличие значений в переменных $path и $handle. Если хотя бы один из них будет равен NULL, то мы запустим процесс, который их определит.

После этого мы сольём данные в одно целое, которое будет содержать полный путь для временного cron файла.
01 public function write_to_file($path=NULL, $handle=NULL)
02 {
03 if ( ! $this->crontab_file_exists())
04 {
05 $this->handle = (is_null($handle)) ? $this->handle : $handle;
06 $this->path = (is_null($path)) ? $this->path : $path;
07
08 $this->cron_file = "{$this->path}{$this->handle}";
09 }
10 }

Затем мы будем использовать команду Linux crontab, с-l набором аргумента. Затем, используя Linux оператор >, мы перенаправим стандартный вывод, или STDOUT, в наш временный cron файл! Перенаправление вывода к файлу, используя оператор>, создаст файл, если он не существует.
01 public function write_to_file($path=NULL, $handle=NULL)
02 {
03 if ( ! $this->crontab_file_exists())
04 {
05 $this->handle = (is_null($handle)) ? $this->handle : $handle;
06 $this->path = (is_null($path)) ? $this->path : $path;
07
08 $this->cron_file = "{$this->path}{$this->handle}";
09
10 $init_cron = "crontab -l > {$this->cron_file}";
11 }
12 }

Всё это работает очень хорошо в том случае, если у нас уже есть настроенные cronTab задачи. Если не будет никаких cron задач, то этот файл никогда не будет создаваться! Используя оператор &&, мы можем проверить несколько команд / выражений. Если файл не существует, то запустится содержание блока if.
01 public function write_to_file($path=NULL, $handle=NULL)
02 {
03 if ( ! $this->crontab_file_exists())
04 {
05 $this->handle = (is_null($handle)) ? $this->handle : $handle;
06 $this->path = (is_null($path)) ? $this->path : $path;
07
08 $this->cron_file = "{$this->path}{$this->handle}";
09
10 $init_cron = "crontab -l > {$this->cron_file} && [ -f {$this->cron_file} ] > {$this->cron_file}";
11 }
12 }

Наконец, мы вызовем метод exec () и передадим строку с командой.
01 public function write_to_file($path=NULL, $handle=NULL)
02 {
03 if ( ! $this->crontab_file_exists())
04 {
05 $this->handle = (is_null($handle)) ? $this->handle : $handle;
06 $this->path = (is_null($path)) ? $this->path : $path;
07
08 $this->cron_file = "{$this->path}{$this->handle}";
09
10 $init_cron = "crontab -l > {$this->cron_file} && [ -f {$this->cron_file} ] > {$this->cron_file}";
11
12 $this->exec($init_cron);
13 }
14
15 return $this;
16 }
Шаг 5. Удаляем временный файл

Метод remove_file () прост настолько, насколько это может быть! Тут мы воспользуемся вспомогательным методом crontab_file_exists (), чтобы проверить существование временного cron файла и затем выполним команду Linux, чтобы удалить его. Как обычно мы также возвратим $this.
1 public function remove_file()
2 {
3 if ($this->crontab_file_exists()) $this->exec("rm {$this->cron_file}");
4
5 return $this;
6 }
Шаг 6. Создание новой cron задачи

Метод, который мы сейчас напишем, будет создавать новую cron задачу. Метод append_cronjob () будет принимать один аргумент $cron_jobs, представляющий собой последовательность или множество последовательностей cron задач.

В самом начале этого метода мы проверим, является ли аргумент $cron_jobs равным NULL. Если да, то мы вызовем метод error_message(), чтобы остановить скрипт и показать пользователю сообщение об ошибке.
1 public function append_cronjob($cron_jobs=NULL)
2 {
3 if (is_null($cron_jobs)) $this->error_message("Nothing to append! Please specify a cron job or an array of cron jobs.");
4
5 }

Затем мы определим новую переменную $append_cronfile с текстом "echo", после которой стоит пробел и кавычка. Эту строку мы будем использовать для различных cron задач. Для конкатенации строк будем использовать выражение .=

Используя тернарный оператор, мы определим, содержит ли $cron_jobs множество команд. Если это будет так, то нам нужно разделить команды символом n так, чтобы каждая cron задача располагалась на своей собственной строке. Если там только одно выражение, ничего из выше перечисленного мы не делаем.

По сути, мы можем просто вывести нашу задачу в cron файл, перенаправив процесс вывода. Таким образом, используя оператор конкатенации строк, мы добавим закрывающуюся кавычку, также как и Linux оператор >>. Оператор >, в отличие от этого оператора >>, всегда переписывает файл. Оператор >> добавляет информацию в конец файла. Так при использовании этого оператора, мы не будем переписывать существующие cron задачи.
01 public function append_cronjob($cron_jobs=NULL)
02 {
03 if (is_null($cron_jobs)) $this->error_message("Nothing to append! Please specify a cron job or an array of cron jobs.");
04
05 $append_cronfile = "echo '";
06
07 $append_cronfile .= (is_array($cron_jobs)) ? implode("n", $cron_jobs) : $cron_jobs;
08
09 $append_cronfile .= "' >> {$this->cron_file}";
10
11 }

Прежде чем выполнить команду через метод exec (), сначала необходимо вызвать метод write_to_file(), чтобы создать временный cron файл. После выполнения этих двух команд, следует вызвать remove_file(), чтобы удалить временный файл.
01 public function append_cronjob($cron_jobs=NULL)
02 {
03 if (is_null($cron_jobs)) $this->error_message("Nothing to append! Please specify a cron job or an array of cron jobs.");
04
05 $append_cronfile = "echo '";
06
07 $append_cronfile .= (is_array($cron_jobs)) ? implode("n", $cron_jobs) : $cron_jobs;
08
09 $append_cronfile .= "' >> {$this->cron_file}";
10
11 $install_cron = "crontab {$this->cron_file}";
12
13 $this->write_to_file()->exec($append_cronfile, $install_cron)->remove_file();
14
15 return $this;
16 }
Шаг 7. Удаление существующих cron задач

Теперь, когда мы можем создать новые cron задачи, по логике вещей, нам необходимо иметь возможность их удалить! Метод remove_cronjob () будет принимать один аргумент, представляющий из себя регулярное выражением. Этот regEx будет использоваться для того, чтобы найти соответствие задачи в пределах cronTab и удалить их.
1 public function remove_cronjob($cron_jobs=NULL)
2 {
3 if (is_null($cron_jobs)) $this->error_message("Nothing to remove! Please specify a cron job or an array of cron jobs.");
4
5 $this->write_to_file();
6
7 }

Если cronTab не будет пуст, то тогда посчитаем элементы в $cron_array, используя функцию count(). Полученное значение сохраним в переменной $original_count.
01 public function remove_cronjob($cron_jobs=NULL)
02 {
03 if (is_null($cron_jobs)) $this->error_message("Nothing to remove! Please specify a cron job or an array of cron jobs.");
04
05 $this->write_to_file();
06
07 $cron_array = file($this->cron_file, FILE_IGNORE_NEW_LINES);
08
09 if (empty($cron_array)) $this->error_message("Nothing to remove! The cronTab is already empty.");
10
11 $original_count = count($cron_array);
12
13 }

Теперь у нас есть возможность узнать содержит ли $cron_jobs несколько значений или нет. Если да, то мы воспользуемся циклом foreach для обработки каждого значения. На каждом шаге будем использовать функцию preg_grep(). Эта изящная функция, мало чем отличается от preg_match(). В этом случае, однако, мы хотим получить элементы множества, которые не соответствуют шаблону. Таким образом, у нас будет множество всей cron работы, которой мы хотим сохранить!
01 public function remove_cronjob($cron_jobs=NULL)
02 {
03 if (is_null($cron_jobs)) $this->error_message("Nothing to remove! Please specify a cron job or an array of cron jobs.");
04
05 $this->write_to_file();
06
07 $cron_array = file($this->cron_file, FILE_IGNORE_NEW_LINES);
08
09 if (empty($cron_array)) $this->error_message("Nothing to remove! The cronTab is already empty.");
10
11 $original_count = count($cron_array);
12
13 if (is_array($cron_jobs))
14 {
15 foreach ($cron_jobs as $cron_regex) $cron_array = preg_grep($cron_regex, $cron_array, PREG_GREP_INVERT);
16 }
17 else
18 {
19
20 }
21 }

Если аргументом $cron_jobs не будет множество, то мы продолжим двигаться в почти такой же манере, но без циклов.
01 public functionremove_cronjob($cron_jobs=NULL)
02 {
03 if (is_null($cron_jobs)) $this->error_message("Nothing to remove! Please specify a cron job or an array of cron jobs.");
04
05 $this->write_to_file();
06
07 $cron_array = file($this->cron_file, FILE_IGNORE_NEW_LINES);
08
09 if (empty($cron_array)) $this->error_message("Nothing to remove! The cronTab is already empty.");
10
11 $original_count = count($cron_array);
12
13 if (is_array($cron_jobs))
14 {
15 foreach ($cron_jobs as $cron_regex) $cron_array = preg_grep($cron_regex, $cron_array, PREG_GREP_INVERT);
16 }
17 else
18 {
19 $cron_array = preg_grep($cron_jobs, $cron_array, PREG_GREP_INVERT);
20 }
21 }

Далее мы сравним значение $cron_array с $original_count. Если длины будут идентичны, то мы просто вызовем метод remove_file(), чтобы удалить временный cron файл. Если они не будут соответствовать, то мы удалим существующий cronTab, а затем создадим новый!
01 public function remove_cronjob($cron_jobs=NULL)
02 {
03 if (is_null($cron_jobs)) $this->error_message("Nothing to remove! Please specify a cron job or an array of cron jobs.");
04
05 $this->write_to_file();
06
07 $cron_array = file($this->cron_file, FILE_IGNORE_NEW_LINES);
08
09 if (empty($cron_array)) $this->error_message("Nothing to remove! The cronTab is already empty.");
10
11 $original_count = count($cron_array);
12
13 if (is_array($cron_jobs))
14 {
15 foreach ($cron_jobs as $cron_regex) $cron_array = preg_grep($cron_regex, $cron_array, PREG_GREP_INVERT);
16 }
17 else
18 {
19 $cron_array = preg_grep($cron_jobs, $cron_array, PREG_GREP_INVERT);
20 }
21
22 return ($original_count === count($cron_array)) ? $this->remove_file() : $this->remove_crontab()->append_cronjob($cron_array);
23 }
Шаг 8. Удаление cronTab

Удаление всего cronTab сделать очень просто. По существу мы только выполним команду crontab -r, которая удалит весь cronTab для данного пользователя. Так как crontab был удален, мы могли бы также удалить временный cron файл.
1 public function remove_crontab()
2 {
3 $this->exec("crontab -r")->remove_file();
4
5 return $this;
6 }
Шаг 9. Несколько вспомогательных методов

Теперь давайте рассмотрим несколько вспомогательных методов, которые мы использовали во время написания основного скрипта.
1 $this-> crontab_file_exists ()

Этот метод просто возвращает результат функции file_exists() в зависимости от того, существует ли временный cron файл.
1 private function crontab_file_exists()
2 {
3 return file_exists($this->cron_file);
4 }
5 $this-> error_message ($error)

Этот метод принимает сообщение об ошибке, которое мы хотим показать.
1 private function error_message($error)
2 {
3 die("<pre style='color:#EE2711'>ERROR: {$error}</pre>");
4 }
Шаг 10. Собираем всё в кучу

Теперь давайте посмотрим, как пользоваться созданным нами детищем:

Установка соединения

1 $crontab = new Ssh2_crontab_manager('11.11.111.111', '22', 'my_username', 'my_password');

Создание одной задачи

1 $crontab = new Ssh2_crontab_manager('11.11.111.111', '22', 'my_username', 'my_password');
2 $crontab->append_cronjob('30 8 * * 6 home/path/to/command/the_command.sh >/dev/null 2>&1');

Создание нескольких задач

1 $crontab = new Ssh2_crontab_manager('11.11.111.111', '22', 'my_username', 'my_password');
2 $new_cronjobs = array(
3 '0 0 1 * * home/path/to/command/the_command.sh',
4 '30 8 * * 6 home/path/to/command/the_command.sh >/dev/null 2>&1'
5 );
6
7 $crontab->append_cronjob($new_cronjobs);

Удаление одной задачи

1 $crontab = new Ssh2_crontab_manager('11.11.111.111', '22', 'my_username', 'my_password');
2
3 $cron_regex = '/home/path/to/command/the_command.sh/';
4
5 $crontab->remove_cronjob($cron_regex);

Удаление нескольких задач

1 $crontab = new Ssh2_crontab_manager('11.11.111.111', '22', 'my_username', 'my_password');
2
3 $cron_regex = array(
4 '/0 0 1 * */',
5 '/home/path/to/command/the_command.sh/'
6 );
7
8 $crontab->remove_cronjob($cron_regex);
Заключение

Вот и всё! Надеюсь, урок был для вас полезен, и вы сможете применить накопленные знания в ваших проектах. Удачи!

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: www.net.tutsplus.com/tutorials/php/managing-cron-jobs-with-php-2/
Перевел: Станислав Протасевич