Чи означає 3> & 1 4> & 3 5> & 3 тощо?


31

Я очікував

echo foo | tee /proc/self/fd/{3..6} 3>&1

до помилок, таких як / proc / self / fd / 4: Немає такого файлу чи каталогу тощо, але, на мій подив, він виводить

foo
foo
foo
foo
foo

Це як би 3>&1спричиняє перенаправлення всіх наступних дескрипторів на stdout, за винятком того, що він не працює, якщо я переходжу 3на щось інше, наприклад

$ echo foo | tee /proc/self/fd/{3..6} 4>&1
tee: /proc/self/fd/3: No such file or directory
tee: /proc/self/fd/5: No such file or directory
tee: /proc/self/fd/6: No such file or directory
foo
foo
$ echo foo | tee /proc/self/fd/{4..6} 4>&1
tee: /proc/self/fd/5: No such file or directory
tee: /proc/self/fd/6: No such file or directory
foo
foo

Чи є пояснення такої поведінки?

Відповіді:


31

strace показує цю послідовність системних викликів:

$ strace -o strace.log tee /proc/self/fd/{3..6} 3>&1
...
$ cat strace.log
...
openat(AT_FDCWD, "/proc/self/fd/3", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
openat(AT_FDCWD, "/proc/self/fd/4", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 5
openat(AT_FDCWD, "/proc/self/fd/5", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 6
openat(AT_FDCWD, "/proc/self/fd/6", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 7
...

Перший рядок відкривається /proc/self/fd/3і присвоює йому наступний доступний номер fd, 4. /proc/self/fd/3це спеціальний шлях. Відкриваючи це, ефект, подібний до копіювання fd 3: fd 4 вказує на те саме місце, що і fd 3, tty.

Те ж саме відбувається і для кожного наступного openat()дзвінка. Коли пил осідає fds 4, 5, 6 і 7, всі дублікати fd 3.

  • 1 → тти
  • 3 → тти
  • 4 → тти
  • 5 → тти
  • 6 → тти
  • 7 → тти

Зауважте, що 3>&1перенаправлення не важливо. Важливо те, що ми просимо трійника відкрити /proc/self/fd/Nтам, де N вже використовується. Ми повинні отримати той самий результат, якщо ми позбудемося 3>&1і /proc/self/fd/2натомість матимемо трійник . Подивимось:

$ echo foo | tee /proc/self/fd/{2..6}
foo
foo
foo
foo
foo
foo

Підтверджено! Той самий результат.

Ми також можемо повторювати одне і те ж число fd знову і знову. Ми отримуємо такий же результат, коли потрапляємо на fd 6. До того моменту, коли він досягне останнього, він відкрив достатньо дескрипторів, щоб зробити стрибок до 6 можливим.

$ echo foo | tee /proc/self/fd/{2,2,2,2,6}
foo
foo
foo
foo
foo
foo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.