Набагато легше візуалізувати речі, якщо подумати про те, що насправді відбувається з "переадресаціями" та "трубами". Перенаправлення та труби в bash роблять одне: змінюють, де дескриптори файлів процесу 0, 1 і 2 вказують на (див. / Proc / [pid] / fd / *).
Коли труба або "|" Оператор присутній у командному рядку, перше, що має відбутися, це те, що bash створює FIFO і вказує FD 1 лівої команди на цей FIFO і вказує FD 0 правої бічної команди на ту саму fifo.
Далі, оператори переадресації для кожної сторони оцінюються зліва направо , і поточні параметри використовуються, коли відбувається дублювання дескриптора. Це важливо, тому що, оскільки труба була встановлена спочатку, FD1 (ліва сторона) та FD0 (права сторона) вже змінені від того, що вони могли бути, і будь-яке дублювання цих даних відображатиме цей факт.
Тому, коли ви набираєте щось подібне:
command 2>&1 >/dev/null | grep 'something'
Ось що відбувається, щоб:
- створюється труба (фіфо). "команда FD1" вказується на цю трубу. "grep FD0" також вказується на цю трубу
- "команда FD2" вказується на те, куди в даний момент вказує "команда FD1" (труба)
- "команда FD1" вказується на / dev / null
Отже, весь вихід, який "команда" записує до свого FD 2 (stderr), пробивається до труби і читається "grep" з іншого боку. Весь вихід, який "команда" записує до свого FD 1 (stdout), пробивається до / dev / null.
Якщо замість цього, виконайте такі дії:
command >/dev/null 2>&1 | grep 'something'
Ось що відбувається:
- створюється труба і на неї вказуються "команди FD 1" і "grep FD 0"
- "команда FD 1" вказується на / dev / null
- "команда FD 2" вказується на те, де FD 1 в даний момент вказує (/ dev / null)
Отже, всі stdout та stderr з "команди" переходять до / dev / null. Нічого не йде в трубу, і, таким чином, "греп" закриється, не відображаючи нічого на екрані.
Також зауважте, що переспрямовування (дескриптори файлів) можуть бути лише для читання (<), лише для запису (>) або для читання-запису (<>).
Заключна примітка. Чи програма пише щось на FD1 чи FD2, повністю залежить від програміста. Хороша практика програмування диктує, що повідомлення про помилки повинні переходити до FD 2 і нормального виводу в FD 1, але ви часто зустрінете неохайне програмування, яке змішує два або інакше ігнорує умову.