Процесс замещения сломан трубой

Я сделал глупость сегодня:

read x <( ps -fu $LOGNAME | grep ' /usr/bin/ps$' )

Он висел, никогда не вернулся. Я должен был сломать это.

Некоторые из вас совершенно справедливо смеются надо мной прямо сейчас.:)

Мне потребовалась всего минута, чтобы понять, почему это не работает, но я хотел опубликовать его как вопрос (на который я также кратко отвечу ниже, но не стесняйтесь) на тот случай, если это кого-то поставит в тупик.

2 ответа

Решение

Если вы замените read x с catсколько времени займет бег?

Проблема в том, что вы выполнили такую ​​команду:

read x /dev/fd/63

(как вы могли видеть, запустив echo read x <(…)) и read сидел там и ждал, пока ты напишешь что-то, чтобы положить в x,

$ read x <( ps -fu $LOGNAME | grep ' /usr/bin/ps$' )
asc def
-bash: read: `/dev/fd/63': not a valid identifier
$

Оболочка ждала, чтобы вы что-то набрали, вот и все. Вы нетерпеливы.

Если вы хотите перенаправить ввод в read commnd, вам нужен отдельный < чтобы сделать это (мне нужно было изменить grep регулярное выражение, чтобы получить любой вывод):

$ read x < <( ps -fu $LOGNAME | grep ' /usr/bin/ps' )
$ echo $x
501 16166 16164 0 7:50AM ttys000 0:00.00 grep /usr/bin/ps
$

Обратите внимание, что с прямым перенаправлением, как показано в последнем read команда, только первая строка ввода из процесса подстановки будет прочитана; остальное будет потеряно. Если вам нужно обработать несколько строк в while цикл, вам нужно перенаправить весь цикл:

while read x
do
    whatever -with "$x"
done < <(ps -fu $LOGNAME | grep ' /usr/bin/ps')

Смотрите также руководство Bash по замене процессов, где говорится:

Замена процесса позволяет ссылаться на вход или выход процесса, используя имя файла.

Результатом является имя файла (по крайней мере на Mac, оно принимает форму /dev/fd/xx для некоторого числового значения xx), который можно использовать для ссылки на выходные данные команд при замене процесса.

Подстановка процесса перенаправляет стандартный вывод на чтение. Ничто не идет в трубу к grep,

Соответственно, grep терпеливо ждет и блокирует, и командная цепочка никогда не заканчивается.

Я сделал это так:

read x pid x <<< "$( ps -fu $LOGNAME | grep ' /usr/bin/ps$' )"

Это отлично работает. Весь этот процесс выполняется, создает строку вывода, а затем результат передается read,

Должен обратить внимание на ваш поток данных.:)

Другие вопросы по тегам