Назад | Перейти на главную страницу

Выполнение скрипта, содержащего find, с регулярным выражением не удается в cron, но работает в оболочке

У меня в /etc/cron.d есть следующий сценарий:

19 15 * * * root /opt/scripts/clean-nexus-release-repo.sh

Скрипт clean-nexus-release-repo.sh выглядит так:

#!/bin/bash
find /opt/sonatype-work/nexus/storage/releases/se/company* -regextype posix-extended -depth -regex '.*/r?[0-9]{5,7}[a-Z0-9_.-]*\.[0-9]{1,3}' -mtime +60 -type d -print -exec rm -r {} \;
find /opt/sonatype-work/nexus/storage/releases/nu/company -regextype posix-extended -depth -regex '.*/r?[0-9]{5,7}[a-Z0-9_.-]*\.[0-9]{1,3}' -mtime +60 -type d -print -exec rm -r {} \;

Когда я запускаю сценарий clean-nexus-release-repo.sh из своей оболочки, все работает нормально. Когда он запускается через cron, я получаю следующий результат:

find: Invalid range end
find: Invalid range end

Это та же ошибка, которую я получаю, когда перемещаю дефис в [a-Z0-9_.-] регулярное выражение в недопустимую позицию. Я пробовал следующее, но все равно получаю ту же ошибку:

find --version дает:

find (GNU findutils) 4.4.2

Работает в Linux devtools01 2.6.32-71.el6.x86_64 (CentOS Linux, выпуск 6.0)

[a-Z] работает, как задумано, с языковым стандартом fr_FR.UTF-8 и, вероятно, со всеми языковыми стандартами UTF8, но не с языковым стандартом "C", как было сказано ранее.

Сценарий, запускаемый из cron, не наследует языковой стандарт, тогда как тот же сценарий, протестированный из командной строки, наследует языковой стандарт пользователя (xx_XX.UTF-8). Это объясняет различное поведение.

Я не уверен, что смогу дать здесь идеальное техническое объяснение. может кто-нибудь еще может улучшить ответ.

в основном я помню, что выражения диапазона зависят от локали, поэтому [a-Z] не обязательно означает то же, что и [a-zA-Z]

Я думаю, что соответствующая документация:

http://www.gnu.org/software/grep/manual/grep.html#index-range-expression-216:

В выражении в квадратных скобках выражение диапазона состоит из двух символов, разделенных дефисом. Он соответствует любому одиночному символу, который выполняет сортировку между двумя символами, включительно, с использованием последовательности сортировки и набора символов локали. Например, в локали C по умолчанию «[a-d]» эквивалентно «[abcd]». Многие языковые стандарты сортируют символы в словарном порядке, и в этих языковых стандартах «[a-d]» обычно не эквивалентно «[abcd]»; он может быть, например, эквивалентом «[aBbCcDd]». Чтобы получить традиционную интерпретацию выражений в квадратных скобках, вы можете использовать локаль «C», установив для переменной среды LC_ALL значение «C».

Хорошо, я думаю, что проблема обнаружена в способе определения диапазонов. a-Z означает от значения ascii «a» (97) до значения ascii «Z» (90), что означает, что диапазон заканчивается раньше, чем начинается.

Почему это работает в оболочке, я не уверен, но меняя регулярное выражение с

-regex '.*/r?[0-9]{5,7}[a-Z0-9_.-]*\.[0-9]{1,3}'

к

-regex '.*/r?[0-9]{5,7}[a-zA-Z0-9_.-]*\.[0-9]{1,3}'

работает для меня.