docker exec не работает в cron

У меня есть довольно простая команда, которая отлично работает как команда или скрипт bash, но не когда я помещаю ее в crontab.

40 05 * * * bash /root/scripts/direct.sh >> /root/cron.log

который имеет следующую строку

PATH=$PATH:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
SHELL=/bin/sh PATH=/bin:/sbin:/usr/bin:/usr/sbin:/root/
# Mongo Backup
docker exec -it mongodb mongodump -d meteor -o /dump/

Я попытался изменить URL-адрес скрипта на /usr/bin/scirpts/ безуспешно.

Я даже пытался запустить скрипт прямо в cron.

26 08 * * * docker exec -it mongodb mongodump -d meteor -o /dump/ >> /root/cron.log

не повезло, любая помощь приветствуется.

ИЗМЕНИТЬ

Я также не вижу ошибок в файле /root/cron.log


person user555    schedule 07.05.2016    source источник
comment
Не работает не очень полезное описание ошибки. Пожалуйста, проверьте свой системный журнал, а также добавьте к своему вопросу сообщения об ошибках и/или содержимое /root/cron.log.   -  person Erik Dannenberg    schedule 07.05.2016
comment
Не могли бы вы объяснить, какой файл содержит какой код? Я не очень понимаю, что первично и где это написано... Кстати, попробуйте записать вывод в свой пользовательский файл (вместо root/cron.log), у меня это сработало однажды   -  person I-V    schedule 21.05.2016
comment
Первый PATH= бесполезен, потому что вы перезаписываете его во второй строке.   -  person Cyrus    schedule 21.05.2016
comment
Что именно не сработало? Где вы ожидаете свалку? Я ожидаю, что он будет сохранен в каталоге /dump/, но внутри контейнера. Может быть, вы добавили этот каталог в качестве монтирования тома в контейнер mongodb?   -  person gesellix    schedule 23.05.2016
comment
Если вы достаточно заботитесь о том, чтобы опубликовать награду, вам, безусловно, также следует позаботиться о том, чтобы перенаправить stderr в файл и включить эти журналы в свой вопрос.   -  person Charles Duffy    schedule 25.05.2016
comment
... перенаправление только stdout, как вы делаете сейчас, обычно вряд ли будет полезно в отношении непредвиденных ошибок.   -  person Charles Duffy    schedule 25.05.2016


Ответы (6)


Ваша команда docker exec говорит, что ей нужен «псевдотерминал и работает в интерактивном режиме» (-it flags), в то время как cron не подключается ни к каким TTY.

Попробуйте изменить команду docker exec на это и посмотрите, сработает ли это?

docker exec mongodb mongodump -d meteor -o /dump/
person VDR    schedule 24.05.2016
comment
Вы спасатель жизни! - person ademarizu; 23.03.2017
comment
Можно оставить -t - person mfit; 03.07.2018
comment
Для тех, кто использует docker-compose, вам нужно будет добавить флаг -T, который задокументирован как: Отключить выделение псевдотерминала. По умолчанию docker-compose exec назначает TTY. - person Scott Weldon; 09.02.2019
comment
Спасибо большое... ты спас меня :D - person Omidreza Bagheri; 25.12.2019

для чего это стоит, у меня была точно такая же проблема. Исправление вашего PATH, изменение разрешений и проверка того, что вы работаете как соответствующий пользователь докера, — все это хорошо, но этого недостаточно. Это будет продолжаться с ошибкой, потому что вы используете «docker exec -it», который указывает докеру использовать интерактивную оболочку. Измените его на «docker exec -t», и он будет работать нормально. Однако нигде не будет вывода журнала, сообщающего вам об этом. Наслаждаться!

person Jason Hughes    schedule 05.09.2017
comment
Изменение docker exec -it на docker exec -t сработало для меня! - person JemoeE; 27.10.2018

отладка cron

1. /var/log or sendmail

Поскольку crond работает как демон, без возможности сбоя, выполнение важнее, чем ведение журнала. Затем по умолчанию, если что-то пойдет не так, cron отправит письмо на $USER@localhost, сообщив о выходных данных скрипта и ошибках.

Взгляните на /var/mail или /var/spool/mail для некоторых писем, может быть

