URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 9572
[ Назад ]

Исходное сообщение
"crontab и правильное экранирование"

Отправлено mr_tee , 02-Ноя-12 13:56 
Уважаемые господа, помогите пожалуйста разобраться с экранированием в crontab.

Общий вопрос в том, что комманда (трехэтажная) прекрасно запускается и работает из командной строки, но не работает когда ее помещаю в crontab.
Как я понимаю, нужно сделать правильное экранирование символов, а вот как именно, не совсем понятно.

Вот комманда:
cd /mnt/sdb/report; ls -1 | sed '/tbz2/d; /$(date --date=6\ months\ ago +%Y%m)/,\$d' | xargs -n 1 -I {} tar cjpf {}.tbz2 {} --remove-files

ее смысл:

есть директории вида YYYYMMDD, нужно выбрать те, которые старше 6-ти месяцев и сжать tar-ом, каждую в свой файл.

ls -1          выводит в алфавитном порядке
sed            выкидываем архивы и то что новее 6-ти месяцев
date --date=6\ months\ ago +%Y%m   дает месяц 6 месяцев назад

на xargs и т.д. можно не обращать внимания

В crontab пишу так:
0 3 1 * * cd /mnt/sdb/report; ls -1 | sed '/tbz2/d; /$(date --date=6\ months\ ago +%Y%m)/,\$d' | xargs -n 1 -I {} tar cjpf {}.tbz2 {} --remove-files

получаю ошибку:
/bin/sh: -c: line 0: unexpected EOF while looking for matching `''
/bin/sh: -c: line 1: syntax error: unexpected end of file


Содержание

Сообщения в этом обсуждении
"crontab и правильное экранирование"
Отправлено erera22 , 02-Ноя-12 15:06 
Велосипед, такой велосипед...
find /mnt/sdb/report -maxdepth 1 -type d -mtime +183 | while read i ; do tar cjvf "/mnt/sdb/report/$i.tbz2" "$i" ; rm -fr "$i"; done

"crontab и правильное экранирование"
Отправлено mr_tee , 02-Ноя-12 15:12 
> Велосипед, такой велосипед...
> -mtime +183

не годится, все даты не соответствуют ничему
цепляться можно только за имя каталога


"crontab и правильное экранирование"
Отправлено ReSeT , 02-Ноя-12 17:44 
Написать скрипт, отладить, в кронтабе запускать уже скрипт.


"crontab и правильное экранирование"
Отправлено ReSeT , 02-Ноя-12 17:55 
> Написать скрипт, отладить, в кронтабе запускать уже скрипт.

Суть в том, что в командной строке у Вас скорее всего bash, а crontab, судя по логам ошибки, использует /bin/sh



"crontab и правильное экранирование"
Отправлено mr_tee , 07-Ноя-12 09:41 
>> Написать скрипт, отладить, в кронтабе запускать уже скрипт.
> Суть в том, что в командной строке у Вас скорее всего bash,
> а crontab, судя по логам ошибки, использует /bin/sh

Вы правы, поэтому для отладки я запускаю так:
/bin/sh -c "cd /mnt/sdb/report; ls -1 | sed '/tbz2/d; /$(date --date=6\ months\ ago +%Y%m)/,\$d' | xargs -n 1 -I {} echo tar cjpf {}.tbz2 {}"

И получаю такой вывод:
tar cjpf 20120401.tbz2 20120401
tar cjpf 20120402.tbz2 20120402
...
tar cjpf 20120430.tbz2 20120430

То есть все работает как надо.


"crontab и правильное экранирование"
Отправлено mr_tee , 07-Ноя-12 09:43 
> Написать скрипт, отладить, в кронтабе запускать уже скрипт.

Так тоже работает. Мой вопрос, как и какие символы правильно экранировать, чтобы это работало и из кронтаба.


"crontab и правильное экранирование"
Отправлено LSTemp , 20-Ноя-12 05:59 
>> Написать скрипт, отладить, в кронтабе запускать уже скрипт.
> Так тоже работает. Мой вопрос, как и какие символы правильно экранировать, чтобы
> это работало и из кронтаба.

$whoami
$echo $PATH
$su
..
#echo $PATH

указать полные пути к командам.



"crontab и правильное экранирование"
Отправлено erera22 , 02-Ноя-12 18:15 
>> Велосипед, такой велосипед...
>> -mtime +183
> не годится, все даты не соответствуют ничему
> цепляться можно только за имя каталога

Ну и что?
a=$(date --date=6\ months\ ago +%Y%m)00 ; cd /mnt/sdb/report; ls | while read i; do if [ "$i" -lt "$a" ]; then tar cjvf "$i.tbz2" "$i"; rm -fr "$i"; done


"crontab и правильное экранирование"
Отправлено mr_tee , 07-Ноя-12 09:38 
>>> Велосипед, такой велосипед...
>>> -mtime +183
>> не годится, все даты не соответствуют ничему
>> цепляться можно только за имя каталога
> Ну и что?
> a=$(date --date=6\ months\ ago +%Y%m)00 ; cd /mnt/sdb/report; ls | while read
> i; do if [ "$i" -lt "$a" ]; then tar cjvf
> "$i.tbz2" "$i"; rm -fr "$i"; done

То же самое, ошибка:
/bin/sh: -c: line 0: unexpected EOF while looking for matching `)'
/bin/sh: -c: line 1: syntax error: unexpected end of file

