Объявление stdout как stder

$ cat x
cat: x: No such file or directory
$ cat y
This is y.
$ cat x y 1> hold 2>&1
cat: x: No such file or directory
This is y.

Почему stder был перенаправлен для содержания также? stder был объявлен как stdout после перенаправления stdout в хранение и после произошедшего объявления больше нет перенаправления.

1
задан 2 January 2020 в 09:36

1 ответ

TL; DR

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

Ответ

Базовая причина, почему то, потому что 1 больше не относится к stdout когда 2>&1 читается, но к hold файл, так как перенаправления обрабатываются слева направо.

В первую очередь, помните, что все команды в среде Unix имеют стандартные потоки, на которые ссылаются через дескрипторы файлов 0 для stdin, 1 для stdout, и 2 для stderr. Существуют, конечно, редкие исключения, но 99% времен это - стандартные дескрипторы файлов.

Перенаправления такой как m>n, m>&1 и m<n выполните syscall dup2(), который делает копии дескрипторов файлов (иначе дескрипторы файлов). В m>n, m обычно дескриптор файла, и n может быть или файл или другой дескриптор файла. Это точно что 2>&1 - целочисленные ссылки на дескрипторы файлов, соответствующие stdin и stdout.

Когда cat x y 1> hold 2>&1 происходит, оболочка сначала откроется hold файл и ссылка это через следующий доступный дескриптор файла, обычно 3, и затем выполните копию того дескриптора файла через dup2(3,1). dup2() syscall отчасти похож cp команда, где Вы имеете cp old copy. Таким образом, теперь дескриптор файла 1 обращается к тому же открытому описанию файла (иначе struct file в ядре Linux) независимо от другого дескриптора файла 3.

Когда 2>&1 замечен, оболочка работает второй dup2(1,2). Таким образом, теперь дескриптор файла 2 является независимой копией дескриптора файла 1, но что это было прежде 2>&1 был замечен? 1 уже указывал на открытый файл hold. Оттуда оболочка будет работать fork и execve syscall для фактического выполнения cat как подпроцесс, который наследует открытые дескрипторы файлов.

Но насколько команды затронуты в этом случае cat, это пишет в дескрипторы файлов 1 и 2, не будучи знающим, что они - копии чего-то еще.

Вы видите все это в действии с strace команда:

# ... is several irrelevant lines skipped of bash opening libraries 
$ strace -f -edup2,openat,write bash -c 'cat testFile.txt > hold 2>&1'
...
strace: Process 17766 attached
[pid 17766] openat(AT_FDCWD, "hold", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
[pid 17766] dup2(3, 1)                  = 1
[pid 17766] dup2(1, 2)                  = 2
[pid 17766] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
[pid 17766] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
[pid 17766] openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
[pid 17766] openat(AT_FDCWD, "testFile.txt", O_RDONLY) = 3
[pid 17766] write(1, "potato\n\nNAME   MAJ:MIN RM   SIZE"..., 248) = 248
[pid 17766] +++ exited with 0 +++

Примечание стороны:

Если исходное намерение состоит в том, чтобы позволить stderr обнаружьтесь на экране, затем 2>&1 может быть удален из команды. cat x y > hold достаточно для отправки stdout в hold файл и stderr для экранирования.

Если предназначение должно отправить stderr через stdin к каналу нам будет нужно к дескрипторам файла подкачки

$ cat x y 3>&2 2>&1 2>&3 2>hold | grep --color=always file
this is a test file y
$ cat hold
cat: x: No such file or directory

Это в основном выполняет подкачку как так:

# 3>&2 open new fd 3 , save copy of fd 2 there
dup2(2, 3)                              = 3
# 2>&1 , now turn 2 into copy of 1; 2 is still safe as fd 3
dup2(1, 2)                              = 2
# 2>&3 Now let's make 2 refer to what originally was 1, but now saved in 3
dup2(3, 2)                              = 2
# open file "hold" , which will be next available integer fd
openat(AT_FDCWD, "hold", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
# 2>hold
dup2(4, 2)                              = 2
1
ответ дан 11 January 2020 в 09:45

Другие вопросы по тегам:

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