Обычно при работе с трубами и стандартным вводом у истощенной трубы нет особого значения. Новые данные могут все еще появляться, пока не будет eof который закроет канал. Ваша cat заканчивается в eof как и ожидалось. Если бы не было никаких данных до eof только тогда вы можете сказать , что STDIN был действительно пуст.
Рассмотреть sender | receiver Нередко sender (намного) медленнее, чем receiver ; в этом случае stdin receiver почти всегда истощается, но вам вряд ли захочется уничтожить всю трубу из-за этого. Поэтому инструменты, которые выходят на "пустом" (истощенном, но еще не завершенном) стандартном вводе, являются скорее исключениями, чем стандартными.
В Bash есть read -t 0 (-t не требуется для POSIX). Из help read:
Если TIMEOUT равен 0 , read возвращается немедленно, без попытки считывания каких-либо данных, возвращая успех, только если входные данные доступны в указанном файловом дескрипторе.
По умолчанию read читает из stdin, поэтому состояние выхода read -t 0 сообщит вам, является ли stdin "пустым". Но будьте осторожны! Команда как
echo 1 | read -t 0
может завершиться успешно или нет, потому что echo и read выполняются одновременно, а не последовательно. Чтобы избежать этого, ваш скрипт должен sleep , прежде чем read -t 0 . В зависимости от того, откуда приходит stdin, "время" может быть относительно долгим. Сделайте что-то вроде этого:
sleep 1
if read -t 0; then … # process stdin here, you know it's non-empty
Вы заполняете переменную данными, взятыми из стандартного ввода. Поскольку хранить двоичные данные в переменной не очень хорошая идея (прочитайте это), возможно, ваши данные - просто текст. Если это так, используйте read -t следующим образом:
read -r -t 5 -d $'\0' stdin
Нулевой символ (который вы не можете сохранить в переменной Bash в любом случае) в качестве разделителя (-d $'\0') позволит вам прочитать любой текст (например, с помощью новых строк) в переменной stdin . Через максимум 5 секунд (-t 5) команда завершается, что позволяет вашему сценарию продолжаться.
Другой подход с timeout . Базовый пример из моего Debian:
timeout --foreground 5 cat | wc -c
(Замените wc -c вашим кодом, который анализирует стандартный ввод; это всего лишь пример).
Это должно обрабатывать двоичные данные просто отлично. Если cat не получит eof то через 5 секунд она будет убита, поэтому wc все равно получит eof и линия не остановится. Проблема в том, что cat будет убита независимо от того, обрабатывает ли она какие-либо данные в данный момент. Я предполагаю, что вы хотите получить все данные, если они есть, даже если это занимает более 5 секунд. Улучшенная версия:
{ timeout --foreground 5 dd bs=1 count=1 2>/dev/null && cat; } | wc -c
Если первый байт появится в течение 5 секунд, сработает cat . Затем он будет обрабатывать любой дополнительный ввод до eof , независимо от того, сколько времени это займет. Все, включая первый байт (если есть), перейдет в wc . Если в течение 5 секунд не будет ни байта, ни eof , wc получит только eof ; линия не останавливается.