Вашу строку я даже руками не могу запустить, так как она содержит кавычки:
/bin/sh -c "комманда"


"crontab и правильное экранирование"
Отправлено mr_tee , 21-Ноя-12 11:59 
> Уважаемые господа, помогите пожалуйста разобраться с экранированием в crontab.
> Общий вопрос в том, что комманда (трехэтажная) прекрасно запускается и работает из
> командной строки, но не работает когда ее помещаю в crontab.
> Как я понимаю, нужно сделать правильное экранирование символов, а вот как именно,
> не совсем понятно.
> есть директории вида YYYYMMDD, нужно выбрать те, которые старше 6-ти месяцев и
> сжать tar-ом, каждую в свой файл.

Итак, результаты изысканий:
1. crontab не пропускает конструкции `команда` и $(команда)
2. не нравится символ + в параметрах команды date

Работающий итог следующий:

cd /mnt/sdb/report; (/bin/date --date=6\ months\ ago -I | sed 's/-//; s/-.*$/!!/'; ls -1 | sed -n '/^[0-9]\{8\}$/p') | sort | sed '/!!/,$d' | xargs -n 1 -I {} tar cjpf {}.tbz2 {} --remove-files

Краткое пояснение (для себя ;-))

Дает дату 6 месяцев назад в виде YYYYMM!!
/bin/date --date=6\ months\ ago -I | sed 's/-//; s/-.*$/!!/'

Список всего вида YYYYMMDD, у меня это каталоги. Специально сделал так, чтобы ничего лишнего случайно не обработалось, мало ли что там появится в будущем.
ls -1 | sed -n '/^[0-9]\{8\}$/p'

После сортировки этого строка YYYYMM!! оказывается между списком того, что старее 6-ти месяцев и тем, что новее, соответственно удаляем из списка все от этой строки до конца:
sed '/!!/,$d'

Ну а дальше - дело техники: на входе список на выходе архивы:
xargs -n 1 -I {} tar cjpf {}.tbz2 {} --remove-files

Всем спасибо за участие)


"crontab и правильное экранирование"
Отправлено LSTemp , 22-Ноя-12 05:19 
>> Уважаемые господа, помогите пожалуйста разобраться с экранированием в crontab.
>> Общий вопрос в том, что комманда (трехэтажная) прекрасно запускается и работает из
>> командной строки, но не работает когда ее помещаю в crontab.
>> Как я понимаю, нужно сделать правильное экранирование символов, а вот как именно,
>> не совсем понятно.
>> есть директории вида YYYYMMDD, нужно выбрать те, которые старше 6-ти месяцев и
>> сжать tar-ом, каждую в свой файл.
> Итак, результаты изысканий:
> 1. crontab не пропускает конструкции `команда` и $(команда)

