Intereting Posts
Ubuntu 12.04 / Элементарная ОС – Проблема завершения / Logfiles / etc / network / interfaces автоматически запускает pppoe на беспроводном LAN (wlan0) при загрузке, а также делает его постоянным Что случилось с моим скриптом bash? Как я могу передать stdout в другую программу? Как получить детерминированный полный сброс всех правил iptables? Как установить Flash-плагин на Fedora? Событие bash не найдено, пытаясь совместить и исключить скобки в grep Как «благословить» диск без доступа к OSX? Переназначить все domain.com/path, которые не начинаются с domain.com/wiki, на домен.com/wiki – NginX Proxy Linux отбрасывает пакеты, если они получены от другого оборудования Синтаксис конфигурации Syslog Использование telnet для получения заголовка веб-сайта Добавить строку после определенной строки в одной строке в текстовом файле Что такое демонстрация для Linux? Сохранение секретных паролей SSH Атака грубой силы на сервере vsftp не показывает неудачную проверку подлинности в журнале

Почему на выходе «echo 123> (cat)» есть «/ dev / fd / 63»?

echo 123 | cat 123 

делает то, что я ожидал, обе команды запускаются внутри одной оболочки.

но когда я соединяю их с

> (…) Выражение

который соединяет вывод одной команды в оболочке со второй в подоболочке, я получаю следующее:

 echo 123 >(cat) 123 /dev/fd/63 

это также верно и для других значений:

 echo 101 >(cat) 101 /dev/fd/63 echo $BASHPID >(cat) 3252 /dev/fd/63 

Я думал, что command1> (command2) совпадает с command1 | command2 , но с той разницей, что в command1> (command2) каждая команда находится внутри другой оболочки, поэтому они должны иметь одинаковый вывод, где я ошибаюсь?

Подстановка процесса >(thing) будет заменена именем файла. Это имя файла соответствует файлу, который связан со стандартным вводом thing внутри подстановки.

Следующий пример будет лучшим примером его использования:

 $ sort -o >(cat -n >/tmp/out) ~/.profile 

Это отсортировало файл ~/.profile и отправил вывод cat -n который перечислил бы строки и сохранил результат в /tmp/out .

Итак, чтобы ответить на ваш вопрос: вы получаете этот вывод, потому что echo получает два аргумента 123 и /dev/fd/63 . /dev/fd/63 – файл, связанный со стандартным входом процесса cat в процессе замены.

Поскольку это то, что делает подстановка процесса , это делает команду внутри подстановки отображаемой в виде имени файла. Внутренне он соединяет команды через канал, предоставляя путь /dev/fd/NN к основной команде, поэтому он может открыть уже открытый файловый дескриптор для канала.

Это не то же самое, что и труба. Трубы подключают stdout к stdin не затрагивая ничего, что похоже на имена файлов. Подстановка процесса более гибкая, поскольку вы можете иметь несколько таких подстановок в одной командной строке, но для ее основной команды требуется открыть файлы по имени (например, cat а не echo ).

Вы можете эмулировать трубу с заменой процесса, выполняя что-то вроде этого:

 echo foo > >(cat -n) 
 $ echo 1 >(cat > /dev/null) 1 /dev/fd/63 $ echo echo >(cat /dev/null) echo /dev/fd/63 # We can trace how the commands are executed # so long as we avoid using shell builtin commands, # and run the equivalent external program instead, ie /usr/bin/echo $ strace -f -e execve bash -c '/usr/bin/echo >(cat /dev/null)' execve("/usr/bin/bash", ["bash", "-c", "/usr/bin/echo >(cat /dev/null)"], [/* 56 vars */]) = 0 strace: Process 4213 attached [pid 4212] execve("/usr/bin/echo", ["/usr/bin/echo", "/dev/fd/63"], [/* 56 vars */]) = 0 strace: Process 4214 attached [pid 4214] execve("/usr/bin/cat", ["cat", "/dev/null"], [/* 56 vars */]/dev/fd/63 ) = 0 [pid 4212] +++ exited with 0 +++ [pid 4214] +++ exited with 0 +++ --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=4214, si_uid=1001, si_status=0, si_utime=0, si_stime=0} --- +++ exited with 0 +++ # Apparently, the order of evaluation is arranged so this works nicely: $ echo 1 > >(cat > /dev/null) $ 

Для полноты

 cmd1 >(cmd2) 

в основном такой же, как

 cmd1 | cmd2 

в оболочке yash и только этой оболочке.

В этой оболочке >(cmd) есть переадресация процесса, а не >(cmd) ksh / bash / zsh которая является замещением процесса.

Это не строго эквивалентно, потому что в cmd1 >(cmd2) не ждет cmd2 , поэтому вы можете обнаружить следующее:

 $ yash -c 'echo A >(cat); echo B' B A $ yash -c 'echo A | cat; echo B' A B 

Напротив, замещение процесса расширяется до пути к файлу (обычно это именованный канал или /dev/fd/<x> где <x> – это fd для заранее созданного канала), который при открытии для записи позволит отправить вывод в cmd .

Хотя подстановка процесса была введена ksh , в этой оболочке вы не можете передавать их в качестве аргумента в перенаправления.

 ksh -c 'cmd1 > >(cmd2)' 

для эмулирования перенаправления процесса yash не будет работать. Там вы должны передать это имя файла, полученное в результате замены в качестве аргумента для команды, например:

 ksh -c 'diff <(echo a) <(echo b)' 

Он будет работать в bash и zsh .

Однако в bash например, для перенаправления процесса yash, оболочка не ждет команды ( cmd2 ). Так:

 $ bash -c 'echo A > >(cat); echo B' B A 

Замена процесса ksh можно эмулировать с помощью yash с:

 cmd1 /dev/fd/5 5>(cmd2) 

Подобно:

 diff /dev/fd/3 3<(echo a) /dev/fd/4 4<(echo b)