Процесс замещения сломан трубой
Я сделал глупость сегодня:
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
,
Должен обратить внимание на ваш поток данных.:)