Wszyscy wiemy mkfifo
i rurociągi. Pierwszy tworzy nazwaną potok, dlatego należy wybrać nazwę, najprawdopodobniej za pomocą, mktemp
a później pamiętać, aby rozłączyć. Drugi tworzy anonimową potok, bez kłopotów z nazwami i usuwaniem, ale końce potoku są powiązane z poleceniami w potoku, nie jest tak naprawdę wygodne, aby jakoś uchwycić deskryptory plików i użyć ich w pozostałej części skryptu. W skompilowanym programie po prostu bym to zrobił ret=pipe(filedes)
; w Bash jest exec 5<>file
więc coś, czego można się spodziewać "exec 5<> -"
lub czy "pipe <5 >6"
jest coś takiego w Bash?
38
Chociaż żadna ze znanych mi powłok nie może tworzyć rur bez rozwidlenia, niektóre mają lepsze niż podstawowy potok powłoki.
W bash, ksh i zsh, zakładając, że twój system obsługuje
/dev/fd
(większość obecnie robi), możesz powiązać dane wejściowe lub wyjściowe polecenia z nazwą pliku:<(command)
rozwija się do nazwy pliku, która oznacza potok podłączony do wyjściacommand
i>(command)
rozwija do nazwy pliku oznaczającej potok podłączony do wejściacommand
. Ta funkcja nosi nazwę zastępowania procesu . Jego głównym celem jest potokowanie więcej niż jednego polecenia do lub z drugiego, np.Jest to również przydatne w walce z niektórymi wadami podstawowych rur osłonowych. Na przykład
command2 < <(command1)
jest równoważnecommand1 | command2
, z wyjątkiem tego, że ma statuscommand2
. Innym przypadkiem użycia jestexec > >(postprocessing)
, co jest równoważne, ale bardziej czytelne niż, umieszczenie całej reszty skryptu w środku{ ... } | postprocessing
.źródło
pipe:[123456]
). Emacs widzi, że celem dowiązania symbolicznego nie jest istniejąca nazwa pliku, co dezorientuje go na tyle, że nie czyta pliku (może istnieć opcja, aby i tak go odczytał, chociaż Emacs nie lubi otwierać potoku jako pliku plik mimo to).Bash 4 ma koprocesy .
źródło
Według stanu na październik 2012 r. Ta funkcjonalność nadal nie istnieje w Bash, ale można użyć coproc, jeśli potrzebujesz tylko nienazwanych / anonimowych potoków, aby porozmawiać z procesem potomnym. Problem z coproc w tym momencie polega na tym, że najwyraźniej obsługiwany jest tylko jeden na raz. Nie mogę zrozumieć, dlaczego Coproc ma takie ograniczenie. Powinny one być ulepszeniem istniejącego kodu tła zadań (& &), ale to jest pytanie do autorów bash.
źródło
coproc THING { dothing; }
teraz masz już swoje FD${THING[*]}
i możesz je uruchamiać,coproc OTHERTHING { dothing; }
wysyłać i odbierać rzeczy do iz obu.man bash
, pod tytułem BŁĘDY, mówią tak: Może być tylko jeden aktywny koproces na raz . I pojawi się ostrzeżenie, jeśli uruchomisz drugi coproc. Wygląda na to, że działa, ale nie wiem, co wybucha w tle.Choć @ DavidAnderson za odpowiedź obejmuje wszystkie podstawy i oferuje jedne zabezpieczeniach ładne, najważniejszą rzeczą jest to, że ujawnia się w swoje ręce anonimowego rury jest tak proste, jak
<(:)
, jak długo pozostanie w systemie Linux.Zatem najkrótsza i najprostsza odpowiedź na twoje pytanie to:
W systemie macOS to nie zadziała, wtedy musisz utworzyć tymczasowy katalog, w którym mieści się nazwany fifo, dopóki nie przekierujesz do niego. Nie wiem o innych BSD.
źródło
exec
zostanie przekazany anonimowy plik fifo, który jest otwierany tylko do odczytu,exec
nie powinien zezwalać na otwieranie tego anonimowego pliku fifo do odczytu i zapisu przy użyciu niestandardowego deskryptora pliku. Powinieneś spodziewać się-bash: /dev/fd/5: Permission denied
komunikatu, który właśnie powoduje problemy z systemem macOS. Uważam, że błąd polega na tym, że Ubuntu nie wyświetla tego samego komunikatu. Byłbym skłonny zmienić zdanie, gdyby ktoś był w stanie przedstawić dokumentację stwierdzającą, żeexec 5<> <(:)
jest to dozwolone.open(..., O_RDWR)
na jednym jednokierunkowym końcu potoku zapewnianym przez podstawienie i zamienia go w potok dwukierunkowy w jednym FD. Prawdopodobnie masz rację, że nie należy na tym polegać. :-D Dane wyjściowe z użyciem programu uruchamiającego do utworzenia potoku, a następnie zmiany jego przeznaczenia za pomocą bash<>
: libranet.de/display/0b6b25a8-195c-84af-6ac7-ee6696661765exec 5<>
, wpiszfun() { ls -l $1; ls -lH $1; }; fun <(:)
.Poniższa funkcja została przetestowana przy użyciu
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
. System operacyjny to Ubuntu 18. Ta funkcja przyjmuje jeden parametr, który jest pożądanym deskryptorem pliku dla anonimowego FIFO.Poniższa funkcja została przetestowana przy użyciu
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
. System operacyjny to macOS High Sierra. Ta funkcja zaczyna się od utworzenia nazwanego FIFO w katalogu tymczasowym znanym tylko procesowi, który go utworzył . Następnie deskryptor pliku zostaje przekierowany do FIFO. Na koniec FIFO jest odłączany od nazwy pliku poprzez usunięcie katalogu tymczasowego. To sprawia, że FIFO jest anonimowy.Powyższe funkcje można połączyć w jedną funkcję, która będzie działać w obu systemach operacyjnych. Poniżej znajduje się przykład takiej funkcji. Tutaj podjęto próbę stworzenia prawdziwie anonimowego FIFO. Jeśli się to nie powiedzie, wówczas nazwany FIFO zostanie utworzony i przekształcony w anonimowy FIFO.
Oto przykład tworzenia anonimowego FIFO, a następnie pisania tekstu do tego samego FIFO.
Poniżej znajduje się przykład czytania całej zawartości anonimowego FIFO.
Daje to następujący wynik.
Poniższe polecenie zamyka anonimowy FIFO.
Odnośniki:
Tworzenie anonimowego potoku do późniejszego wykorzystania
Pliki w publicznie zapisywanych katalogach są niebezpiecznym
zabezpieczeniem skryptów powłoki
źródło
Korzystając ze świetnej i jasnej odpowiedzi od htamów, zmodyfikowałem ją trochę, aby użyć jej w jednej linijce, oto ona:
źródło