Использование цикла while:
#!/bin/sh
while :; do
read -rp 'Please enter function: '
case $REPLY in
author)
echo "John"
;;
esac
done
Это будет выполняться до тех пор, пока пользователь не введет прерывающую последовательность, которую я не рекомендую. По крайней мере, я бы обеспечил возможность выхода:
#!/bin/sh
while :; do
read -rp 'Please enter function: '
case $REPLY in
author)
echo "John"
;;
exit)
break
;;
esac
done
Другим вариантом (, если доступен bash, )будет меню выбора:
#!/bin/bash
PS3='Select a function: '
select FUNC in author publisher release_date exit; do
case $FUNC in
author)
echo 'John'
;;
publisher)
echo 'Penguin'
;;
release_date)
echo '1996'
;;
exit)
break 2
;;
*)
echo 'ERROR! Unknown selection' >&2
;;
esac
done
И cat
, и strings
, и большинство подобных утилит¹ считывают ввод понемногу, обрабатывают его, затем считывают ввод и т. д. Итак, в вашем случае cat
читает только то, что отображает less
, плюс еще немного того, что находится в пути.
Более подробно, основной операцией cat
является:
Операция записи блокируется до тех пор, пока не появится место для копирования вывода. При выводе канала сам канал потребляет немного памяти в ядре, которая называется буфером канала . Когда он заполнен, если cat
пытается записать в канал, попытка записи блокируется до тех пор, пока не освободится место. В буфере канала может быть место, когда процесс на считывающем конце канала считывает некоторые данные.
Программа strings
работает так же, как cat
, за исключением того, что она не копирует весь ввод, а только выбранные части.
Программа less
работает немного по-другому :она сохраняет все, что она читает в памяти. Он не перерабатывает свой буфер, он продолжает увеличивать его до тех пор, пока поступает больше входных данных. Однако часть чтения аналогична в том, что less
считывает данные только тогда, когда они нужны :он считывает только до последняя строка, которую он отображает, плюс немного больше, что он читает в ожидании, если доступно.
Итак, когда вы запускаете sudo cat /dev/sda | strings | less
, то, что было прочитано из /dev/sda
, состоит из:
less
уже отображали (или прокручивали после ). less
прочитали, но еще не отобразили. strings
и less
.strings
. cat
и strings
. cat
. Вы можете отслеживать, когда каждая программа читает и записывает данные, отслеживая ее системные вызовы:
sudo strace -e read,write -o cat.strace cat /dev/sda | strace -e read,write -o cat.strace strings | strace -e read,write -o less.strace less
и просмотрите файлы *.strace
. Вы также можете проверить, сколько cat
прочитано, проверив смещение файла, например, с помощью lsof -p1234
или с помощью head /proc/1234/fdinfo/0
, где 1234
— идентификатор процесса cat
.
¹ Среди базовых утилит обработки текста основным исключением является sort
, которая не может выдать никаких выходных данных, пока не прочитает весь ввод :, насколько ей известно, первая строка вывода вполне может быть последней строкой ввода, которую он достигает.
Каналы имеют ограниченное пространство буфера, и если устройство чтения каналов (, такое как less
в вашем примере ), не считывает больше данных из канала, средство записи будет заблокировано после заполнения буфера. Это повлияет на команду strings
, которая, в свою очередь, заблокирует команду cat
после заполнения ее канала.
Естественно, команда cat
не может прочитать все содержимое устройства sda в основную память, поэтому, если изменяются блоки, которые еще не были прочитаны ею, cat
увидит измененное содержимое.
Это больше связано с тем, как работает less
, чем с тем, как работают cat
или strings
.
Команда cat
выводит данные только на стандартный вывод и блокируется всякий раз, когда буфер конвейера между ней и strings
заполнен и никто не читает. cat
выполняет минимальную буферизацию сам по себе, а канальный буфер обычно невелик.
Это верно и для strings
. Он будет обрабатывать данные из cat
и блокируется, когда less
не считывает данные, созданные strings
.
less
буферизует свой ввод, чтобы вы могли перемещаться вперед и назад по отображаемым данным. Когда вы переходите на следующую страницу, less
считывает дополнительные данные из strings
в свой буфер. Пока вы не прокручиваете вперед, я полагаю, что less
будет считывать только ограниченный объем данных (и, следовательно, strings
и cat
будут заблокированы, пока вы не прокручиваете вперед ).
Если вы передаете большое количество данных в less
, довольно много памяти будет использовано для этой буферизации , если вы решите прочитать все это до конца с помощью less
.
Существует параметр -B
, который ограничивает объем памяти, используемой для буферизации, до 64 килобайт (или столько, сколько вы укажете с помощью параметра -b
).Ограничение размера буфера таким образом не позволит вам прокручивать назад больше, чем может быть сохранено в указанном пространстве буфера, но также позволит вам читать огромные объемы данных с помощью less
без нехватки памяти.
См. также man less
в вашей системе.
В некоторых системах (, например. MS -Dos )канал реализован путем копирования вывода первой команды в файл, затем запуска 2-й команды для чтения из этого файла. Unix так не делает .
В Unix-системах это похоже на производственную линию. Каждый этап работает одновременно, считывая ввод и производя вывод. Если процесс A производит быстрее, чем процесс B потребляет, то между процессами A и B происходит накопление запасов. Когда это слишком много (от ½ КБ до 4 КБ ), процесс A приостанавливается. Когда для обработки B нет запаса, B приостанавливается. Процессы приостанавливаются и -не приостанавливаются, чтобы поддерживать низкий уровень запасов.
Код этих программ не заботится об этом. Он просто читает ввод и записывает вывод. Если он попытается прочитать до того, как данные будут доступны, или попытается записать до того, как следующий процесс будет готов, операционная система приостановит его до готовности.
Когда читать больше нечего (и больше ничего не находится в пути ), программа чтения получает конец -файла -и выходит. Это, в свою очередь, вызывает конец -файла -в следующем процессе.