Направьте stdout и stderr в один лог — ловушка порядка 2>&1
Задача cron должна дописывать И stdout, И stderr в run.log, но строка ниже всё равно выпускает сообщения об ошибках в терминал (и cron их шлёт письмом). Ошибка — в порядке перенаправлений.
Ограничения: оба потока должны попасть в run.log; также покажите, как отбросить stderr и как подать литеральный блок на stdin через here-doc.
myjob 2>&1 > run.log
Исправьте порядок, затем добавьте формы отбрасывания и here-doc.
Перенаправления применяются слева направо, поэтому myjob 2>&1 > run.log сначала направляет stderr туда, где сейчас stdout (в терминал), а затем уводит stdout в файл — ошибки утекают. Ставьте файл первым: myjob > run.log 2>&1. Ошибки убирают через 2>/dev/null; stdin подают here-doc'ом cmd <<'EOF' … EOF (тег в кавычках — без подстановки).
- ✗Писать
2>&1до файла, из-за чего stderr копирует терминал, а не файл - ✗Думать, что
2>&1меняет дескрипторы местами, а не дублирует один в другой - ✗Верить, что оболочка разрешает перенаправления разом, а не слева направо
- →Что делает сокращение
&>(или&>>) и почему предпочитать явную форму? - →Почему тег here-doc в кавычках
<<'EOF'отключает подстановку переменных внутри?
Решение
2>&1 — это не обмен, а дублирование: «направь fd 2 туда, куда fd 1 указывает сейчас». Перенаправления читаются слева направо, поэтому порядок решает всё.
# БАГ: сначала stderr копирует текущий stdout (терминал), потом stdout уходит в файл
myjob 2>&1 > run.log # ошибки остаются в терминале
# ВЕРНО: сначала stdout → файл, потом stderr дублирует уже перенаправленный stdout
myjob > run.log 2>&1 # оба потока в файле (для дозаписи: >> run.log 2>&1)
Отбрасывание stderr и подача литерального stdin:
myjob 2>/dev/null # ошибки в «чёрную дыру», stdout как есть
cmd <<'EOF' # here-doc; кавычки на теге = без подстановки $ и `
line one
line two
EOF
Итог: в myjob > run.log 2>&1 к моменту 2>&1 stdout уже указывает на файл, так что stderr дублируется в файл. Перестановка ломает это, потому что fd 1 в тот момент ещё указывает на терминал.