задание cron не перенаправляет вывод в файл

Это очень сложно если родительский процесс не ожидает и не сотрудничает с ним. В этом случае см. изменение среды запущенного процесса и Есть ли способ изменить переменные окружения другого процесса?

Если родительский процесс ожидает значение и сотрудничество с передачей, простой способ — использовать подстановку команд:

export VAR=$(cmd)

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

exec 3>&1       # Copy our file descriptor 1 into file descriptor 3.
                # child_prog will be invoked with file descriptor 1 pointing to a pipe
                # for the command substitution, but all other file descriptors intact.
                # Specifically, fd3 will point to our stdout.
export var=$(child_prog)
exec 3>&-       # (Optionally) close fd3 as cleanup.

Теперь, если child_progкоротко и просто, проще всего просто написать значение переменной в файловый дескриптор 1 и используйте файловый дескриптор 3(cmd >&3)в качестве стандартного вывода. Если он большой и/или сложный, вы можете сделать что-то вроде:

exec 5>&1       # Redirect fd1 (the command substitution pipe) to fd5.
exec 1>&3       # Set our fd1 (stdout) to our parent's stdout (which was passed in as fd3).
exec 3>&-       # Close fd3; it’s no longer needed.

, а затем обычно используйте стандартный вывод и используйте >&5для записи значения.

До сих пор я предполагал, что вы хотите передать только одно значение одной переменной. Если у вас есть несколько значений, достаточно просто разграничить их символом (или строкой ). это гарантированно не появится ни в одном из значений. Если мы выберем @@, то родитель может сказать

exec 3>&1
temp=$(child_prog)
exec 3>&-
export var1="${temp%%@@*}"
rest="${temp#*@@}"
export var2="${rest%%@@*}"
export var3="${rest#*@@}"

и ребенок может сказать echo "value1@@value2@@value3" >&5.

Если трудно найти строку печатных символов это гарантированно не появится ни в одном из значений, вы можете использовать новую строку. Просто измените @@на новую строку в приведенных выше командах:

Родитель:

export var1="${temp%%
*}"
rest="${temp#*
}"
export var2="${rest%%
*}"
export var3="${rest#*
}"

Ребенок:

printf "%s\n" "value1" "value2" "value3" >&5

Еще один вариант заключается в том, чтобы дочерний канал команд обратно к родителю, а не к значениям. Если родитель говорит . <(child_prog), он запускает дочерний процесс, фиксирует вывод и выполняет его . Тогда ребенок может сделать

printf "export var1='value1'\nexport var2='value2' var3=\"value3\"\n" >&5

(Я проверил это с value3, который содержал апостроф, поэтому мне пришлось процитировать его с \"…\", и я оставил его таким, чтобы проиллюстрировать альтернативный синтаксис.)

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

Этот подход требует, чтобы родительский процесс выполнял bash. (или, может быть, один из других продвинутых снарядов? ), поскольку POSIX не поддерживает <(cmd).

0
07.09.2018, 12:56
2 ответа

Знак %в crontab см. man (5 )crontab имеет особое значение (новая строка )и чтобы ваша команда работала, вам нужно их экранировать.

A "%" character in the
   command, unless escaped with a backslash (\), will be changed into
   newline characters, and all data after the first % will be sent to
   the command as standard input.

поэтому ваша команда должна быть:

* * * * * root  [[ -d /var/log/ambari-metrics-collector ]] && find /var/log/ambari-metrics-collector -type f -mtime +10 -regex '.*\.log.*[0-9]$' -printf '\%TY \%Tb \%Td \%TH:\%TM \%P\n' >> /var/log/find_old_file
3
28.01.2020, 02:16

Создать исполняемый файл оболочки

cat /root/bin/find_old_file
    #!/bin/sh
    [[ -d /var/log/ambari-metrics-collector ]] && find  /var/log/ambari-metrics-collector   -type f -mtime +10 -regex '.*\.log.*[0-9]$' -printf '%TY %Tb %Td %TH:%TM %P\n' >> /var/log/find_old_file

который вы запускаете через cron

cat /etc/cron.d/find_old_file
    * * * * * root  /root/bin/find_old_file

Если сценарий необходимо переформатировать, чтобы он соответствовал cron, часто бывает целесообразно удалить его из cron.

2
28.01.2020, 02:16

Теги

Похожие вопросы