Если вам нужна только первая или две строки, уловка следующего типа работает и позволяет избежать проблем с буферизацией, вызванных использованием двух разных команд для чтения выходного потока:
$ ps -eF | { IFS= read -r x ; echo "$x" ; grep worker; }
$ ls -la / | { IFS= read -r x ; echo "$x" ; grep sbin; }
Он read
встроен в оболочку и не использует весь буфер ввода только для вывода одной строки, поэтому использование read
оставляет все остальные выходные данные для следующей команды.
Если вы хотите подчеркнуть проблемы буферизации, показанные в ваших примерах, в которых используются две разные команды, добавьте sleep
к ним a, чтобы устранить проблемы с синхронизацией, и разрешите команде слева сгенерировать все свои выходные данные, прежде чем команды справа попытаются прочитать любую из Это:
$ ps -eF | { sleep 5 ; head -n 1 ; grep worker; }
$ ls -la / | { sleep 5 ; head -n 1 ; grep sbin; }
Теперь оба приведенных выше примера завершаются сбоем одинаково - head
чтение всего буфера вывода производится только для создания одной строки, и этот буфер недоступен для следующего grep
.
Вы можете увидеть проблему буферизации еще яснее, используя несколько примеров, которые нумеруют выходные строки, чтобы вы могли определить, какие строки отсутствуют:
$ ps -eF | cat -n | { sleep 5 ; head -n 1 ; head ; }
$ ls -la /usr/bin | cat -n | { sleep 5 ; head -n 1 ; head ; }
Простой способ увидеть проблему буферизации - использовать seq
список, который генерирует список. Мы можем легко определить, какие цифры пропали без вести:
$ seq 1 100000 | { sleep 5 ; head -n 1 ; head ; }
1
1861
1862
1863
1864
1865
1866
1867
1868
1869
Мое хитрое решение, использующее оболочку для чтения и вывода первой строки, работает правильно даже с добавленной задержкой сна:
$ seq 1 100000 | { sleep 5 ; IFS= read -r x ; echo "$x" ; head ; }
1
2
3
4
5
6
7
8
9
10
11
Ниже приведен полный пример, показывающий head
проблемы с буферизацией, показывающий, как
head
расходуется весь буфер вывода только для того, чтобы каждый раз создавать его пять строк. Этот использованный буфер недоступен для следующей
head
команды в последовательности:
$ seq 1 100000 | { sleep 5 ; head -5 ; head -5 ; head -5 ; head -5 ; }
1
2
3
4
5
1861
1862
1863
1864
499
3500
3501
3502
3503
7
5138
5139
5140
5141
Глядя на число 1861
выше, мы можем вычислить размер используемого буфера, head
посчитав seq
выходные данные от 1
до
1860
:
$ seq 1 1860 | wc -c
8193
Мы видим, что head
буферизация происходит за счет считывания целых 8 КБ (8 * 1024 байт) выходного потока канала за раз, даже для получения только нескольких строк собственного вывода.
head
иgrep
там ничего не делать.