Практическое применение для перемещения дескрипторов файлов

Получение разработанных ошибок сборки предпочтительно, таким образом, я надеюсь, что это удается для Вас.

Но возможно установить альтернативные версии gcc на Fedora. Просто не от пакетов - Вам будет нужен источник, доступный из http://gcc.gnu.org/. Надейтесь загружать gcc-4.5.3.tar.gz с одного из зеркал загрузки.

Следующее смоделировано после некоторой информации Zhongliang Chen при установке gcc-4.3 на Fedora 15.

Загрузите и распакуйте gcc источник tarball. Удостоверьтесь, что Ваш Fedora 16 имеет пакеты, необходимые для создания:

yum install gcc mpfr-devel libmpc libmpc-devel glibc-devel

Затем создайте новый, пустой каталог сборки и создайте gcc с суффиксом 45 - Вы создадите компиляторы gcc45 и g++45 например. Вы могли бы хотеть новый, отдельный каталог установки как/usr/local/gcc45/

$cd PATH_TO_BUILD_DIR
$PATH_TO_SOURCE_DIR/configure --prefix=PATH_TO_INSTALL_DIR --program-suffix=45 --enable-languages=c,c++
$make
$sudo make install

16
17.02.2013, 19:56
3 ответа

3>&4- ksh93 расширение, также поддерживаемое ударом, и это коротко для 3>&4 4>&-, это равняется 3 теперь точки туда, где 4 используемых к, и 4 теперь закрываются, поэтому на что указали 4, теперь переместился в 3.

Типичное использование было бы в случаях, где Вы копировали stdin или stdout сохранить копию его и хотеть восстановить его, как в:

Предположим, что Вы хотите получить только stderr команды (и stderr) при оставлении в покое stdout в переменной.

Замена команды var=$(cmd), создает канал. Конец записи канала становится cmdstdout (дескриптор файла 1) и другой конец читается оболочкой для заполнения переменной.

Теперь, если Вы хотите stderr для движения в переменную Вы могли сделать: var=$(cmd 2>&1). Теперь и fd 1 (stdout) и 2 (stderr) переходит к каналу (и в конечном счете в переменную), который является только половиной того, что мы хотим.

Если мы делаем var=$(cmd 2>&1-) (короткий для var=$(cmd 2>&1 >&-), теперь только cmdstderr переходит к каналу, но fd 1 закрывается. Если cmd попытки записать любой вывод, который возвратился бы с a EBADF ошибка, если это открывает файл, это получит первый свободный fd, и открытому файлу присвоят это stdout если команда не принимает меры против этого! Не, что мы хотим также.

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

{
  var=$(cmd)
} 3>&1

Который является более чистым способом записать:

exec 3>&1
var=$(cmd)
exec 3>&-

(который также обладает преимуществом восстановления fd 3 вместо того, чтобы закрыть его в конце).

Затем на { (или exec 3>&1) и до }, и fd 1 и 3 точки к тому же ресурсу fd 1 указали первоначально. fd 3 также укажет на тот ресурс в замене команды (замена команды только перенаправляет fd 1, stdout). Таким образом выше, для cmd, мы имеем для fds 1, 2, 3:

  1. канал к var
  2. нетронутый
  3. то же, как какой 1 точка к внешней стороне замена команды

Если мы изменяем его на:

{
  var=$(cmd 2>&1 >&3)
} 3>&1-

Затем это становится:

  1. то же, как какой 1 точка к внешней стороне замена команды
  2. канал к var
  3. то же, как какой 1 точка к внешней стороне замена команды

Теперь, мы имеем то, что мы хотели: stderr переходит к каналу, и stdout оставляют нетронутым. Однако мы пропускаем тот fd 3 к cmd.

В то время как команды (условно) предполагают, что fds от 0 до 2 открыт и стандартным входом, производит и ошибка, они не принимают ничего другого fds. Скорее всего, они оставят тот fd 3 нетронутым. Если им будет нужен другой дескриптор файла, то они просто сделают open()/dup()/socket()... который возвратит первый доступный дескриптор файла. Если (как сценарий оболочки, который делает exec 3>&1) они должны использовать это fd а именно, они сначала присвоят его чему-то (и в том процессе, ресурс, сохраненный нашим fd 3, будет выпущен тем процессом).

Это - хорошая практика для закрытия того fd 3 с тех пор cmd не использует его, но это не грандиозное предприятие, если мы оставляем присвоенным, прежде чем мы будем звонить cmd. Проблемы могут быть: это cmd (и потенциально другие процессы, которые это порождает) имеет тот меньше fd доступный ему. Потенциально более серьезная проблема состоит в том, если ресурс, который, что fd указывает на, может закончиться сохраненный процессом, порожденным этим cmd в фоне. Это может быть беспокойство, если тот ресурс является каналом или другим каналом межпроцессного взаимодействия (как то, когда Ваш скрипт запускается как script_output=$(your-script)), поскольку это будет означать, что процесс, читающий из другого конца, никогда не будет видеть конец файла, пока тот фоновый процесс не завершится.

Таким образом, здесь, лучше записать:

{
  var=$(cmd 2>&1 >&3 3>&-)
} 3>&1

Который, с bash может быть сокращаются к:

{
  var=$(cmd 2>&1 >&3-)
} 3>&1

Для подведения причин, почему это редко используется:

  1. это нестандартно и просто синтаксический сахар. Необходимо сбалансировать сохранение нескольких нажатий клавиш с создания сценария, менее портативного и менее очевидного для людей, не привыкших к той редкой функции.
  2. Потребность закрыть исходный fd после дублирования это часто пропускается, потому что большую часть времени, мы не страдаем от последствия, таким образом, мы просто делаем >&3 вместо >&3- или >&3 3>&-.

Доказательство, что это редко используется, поскольку Вы узнали, то, что это является поддельным в ударе. В ударе compound-command 3>&4- или any-builtin 3>&4- листовой fd 4, закрытый даже после compound-command или any-builtin возвратился. Патч для устранения проблемы теперь (2013-02-19) доступен.

14
27.01.2020, 19:48
  • 1
    Спасибо, теперь я знаю, каково перемещение fd. У меня есть 4 основных вопроса относительно 2-го отрывка (и fds в целом): 1) В cmd1, Вы делаете 2 (stderr), чтобы быть копией 3, что, если команда внутренне использовала бы это 3 фарадея? 2) Почему делают 3> &1 и 4> работа &1? Дублирование 3 и 4 вступает в силу только в тех двух cmds, текущая оболочка также затронута? 3) Почему Вы закрываетесь 4 в cmd1 и 3 в cmd2? Те команды не используют упомянутый fds, не так ли? 4) В последнем отрывке, что происходит, если fd дублирован к несуществующему (в cmd1 и cmd2), я значу для 3 и 4, соответственно? –  Quentin 17.02.2013, 04:25
  • 2
    @Quentin, я использовал более простой пример и объяснил немного больше надежды, что он теперь поднимает меньше вопросов, чем он отвечает. Если Вы все еще получили вопросы, не непосредственно связанные с fd движущийся синтаксис, я предлагаю, чтобы Вы спросили отдельный вопрос –  Stéphane Chazelas 17.02.2013, 19:49
  • 3
    { var=$(cmd 2>&1 >&3) ; } 3>&1- Разве это не опечатка в закрытии 1? –  Quentin 18.02.2013, 17:50
  • 4
    @Quentin, Это - опечатка в этом, я не думаю, что намеревался включать его, однако это не имеет никакого значения начиная ни с чего в использовании фигурных скобок тот fd 1 (это был смысл дублирования его к fd 3: потому что оригинал 1 иначе не был бы доступен внутри $(...)). –  Stéphane Chazelas 18.02.2013, 18:14
  • 5
    @Quentin После ввода {...}, fd 3 указывает на то, на что раньше указывал fd 1, и fd 1 закрывается, затем после ввода $(...), fd 1 установлен на канал, который питается $var, затем для cmd 2 к этому также, и затем 1, к какой 3 точки к, который является внешним 1. То, которое 1 остается закрытым впоследствии, является ошибкой в ударе, я сообщу об этом. ksh93, куда та функция прибывает из, не имеет той ошибки. –  Stéphane Chazelas 18.02.2013, 20:30

