Вы можете отсоединить именованный канал сразу после присоединения его к текущему процессу, что практически приводит к анонимному каналу:
# create a temporary named pipe
PIPE=$(mktemp -u)
mkfifo $PIPE
# attach it to file descriptor 3
exec 3<>$PIPE
# unlink the named pipe
rm $PIPE
...
# anything we write to fd 3 can be read back from it
echo 'Hello world!' >&3
head -n1 <&3
...
# close the file descriptor when we are finished (optional)
exec 3>&-
Если вы действительно хотите избежать именованных каналов (например, файловая система доступна только для чтения), ваша идея «получить контроль над дескрипторами файлов» также работает. Обратите внимание, что это специфично для Linux из-за использования procfs.
# start a background pipeline with two processes running forever
tail -f /dev/null | tail -f /dev/null &
# save the process ids
PID2=$!
PID1=$(jobs -p %+)
# hijack the pipe's file descriptors using procfs
exec 3>/proc/$PID1/fd/1 4</proc/$PID2/fd/0
# kill the background processes we no longer need
# (using disown suppresses the 'Terminated' message)
disown $PID2
kill $PID1 $PID2
...
# anything we write to fd 3 can be read back from fd 4
echo 'Hello world!' >&3
head -n1 <&4
...
# close the file descriptors when we are finished (optional)
exec 3>&- 4<&-
Хотя ни одна из известных мне оболочек не может создавать трубы без разветвления, у некоторых все же лучше, чем у базовой оболочки.
В bash, ksh и zsh, предполагая, что ваша система поддерживает
/dev/fd
(большинство в настоящее время поддерживают ), вы можете связать ввод или вывод команды с именем файла:<(command)
расширяется до имени файла, обозначающего канал, подключенный к выходуcommand
, и>(command)
расширяется к имени файла, который обозначает канал, связанный с входомcommand
. Эта функция называется процессом замены . Его основная цель состоит в том, чтобы направить более одной команды в другую или из нее, например,Это также полезно для борьбы с некоторыми недостатками основных оболочек труб. Например,
command2 < <(command1)
эквивалентноcommand1 | command2
, за исключением того, что его статус является статусомcommand2
. Другой вариант использованияexec > >(postprocessing)
, который эквивалентен, но более удобен для чтения, чем помещение всего остального скрипта внутрь{ ... } | postprocessing
.источник
pipe:[123456]
). Emacs видит, что целью символической ссылки не является существующее имя файла, и это настолько запутывает его, что он не читает файл (может быть, в любом случае, есть возможность заставить его прочитать его, хотя Emacs не любит открывать канал как файл в любом случае).Bash 4 имеет сопроцессы .
источник
По состоянию на октябрь 2012 г. эта функциональность еще не существует в Bash, но можно использовать coproc, если все, что вам нужно для безымянных / анонимных каналов, - это поговорить с дочерним процессом. Проблема с coproc на данный момент заключается в том, что, по-видимому, одновременно поддерживается только один. Я не могу понять, почему у coproc такое ограничение. Они должны были улучшить существующий фоновый код задачи (& op), но это вопрос для авторов bash.
источник
coproc THING { dothing; }
теперь ваши FD находятся в системе,${THING[*]}
и вы можете запускать,coproc OTHERTHING { dothing; }
отправлять и получать данные в обе и из них.man bash
, под заголовком BUGS, они говорят следующее: за один раз может быть только один активный сопроцесс . И вы получите предупреждение, если начнете второй копрок. Кажется, это работает, но я не знаю, что взрывается на заднем плане.Хотя ответ @ DavidAnderson охватывает все основы и предлагает несколько хороших мер защиты, самое важное, что он раскрывает, заключается в том, что получить анонимный канал так же просто
<(:)
, как и до тех пор, пока вы остаетесь в Linux.Итак, самый короткий и простой ответ на ваш вопрос:
В macOS это не будет работать, тогда вам нужно будет создать временный каталог для размещения имени fifo, пока вы не будете перенаправлены на него. Я не знаю о других BSD.
источник
exec
передается анонимный fifo, который открывается только для чтения, тоexec
не следует разрешать открытие этого анонимного fifo для чтения и записи с использованием пользовательского дескриптора файла. Вы должны получить-bash: /dev/fd/5: Permission denied
сообщение, которое выдает macOS. Я считаю, что ошибка в том, что Ubuntu не выдает такое же сообщение. Я был бы готов передумать, если бы кто-то мог представить документацию, говорящую,exec 5<> <(:)
что объяснено разрешено.open(..., O_RDWR)
на одном однонаправленном конце канала, обеспечиваемом заменой, и превращает его в двунаправленный канал в одном FD. Вы, вероятно, правы, что не стоит полагаться на это. :-D Вывод из использования piperw execline для создания канала, а затем его перепрофилирование с помощью bash<>
: libranet.de/display/0b6b25a8-195c-84af-6ac7-ee6696661765exec 5<>
, введитеfun() { ls -l $1; ls -lH $1; }; fun <(:)
.Следующая функция была протестирована с помощью
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
. Операционная система была Ubuntu 18. Эта функция принимает один параметр, который является желаемым дескриптором файла для анонимного FIFO.Следующая функция была протестирована с помощью
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
. Операционная система была macOS High Sierra. Эта функция запускается созданием именованного FIFO во временном каталоге, известном только процессу, который его создал . Затем файловый дескриптор перенаправляется в FIFO. Наконец, FIFO отсоединяется от имени файла путем удаления временного каталога. Это делает FIFO анонимным.Вышеуказанные функции могут быть объединены в одну функцию, которая будет работать в обеих операционных системах. Ниже приведен пример такой функции. Здесь делается попытка создать действительно анонимный FIFO. В случае неудачи именованный FIFO создается и преобразуется в анонимный FIFO.
Вот пример создания анонимного FIFO, а затем записи некоторого текста в тот же FIFO.
Ниже приведен пример чтения всего содержимого анонимного FIFO.
Это производит следующий вывод.
Команда ниже закрывает анонимный FIFO.
Ссылки:
Создание анонимных труб для последующего использования
файлов в Публично записи каталогов опасен
Shell Script Security
источник
Используя великолепный и яркий ответ от htamas, я немного изменил его, чтобы использовать его в один слой, вот он:
источник