и в /etc/aliases, чтобы увидеть, куда отправляется почта root.

2. Кронд и $PATH

Когда вы запускаете команду с помощью cron, следите за тем, чтобы $PATH был путем пользователя по умолчанию, а не корневым путем по умолчанию (т.е. не */sbin и другим зарезервированным путем к инструментам суперпользователя).

Для этого более простой способ — напечатать путь по умолчанию в среде, где все работает нормально:

echo $PATH

или исправьте свой скрипт из командной строки:

sed -e "2aPATH='$PATH'" -i /root/scripts/direct.sh

Это добавит текущий инициализатор $PATH в строку 2 вашего скрипта.

Или это, выбьет из вашего скрипта все остальные PATH=:

sed -e "s/PATH=[^ ]*\( \|$\)/\1/;2aPATH='$PATH'" -i /root/scripts/direct.sh

3. Принудительное ведение журнала

Добавьте вверху вашего скрипта:

exec 1>/tmp/cronlog-$$.log
exec 2>/tmp/cronlog-$$.err

Попробуй это:

sed -e '1a\\nexec 1>/tmp/cronlog-$$.log\nexec 2>/tmp/cronlog-$$.err' -i ~/scripts/direct.sh

Окончательный сценарий может выглядеть так:

#!/bin/bash

# uncomment two following lines to force log to /tmp
# exec 1>/tmp/cronlog-$$.log
# exec 2>/tmp/cronlog-$$.err

PATH='....' # copied from terminal console!

docker exec -it mongodb mongodump -d meteor -o /dump/

Исполняемый флаг

Если вы запустите свой скрипт

40 05 * * * bash /root/scripts/direct.sh

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

chmod +x ~/scripts/direct.sh

если вы хотите запустить:

40 05 * * * /root/scripts/direct.sh
person F. Hauri    schedule 25.05.2016

1) Убедитесь, что эта задача находится в crontab пользователя root — вероятно, это так, но вы не написали это явно

2) cron может не найти bash. Я бы удалил его и вызвал непосредственно ваш скрипт после того, как сделал его исполняемым:

chmod 755 /root/scripts/direct.sh

а затем установите свою запись crontab как 40 05 * * * /root/scripts/direct.sh 2>&1 >> /root/cron.log

Если это все еще не работает, то у вас должен быть какой-то полезный вывод в /root/cron.log

person mbarthelemy    schedule 07.05.2016
comment
спасибо за ответ, но оба ваших предложения почему-то не работают, и я тоже ничего не вижу в файле журнала. - person user555; 20.05.2016
comment
@ user555 хорошо, пожалуйста, добавьте вывод, который вы получаете, когда запускаете его из командной строки, в свой OP. - person SaintHax; 23.05.2016

Вы уверены, что ваш скрипт работает? Добавьте другую команду, например touch /tmp/cronok, перед вызовом docker exec.

Не забывайте, что crontab нуждается в новой строке в конце. Используйте crontab -e для редактирования.

Перезапустите службу cron и проверьте журналы (grep -i cron /var/log/syslog).

Если ваша ОС — redhat/centos/fedora, попробуйте указать имя пользователя (root) между частотой и командой.

Проверьте свою почту с помощью команды mail.

Проверьте разрешения crontab. chmod 644 /etc/crontab.

Возможно, вы просто не хотите заново изобретать колесо.

person rdupz    schedule 21.05.2016

Вот несколько вещей, которые я бы изменил — во-первых, захватить STDERR вместе с STDOUT и удалить спецификацию оболочки в cron — используйте #! вместо этого в вашем сценарии.

40 05 * * * /root/scripts/direct.sh &>> /root/cron.log

Затем вы устанавливаете свой PATH в обратном порядке, и вам не хватает вашего shbang. Я понятия не имею, почему вы определяете SHELL как /bin/sh, когда используете bash, а не dash. Измените свой сценарий на этот.

#!/usr/bin/env bash

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/root
PATH=$PATH:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
# Mongo Backup
docker exec -it mongodb mongodump -d meteor -o /dump/

Посмотрите, даст ли это что-то лучшее для работы.

person SaintHax    schedule 23.05.2016