а должен? задайте себе вопрос под каким шелом крон работает и под каким Вы тестировали скрипт.

> 2. не нравится символ + в параметрах команды date

экранировать в соответсвии с праилами шела, который использует крон.

>[оверквотинг удален]
> ничего лишнего случайно не обработалось, мало ли что там появится в
> будущем.
> ls -1 | sed -n '/^[0-9]\{8\}$/p'
> После сортировки этого строка YYYYMM!! оказывается между списком того, что старее 6-ти
> месяцев и тем, что новее, соответственно удаляем из списка все от
> этой строки до конца:
> sed '/!!/,$d'
> Ну а дальше - дело техники: на входе список на выходе архивы:
> xargs -n 1 -I {} tar cjpf {}.tbz2 {} --remove-files
> Всем спасибо за участие)


"crontab и правильное экранирование"
Отправлено mr_tee , 27-Ноя-12 13:22 

>> 1. crontab не пропускает конструкции `команда` и $(команда)
> а должен? задайте себе вопрос под каким шелом крон работает и под
> каким Вы тестировали скрипт.
>> 2. не нравится символ + в параметрах команды date
> экранировать в соответсвии с праилами шела, который использует крон.

Вы все правильно говорите, буду очень признателен, если вы сможете написать мне правильно экранированную сроку для crontab хотя бы одной из этих команд (или всех, если у вас это получится):

my_date=`date`

my_date=$(date)

date +%Y%m


"crontab и правильное экранирование"
Отправлено LSTemp , 29-Ноя-12 00:58 
>[оверквотинг удален]
>> а должен? задайте себе вопрос под каким шелом крон работает и под
>> каким Вы тестировали скрипт.
>>> 2. не нравится символ + в параметрах команды date
>> экранировать в соответсвии с праилами шела, который использует крон.
> Вы все правильно говорите, буду очень признателен, если вы сможете написать мне
> правильно экранированную сроку для crontab хотя бы одной из этих команд
> (или всех, если у вас это получится):
> my_date=`date`
> my_date=$(date)
> date +%Y%m

1)
[root@local ~]# whereis date
date: /bin/date

my_date=`/bin/date`
my_date=$(/bin/date)
/bin/date +%Y%m

Читайте то, что Вам выше писали про пути. Я уже пытался показать Вам, что для разных пользователей $PATH отличется. У crona PATH по умолчанию (как правило) просто нет.

2)
По умолчанию cron пускает скрипты под оболочкой sh, но что у Вас за система и что там накручено - бог знает - инфы нет. Под sh из командной строки Вы проверяли. Значит дело в п.1 или в том, что используется другой шелл - вопрос какой (для того чтобы с экранированием и прочим разобраться).

3)
если файловая система с bash-ем (или другой любимой Вами оболочкой) на момент запуска команды гарантировано доступна, то никто не мешает явно указать /bin/bash в качестве шела для кроновской команды (так же как Вы при тесте использовали /bin/sh)

PS
покажите уже наверно cat /etc/crontab, чтобы не пригодилось на кофейной гуще гадать.


"crontab и правильное экранирование"
Отправлено Аноним , 29-Ноя-12 08:37 
> [root@local ~]# whereis date

очень правильно, для крона - только так.

> my_date=`/bin/date`

правильно и кроссплатформенно (гы - православно!).

> my_date=$(/bin/date)

только под линуксы ну и где ещё sh=bash

> /bin/date +%Y%m

неправильно, правильно /bin/date '+%Y%m'


"crontab и правильное экранирование"
Отправлено LSTemp , 29-Ноя-12 10:08 
>> [root@local ~]# whereis date
> очень правильно, для крона - только так.
>> my_date=`/bin/date`
> правильно и кроссплатформенно (гы - православно!).
>> my_date=$(/bin/date)
> только под линуксы ну и где ещё sh=bash
>> /bin/date +%Y%m
> неправильно, правильно /bin/date '+%Y%m'

похрену сама команда и ее синтаксис в этом конкретном случае - суть в том, что путь к ней полностью прописать надо.