Почему мой скрипт crontab не работает?

Почему мой скрипт crontab не работает?

Я пытаюсь запустить скрипт, хранящийся в моем домашнем каталоге, через crontab, но он не работает. Журнал CRON просто говорит это каждый раз, когда он запускается:

Sep  3 18:30:01 backup CRON[6778]: (root) CMD (/home/hannes/script > /tmp/yc.log)
Sep  3 18:30:01 backup CRON[6777]: (CRON) info (No MTA installed, discarding output)

Кронтаб:

*/1 * * * * /home/hannes/script > /tmp/yc.log

Если я попробую добавить расширение файла .sh, это ничего не изменит. Файл yc.log останется пустым.

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

#!/bin/sh
cp -r -p mnt/main-nas/PATH-TO-FILE mnt/backup-nas/01/temp/server
zip -r mnt/backup-nas/01/1.19_Test.`date +%d.%m.%Y_%H.%M.%S`.zip mnt/backup-nas/01/temp/server
rm -r mnt/backup-nas/01/temp/server

Любая помощь приветствуется! :)

решение1

Ваш сценарийявляетсяна самом деле работает... но где-то выдает ошибку. И поскольку вы не захватываете stderrвывод, stderr отправляется cronпользователю, который запускает скрипт локально. (И тоже падает)

Основная причина в следующем: ваш скрипт перенаправляет только stdoutв файлы. Однако множество неудачных скриптов и программ используют stderrдля вывода сообщений об ошибках. Вам нужно отловить это, добавив 2>&1в конец вашей командной строки, которая cronвыполняется, что также будет захватывать stderrи регистрировать ошибки в вашем файле.

Поскольку вы не перехватывали его ранее, stderr доставлялся по почте root, но поскольку у вас нет локального MTA (Mail Transfer Agent, он же сервер Local Mail Transport Protocol (LMTP)) для локальной доставки, вы получили эти ошибки cron. С перехватом stderrвы теперь увидите ошибки и то, почему ваш скрипт(ы) не запустился(лись) должным образом.

После того, как в ваших журналах появятся сообщения об ошибках, вы можете продолжить отладку скрипта, чтобы определить, что нужно сделать, чтобы «исправить» ситуацию.

решение2

Итак, было несколько проблем. Во-первых, я забыл добавить 2>&1конец /home/hannes/script > /tmp/yc.log, чтобы журнал действительно сохранился. А во-вторых, у меня была опечатка в скрипте, где я забыл первый слеш во всех путях. Это перешло от этого home/hannes/...к этому /home/hannes/.... Надеюсь, это поможет другим людям, у которых возникла похожая проблема, и спасибо всем, кто ответил :)

решение3

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


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

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

Первый подход намного проще, вы можете просто добавить дату в каталог, который вы используете. Это будет выглядеть примерно так (обратите внимание, что это также гарантирует, что вызов dateбудет выполнен только один раз):

#!/bin/sh
now="$(date +%d.%m.%Y_%H.%M.%S)"
cp -r -p mnt/main-nas/PATH-TO-FILE mnt/backup-nas/01/temp/server/${now}
zip -r mnt/backup-nas/01/1.19_Test.${now}.zip mnt/backup-nas/01/temp/server/${now}
rm -r mnt/backup-nas/01/temp/server/${now}

Подход с блокировкой файлов немного сложнее, но, возможно, чище, поскольку он также гарантирует, что вы не сможете случайно завалить систему несколькими zipкомандами, запущенными одновременно. Это включает в себя использование команды под названием flock(часть пакета util-linuxв Ubuntu и Debian, который уже будет установлен), и выглядит примерно так (с комментариями, поясняющими, что происходит):

#!/bin/sh
# All of this gets run in a subshell so we can hold a file descriptor open
# for all the commands. We're using file descriptor 9 here, but any number
# higher than 2 will work.
(
    # This flock command is what actually takes the lock. The lock itself 
    # persists until the file descriptor is closed when the subshell exits.
    # The -x means it's an exclusive lock (so only one instance can hold it).
    # The -w says to try for that many seconds before failing if something
    # else is holding the lock (this is an important safety net to ensure you
    # don’t get a long queue of these scripts waiting to run).
    # The -n indicates which file descriptor to take the lock on.
    flock -x -w 30 -n 9 || exit 1
    cp -r -p mnt/main-nas/PATH-TO-FILE mnt/backup-nas/01/temp/server
    zip -r mnt/backup-nas/01/1.19_Test.`date +%d.%m.%Y_%H.%M.%S`.zip mnt/backup-nas/01/temp/server
    rm -r mnt/backup-nas/01/temp/server
# And this line closes the subshell, and also sets the path to be used for
# the lock file by opening it as file descriptor 9 for the subshell. /run
# is generally the place you want to put stuff like this, because it will
# get cleaned up automatically every time the system reboots.
) 9> /run/backup-nas.lock

Связанный контент