Это означает заставлять его указать на то же место, которое делает другой дескриптор файла. Необходимо делать это очень редко кроме очевидной отдельной обработки дескриптора стандартной погрешности (stderr, fd 2, /dev/stderr -> /proc/self/fd/2). Это может прибыть удобное в некоторые сложные случаи.

Усовершенствованное Руководство по созданию сценариев Bash имеет этот более длительный пример уровня журнала и этот отрывок:

# Redirecting only stderr to a pipe.
exec 3>&1                              # Save current "value" of stdout.
ls -l 2>&1 >&3 3>&- | grep bad 3>&-    # Close fd 3 for 'grep' (but not 'ls').
#              ^^^^   ^^^^
exec 3>&-                              # Now close it for the remainder of the script.

В Исходном Колдовстве Волшебника мы, например, используем его для различения различных выводов из того же блока кода:

  (
    # everything is set, so run the actual build infrastructure
    run_build
  ) 3> >(tee -a $C_LOG >> /dev/stdout) \
    2> >(tee -a $C_LOG 1>&2 > $VOYEUR_STDERR) \
     > >(tee -a $C_LOG > $VOYEUR_STDOUT)

Этому добавили дополнительную замену процесса для входа причин (СОГЛЯДАТАЙ решает, нужно ли данные показать на экране или просто зарегистрироваться), но некоторые сообщения должны всегда представляться. Для достижения этого мы печатаем их к дескриптору файла 3 и затем обрабатываем его особенно.

4
27.01.2020, 19:48

В Unix файлы обрабатываются дескрипторами файлов (небольшие целые числа, например, стандартный вход 0, стандартный вывод равняется 1, стандартная погрешность равняется 2; поскольку Вы открываете другие файлы, которые им обычно присваивают самый маленький неиспользованный дескриптор). Таким образом, если Вы знаете внутренности программы, и Вы хотите отправить вывод, который переходит к дескриптору файла 5 к стандартному выводу, Вы переместили бы дескриптор от 5 до 1. Это то, где 2> errors прибывает из, и конструкции как 2>&1 копировать ошибки в поток вывода.

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

0
27.01.2020, 19:48
  • 1
    Но почему не к дескриптору дубликата файла 1 следующим образом: 5> &1? Я не понимаю, что проку от перемещения FD, так как ядро собирается закрыть его прямо после... –  Quentin 16.02.2013, 20:57
  • 2
    Это не копирует 5 в 1, это отправляет 5 туда, где 1 идет. И перед выяснением; да, существует несколько различных нотаций, поднятых со множества предшествующих оболочек. –  vonbrand 16.02.2013, 21:01
  • 3
    Все еще не получайте его. Если 5>&1 отправляет 5 туда, где 1 идет, затем что точно делает 1>&5- помимо закрытия 5? –  Quentin 16.02.2013, 21:23

Теги

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