перенаправление в / dev / null

144

Я читаю пример сценария оболочки bash:

#!/bin/bash

# This script makes a backup of my home directory.

cd /home

# This creates the archive
tar cf /var/tmp/home_franky.tar franky > /dev/null 2>&1

# First remove the old bzip2 file.  Redirect errors because this generates some if the archive
# does not exist.  Then create a new compressed file.
rm /var/tmp/home_franky.tar.bz2 2> /dev/null
bzip2 /var/tmp/home_franky.tar

# Copy the file to another host - we have ssh keys for making this work without intervention.
scp /var/tmp/home_franky.tar.bz2 bordeaux:/opt/backup/franky > /dev/null 2>&1

# Create a timestamp in a logfile.
date >> /home/franky/log/home_backup.log
echo backup succeeded >> /home/franky/log/home_backup.log

Я пытаюсь понять использование "/ dev / null 2> & 1" здесь. Сначала я подумал, что этот скрипт использует / dev / null для того, чтобы изящно игнорировать ошибки, не вызывая сбой скрипта (вроде как попытка перехватить обработку исключений в языках программирования). Потому что я не понимаю, как использование tar для сжатия каталога в файл tar может привести к любому типу ошибок.

JohnMerlino
источник
3
Перенаправление на /dev/nullне предотвратит сбой, но очистит выходные потоки stdout и stderr. tarможет вызвать ошибки различными способами. Возможно, у вас нет
прав на
3
Просто трюк, чтобы избежать ненужного вывода. Что касается того, почему tar может вызывать ошибки: потому что целевой каталог не существует, потому что источник не существует, потому что у вас нет доступа на запись к цели или чтение на источник, потому что tarнет в вашем $ PATH, потому что tarсбой (вы никогда не знаете), потому что на устройстве не осталось места, потому что tarверсия изменилась и теперь требует другого синтаксиса, потому что диск вызвал ошибку ввода-вывода. Я уверен, что вы могли бы найти больше.
Тердон

Ответы:

224

Нет, это не предотвратит сбой скрипта. Если в tarпроцессе происходят какие-либо ошибки (например, отказано в разрешении, нет такого файла или каталога, ...), скрипт все равно будет аварийно завершать работу.

Потому что использование > /dev/null 2>&1перенаправит все выходные данные вашей команды (как stdoutи stderr) /dev/null, что означает, что выходные данные не выводятся на терминал.

По умолчанию:

stdin  ==> fd 0
stdout ==> fd 1
stderr ==> fd 2

В сценарии вы используете > /dev/nullвызывающий:

stdin  ==> fd 0
stdout ==> /dev/null
stderr ==> fd 2

А потом 2>&1вызывает:

stdin  ==> fd 0
stdout ==> /dev/null
stderr ==> stdout
cuonglm
источник
3
Насколько понятно > /dev/null 2>&1, эта команда приводит к тому stderr ==> stdout, что stderr все еще печатается в stdout ??
Вейши Цзэн
11
наверное не так уж важно, но что это fd?
Кев
7
Почему: CMD > /dev/null 2>&1работает, но CMD 2>&1 > /dev/nullвсе еще дает мне STDERR?
dbmikus
3
Рекомендуется: используйте 2>& 1в примерах кода, чтобы подчеркнуть, что число и амперсанд считаются частью оператора перенаправления. Обычно для перенаправления в файл между пробелами >и пробелом /path/to/file, перенаправление в файловый дескриптор, по сути, одно и то же.
Хенк Лангевелд
21

Я пытаюсь понять использование "> / dev / null 2> & 1" здесь.

(обратите внимание, что я добавил перенаправление раньше /dev/nullв вашем вопросе.)

Выше будет перенаправить STDOUTи STDERRк /dev/null. Это работает путем слияния STDERRв STDOUT. (По существу, все выходные данные команды будут перенаправлены на нулевое устройство .)

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

Это не совсем похоже на try/catchчто-нибудь. Он просто отключает любой вывод (включая ошибку) команды.

Потому что я не понимаю, как использование tar для сжатия каталога в файл tar может привести к любому типу ошибок.

Это может привести к ошибкам по ряду причин, в том числе:

  • Недостаточные права доступа к файлу (файлам), который вы пытаетесь архивировать, или к файлу, в который вы пытаетесь записать
  • Недостаток места на диске для создания архива
devnull
источник
хорошо объяснил.
Адитья Гупта
7

Когда вы запускаете CMD> / dev / null 2> & 1

STDOUT перенаправляет на / dev / null, а затем STDERR перенаправляет на АДРЕС STDOUT, который был установлен в / dev / null, следовательно, и STDOUT, и STDERR указывают на / dev / null

И наоборот, когда вы запускаете CMD 2> & 1> / dev / null

STDERR перенаправляет на АДРЕС STDOUT (дескриптор файла 1 в тот момент или / proc / self / fd / 1), а затем STDOUT перенаправляет на / dev / null, но STDERR продолжает перенаправлять на fd1 !! В результате обычный вывод из STDOUT отбрасывается, но ошибки, поступающие из STDERR, все еще записываются на консоль.

задирать
источник
-2

Bash I / O Redirection

Основная идея прояснить это так:

Перенаправления применяются справа налево, в отличие от того, как обычно говорят на английском языке.


Итак, этот код:

command > filename 2>&1

перенаправляет stderrна stdout first ( 2>&1), а затем отправляет stdout(включая перенаправленные stderr) на filename( > filename). Вот объяснение ABSG (гл. 20) .

Этот код:

command >>/dev/null 2>&1

перенаправляет stderrи stdoutв /dev/null... что означает в никуда . Отправленные вещи /dev/nullне сохраняются, не кэшируются и не запоминаются каким-либо образом.

Их просто отправляют в « никуда » и забывают. Это способ запуска программ и проверки того, что они НЕ выдают никаких результатов и никогда не будут отображаться в командной строке или в файле журнала.


Я вижу этот тип вопросов довольно часто ... в основном потому, что мне самому пришлось его искать, так как я не программировал годами. Вот некоторая полезная информация из ABSG:

«Перенаправление просто означает захват вывода из файла, команды, программы или сценария и отправку его в качестве ввода в другой файл, команду, программу или сценарий».

2>&1 
# Redirects stderr to stdout.

command >>filename 2>&1
# Appends both stdout and stderr
#+  to the file "filename" ...

ABSG: Advanced Bash Scripting Guide: Глава 20 Ссылка выше является ссылка на страницу перенаправления ввода / вывода с открытым исходным кодом tldp.org документа под названием Advanced Bash Scripting Guide Менделем Купер. Он указан как «Углубленное исследование искусства сценариев оболочки», и я абсолютно согласен. Это потрясающий ресурс, на котором есть множество ответов на все безумные ситуации.

Другие ценные ресурсы: в текущем / поддерживаемом разделе есть много ценных ресурсов (в нескольких удобных форматах, таких как html, pdf, text и т. Д.) На странице руководств по проектам документации для Linux . Вот некоторые из них, которые я нашел полезными:

Skeptycal
источник
1
Нет, перенаправления обрабатываются слева направо. В вашем примере стандартный вывод перенаправляется в filename, а затем стандартная ошибка перенаправляется туда, куда направляется стандартный вывод (в filename). Если бы все было наоборот, стандартная ошибка заканчивалась на терминале, а перенаправлялся только стандартный вывод filename. Кроме того , в command >file1 2>file2, file2не будет создан , если file1не может быть создан (независимо от того , является ли file1и на file2самом деле были совершенно разные имена путей).
Кусалананда