Каков наилучший способ проверки записи crontab с помощью PHP? Должен ли я использовать регулярное выражение или внешнюю библиотеку? У меня есть PHP-скрипт, который добавляет/удаляет записи из файла crontab, но хочет иметь некоторый способ проверить, что часть интервала времени находится в допустимом формате.Проверка записей Crontab с PHP
ответ
Хммм, интересная проблема.
Если вы собираетесь его проверить, регулярное выражение не будет достаточным, вам нужно будет проанализировать запись и проверить каждый бит планирования. Это связано с тем, что каждый бит может быть числом, месяцем/днем недели, диапазоном (2-7), набором (3, 4, суббота), ярлыком стиля Vixie cron (60/5) или любой комбинацией из вышеперечисленного - любой подход с одним регулярным выражением будет очень волосатым, быстрым.
Просто использовать программу Vixie cron для проверки не достаточно, потому что она фактически не проверяется полностью! Я могу получить crontab
, чтобы принять всевозможные незаконные вещи.
Dick Taylor's Wicked Cool Shell Scripts (Google books link) имеет скрипт sh, который выполняет частичную валидацию, я нашел интересную дискуссию. Вы также можете использовать или адаптировать код.
Я также появился ссылки на два класса PHP, что делать то, что вы говорите (качество которых я не оценивали):
- http://www.phpclasses.org/browse/package/1189.html
- http://www.phpclasses.org/browse/package/1985.html
Другой подход (в зависимости от то, что должно делать ваше приложение) может быть, чтобы PHP построил запись crontab программно и вставлял ее, поэтому вы знаете, что она всегда действительна, а не пытается проверить ненадежную строку. Тогда вам просто нужно создать пользовательский интерфейс «build a crontab entry», который может быть простым, если вам не нужны действительно сложные комбинации планирования.
Вы должны иметь возможность сделать это довольно легко с помощью регулярного выражения. На самом деле, я бы не удивился, если бы вы могли найти существующее регулярное выражение только для Google. Это не проверено, но возможно что-то вроде:
/^((\*)|(\d+((-\d+)|(,\d+)+))\s+){5}/
Кто сказал, что регулярные выражения не могут это сделать?
Предоставлено моим работодателем, Salir.com, вот тест PHPUnit, который выполняет такую проверку. Не стесняйтесь изменять &. Буду признателен, если вы оставите уведомление @author & ссылкой на веб-сайт.
<?php
/**
* @author Jordi Salvat i Alabart - with thanks to <a href="www.salir.com">Salir.com</a>.
*/
abstract class CrontabChecker extends PHPUnit_Framework_TestCase {
protected function assertFileIsValidUserCrontab($file) {
$f= @fopen($file, 'r', 1);
$this->assertTrue($f !== false, 'Crontab file must exist');
while (($line= fgets($f)) !== false) {
$this->assertLineIsValid($line);
}
}
protected function assertLineIsValid($line) {
$regexp= $this->buildRegexp();
$this->assertTrue(preg_match("/$regexp/", $line) !== 0);
}
private function buildRegexp() {
$numbers= array(
'min'=>'[0-5]?\d',
'hour'=>'[01]?\d|2[0-3]',
'day'=>'0?[1-9]|[12]\d|3[01]',
'month'=>'[1-9]|1[012]',
'dow'=>'[0-7]'
);
foreach($numbers as $field=>$number) {
$range= "($number)(-($number)(\/\d+)?)?";
$field_re[$field]= "\*(\/\d+)?|$range(,$range)*";
}
$field_re['month'].='|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec';
$field_re['dow'].='|mon|tue|wed|thu|fri|sat|sun';
$fields_re= '('.join(')\s+(', $field_re).')';
$replacements= '@reboot|@yearly|@annually|@monthly|@weekly|@daily|@midnight|@hourly';
return '^\s*('.
'$'.
'|#'.
'|\w+\s*='.
"|$fields_re\s+\S".
"|($replacements)\s+\S".
')';
}
}
Это замечательно! В моем случае я хочу проверять полное содержание crontab по строкам. Поэтому я просто добавляю несколько проверок перед запуском вышеупомянутого решения, чтобы также проверять пустые строки, строки, начинающиеся с комментария #, и строки с присваиванием переменных «ABC = DEF» – bksunday 2017-08-13 16:53:08
Благодаря Jordi Salvat i Alabart, который опубликовал большое решение.
У меня есть только модифицированное существующее решение, отправленное Jordi Salvat i Alabart. Это сработало для меня хорошо, но я хотел извлечь определенные части, захватив группы. Я добавил не захватывающие круглые скобки, чтобы иметь возможность извлекать определенные части записи crontab.Легко видеть, которые захватывают группу использовать при тестировании вывода регулярных выражений по адресу: http://www.regexplanet.com/advanced/java/index.html
<?php
/**
* @author Jordi Salvat i Alabart - with thanks to <a href="www.salir.com">Salir.com</a>.
*/
function buildRegexp() {
$numbers = array(
'min' => '[0-5]?\d',
'hour' => '[01]?\d|2[0-3]',
'day' => '0?[1-9]|[12]\d|3[01]',
'month' => '[1-9]|1[012]',
'dow' => '[0-6]'
);
foreach ($numbers as $field => $number) {
$range = "(?:$number)(?:-(?:$number)(?:\/\d+)?)?";
$field_re[$field] = "\*(?:\/\d+)?|$range(?:,$range)*";
}
$field_re['month'].='|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec';
$field_re['dow'].='|mon|tue|wed|thu|fri|sat|sun';
$fields_re = '(' . join(')\s+(', $field_re) . ')';
$replacements = '@reboot|@yearly|@annually|@monthly|@weekly|@daily|@midnight|@hourly';
return '^\s*(' .
'$' .
'|#' .
'|\w+\s*=' .
"|$fields_re\s+" .
"|($replacements)\s+" .
')' .
'([^\\s]+)\\s+' .
'(.*)$';
}
Этот код генерирует регулярное выражение:
^\s*($|#|\w+\s*=|(\*(?:\/\d+)?|(?:[0-5]?\d)(?:-(?:[0-5]?\d)(?:\/\d+)?)?(?:,(?:[0-5]?\d)(?:-(?:[0-5]?\d)(?:\/\d+)?)?)*)\s+(\*(?:\/\d+)?|(?:[01]?\d|2[0-3])(?:-(?:[01]?\d|2[0-3])(?:\/\d+)?)?(?:,(?:[01]?\d|2[0-3])(?:-(?:[01]?\d|2[0-3])(?:\/\d+)?)?)*)\s+(\*(?:\/\d+)?|(?:0?[1-9]|[12]\d|3[01])(?:-(?:0?[1-9]|[12]\d|3[01])(?:\/\d+)?)?(?:,(?:0?[1-9]|[12]\d|3[01])(?:-(?:0?[1-9]|[12]\d|3[01])(?:\/\d+)?)?)*)\s+(\*(?:\/\d+)?|(?:[1-9]|1[012])(?:-(?:[1-9]|1[012])(?:\/\d+)?)?(?:,(?:[1-9]|1[012])(?:-(?:[1-9]|1[012])(?:\/\d+)?)?)*|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\s+(\*(?:\/\d+)?|(?:[0-6])(?:-(?:[0-6])(?:\/\d+)?)?(?:,(?:[0-6])(?:-(?:[0-6])(?:\/\d+)?)?)*|mon|tue|wed|thu|fri|sat|sun)\s+|(@reboot|@yearly|@annually|@monthly|@weekly|@daily|@midnight|@hourly)\s+)([^\s]+)\s+(.*)$
Или Java альтернатива генерировать это регулярное выражение (без @x материала):
public static String buildRegex(){
// numbers intervals and regex
Map<String, String> numbers = new HashMap<String, String>();
numbers.put("min", "[0-5]?\\d");
numbers.put("hour", "[01]?\\d|2[0-3]");
numbers.put("day", "0?[1-9]|[12]\\d|3[01]");
numbers.put("month", "[1-9]|1[012]");
numbers.put("dow", "[0-6]");
Map<String, String> field_re = new HashMap<String, String>();
// expand regex to contain different time specifiers
for(String field : numbers.keySet()){
String number = numbers.get(field);
String range = "(?:"+number+")(?:-(?:"+number+")(?:\\/\\d+)?)?";
field_re.put(field, "\\*(?:\\/\\d+)?|"+range+"(?:,"+range+")*");
}
// add string specifiers
String monthRE = field_re.get("month");
monthRE = monthRE + "|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec";
field_re.put("month", monthRE);
String dowRE = field_re.get("dow");
dowRE = dowRE + "|mon|tue|wed|thu|fri|sat|sun";
field_re.put("dow", dowRE);
StringBuilder fieldsReSB = new StringBuilder();
fieldsReSB.append("^\\s*(")
.append("$")
.append("|#")
.append("|\\w+\\s*=")
.append("|");
.append("(")
.append(field_re.get("min")).append(")\\s+(")
.append(field_re.get("hour")).append(")\\s+(")
.append(field_re.get("day")).append(")\\s+(")
.append(field_re.get("month")).append(")\\s+(")
.append(field_re.get("dow"))
.append(")")
.append("\\s+)")
.append("([^\\s]+)\\s+")
.append("(.*)$");
return fieldsReSB.toString();
}
Не знаю, сгенерированное регулярное выражение не будет соответствовать даже простым `* * * * * `. Что я делаю неправильно? https://regex101.com/r/rO2wW9/2 – bentinata 2015-03-31 08:10:14
Благодаря Jordi Salvat i Alabart и ph4r05.
У меня есть небольшое модифицированное существующее решение, размещенное на php. Альтернативой Perl для создания регулярных выражений:
sub _BuildRegex {
my $number = {
'min' => '[0-5]?\d',
'hour' => '[01]?\d|2[0-3]',
'day' => '0?[1-9]|[12]\d|3[01]',
'month' => '[1-9]|1[012]',
'dow' => '[0-6]'
};
my $field_re = {};
foreach my $nmb (qw/min hour day month dow/) {
my $range = "(?:$number->{$nmb})(?:-(?:$number->{$nmb})(?:\\/\\d+)?)?";
$field_re->{$nmb} = "\\*(?:\\/\\d+)?|$range(?:,$range)*";
}
$field_re->{'month'} .='|[jJ]an|[fF]eb|[mM]ar|[aA]pr|[mM]ay|[jJ]un|[jJ]ul|[aA]ug|[sS]ep|[oO]ct|[nN]ov|[dD]ec';
$field_re->{'dow'} .= '|[mM]on|[tT]ue|[wW]ed|[tT]hu|[fF]ri|[sS]at|[sS]un';
my $ff = [];
push @$ff, $field_re->{$_} foreach (qw/min hour day month dow/);
my $fields_req = '(' . join(')\s+(', @$ff) . ')';
my $replacements = '@reboot|@yearly|@annually|@monthly|@weekly|@daily|@midnight|@hourly';
return '^\s*(' .
'$' .
'|#' .
'|\w+\s*=' .
"|$fields_req\\s+" .
"|($replacements)\\s+" .
')' .
'([^\\s]+)\\s+' .
'(.*)$';
}
Используйте шаблон: /^((?:[1-9]?\d|\*)\s*(?:(?:[\/-][1-9]?\d)|(?:,[1-9]?\d)+)?\s*){5}$/
В PHP:
<?php
$cron = "*/5 1-2 3 3,4,5 *";
$result = preg_match("/^((?:[1-9]?\d|\*)\s*(?:(?:[\/-][1-9]?\d)|(?:,[1-9]?\d)+)?\s*){5}$/", $cron, $matches);
print_r($matches);
Существует хорошая PHP библиотека, которая может быть использована для проверки экспрессии Cron:
Чтобы установить эту библиотеку с помощью композитора:
composer require mtdowling/cron-expression
Чтобы проверить, если выражение Cron справедливо
$isValid = Cron\CronExpression::isValidExpression($expression);
- 1. Выполнение php с crontab
- 2. Проверка записей с запросом
- 3. Запуск PHP-скрипта с crontab
- 4. Вопросы Php crontab
- 5. Crontab для php
- 6. Проверка php/mysql во избежание дублирования записей
- 7. PHP генерировать crontab
- 8. Добавление нескольких записей в выходной файл с помощью crontab с использованием php?
- 9. Crontab Linux с PHP, MySQL и Curl
- 10. Безопасно ли редактировать CronTab с помощью PHP?
- 11. PHP: Список корневых crontab с sudo
- 12. PHP-классы не найдены с crontab
- 13. Запуск PHP-файла с использованием crontab
- 14. Запуск php-скриптов без crontab
- 15. Crontab тест сценариев оболочки PHP
- 16. Глобальная библиотека в Crontab PHP
- 17. Создать crontab с python-crontab в Python?
- 18. Запуск php-скрипта в crontab
- 19. Проверка на несколько повторяющихся записей
- 20. crontab с php запущен, но иногда он не заканчивается
- 21. Проверка пустых записей EditText и проверка его
- 22. Проверка 100k записей с записями базы данных
- 23. Проверка учетных записей пользователей с помощью libcurl
- 24. Проверка существующих записей с подготовленным оператором MySQLi
- 25. Проверка записей в массиве с помощью Regex
- 26. MySQL - Проверка нескольких записей с несколькими столбцами
- 27. Проверка записей в базе данных
- 28. Проблемы с crontab config
- 29. Запустить Makefile с crontab
- 30. Использование Crontab с Python
это не соответствует `@ reboot`,` @ daily`, `2- 39/4` и несколько других расширений Vixie – Jasen 2015-01-10 04:59:58