Скрипт Bash с неблокирующим чтением - PullRequest
8 голосов
/ 02 февраля 2011

Я хочу отправить некоторые данные корневому процессу с именованным каналом. Вот скрипт, и он прекрасно работает:

#!/bin/sh
pipe=/tmp/ntp

if [[ ! -p $pipe ]]; then
    mknod -m 666 $pipe p
fi

while true
do
    if read line <$pipe; then
         /root/netman/extra/bin/ntpclient -s -h $line > $pipe 2>&1
    fi
done

У меня на самом деле есть несколько таких скриптов. Я хотел бы заключить их все в один сценарий. Проблема в том, что блоки выполнения выполняются при первом «чтении», и я не могу выполнить несколько «чтений» в одном процессе. Я ничего не могу сделать? Возможно ли иметь «неблокирующее» чтение bash?

Ответы [ 3 ]

18 голосов
/ 02 февраля 2011

Встроенная команда чтения Bash имеет параметр -t для установки времени ожидания:

-t timeout
    Cause read to time out and return failure if a complete line of input is not
    read within timeout seconds. This option has no effect if read is not reading
    input from the terminal or a pipe.

Это должно помочь вам решить эту проблему.

Edit:

Существуют некоторые ограничения для этого решения для работы, как указывает справочная страница: Этот параметр не действует, если чтение не считывает ввод с терминала или канала.

Так что, если я создам трубу в / tmp:

mknod /tmp/pipe p

Чтение напрямую из трубы не работает:

$ read -t 1 </tmp/pipe  ; echo $?

Висит навсегда.

$ cat /tmp/pipe | ( read -t 1 ; echo $? )
1

Работает, но кот не выходит.

Решение состоит в том, чтобы назначить канал дескриптору файла:

$ exec 7<>/tmp/pipe

А затем читать из этого файлового дескриптора либо с помощью перенаправления:

$ read -t 1 <&7  ; echo $?
1

или -u опция read:

$ read -t 1 -u 7  ; echo $?
1
3 голосов
/ 02 февраля 2011

Просто поместите цикл чтения в фоновый режим (добавить и после того, как сделано)?

0 голосов
/ 02 февраля 2011

Вы можете использовать stty для установки времени ожидания. IIRC это что-то вроде

stty -F $pipe -icanon time 0
...