Od czasu do czasu muszę podać ścieżkę „równoważne” w jednym ze standardowych strumieni IO ( stdin
, stdout
, stderr
). Ponieważ 99% czasu pracuję z Linuksem, po prostu przygotowuję się /dev/
do zdobycia /dev/stdin
itp., A to „ wydaje się właściwe”. Ale z jednej strony zawsze byłem zaniepokojony takim uzasadnieniem (ponieważ oczywiście „wydaje się, że działa”, dopóki nie zadziała). Co więcej, nie mam rozsądku, jak przenośny jest ten manewr.
Mam więc kilka pytań:
W kontekście systemu Linux, jest to bezpieczne (tak / nie), aby zrównać
stdin
,stdout
istderr
z/dev/stdin
,/dev/stdout
i/dev/stderr
?Mówiąc bardziej ogólnie, czy ta równoważność jest „odpowiednio przenośna ”?
Nie mogłem znaleźć żadnych odniesień do POSIX.
Odpowiedzi:
Jest dostępny w Linuksie z powrotem do swojej prehistorii. To nie jest POSIX, chociaż wiele rzeczywistych powłok (w tym AT&T
ksh
ibash
) będzie go symulować, jeśli nie jest obecne w systemie operacyjnym; zauważ, że ta symulacja działa tylko na poziomie powłoki (tj. przekierowanie lub parametr wiersza poleceń, a nie jako wyraźny argument npopen()
.). To powiedziawszy, powinno być dostępne w większości komercyjnych systemów Unix, w ten czy inny sposób (czasami jest pisane/dev/fd/N
dla różnych liczb całkowitychN
, ale większość systemów z tym zapewnia łącza symboliczne, jak Linux i * BSD).źródło
/dev/std{in,out,err}
są wyraźnie wymienione jako nie będące częścią standardu POSIX.1-2008 .ash
nie obsługuje/dev/stdout
initrd ( git.razvi.ro/… )te
/dev/std{in,out,err}
pliki są zwykle tylko dowiązania symboliczne do/proc/self/fd/{0,1,2}
(odpowiednio). W związku z tym nic nie zyskało dzięki zastosowaniu metod zdefiniowanych w POSIX.Jeśli chcesz być zgodny z POSIX, najlepszym sposobem na to jest przekierowanie danych wyjściowych. Przekierowanie wyjścia powłoki jest zdefiniowane w standardzie POSIX . Dodatkowo numery deskryptorów plików STDIN, STDOUT, STDERR są również częścią POSIX .
Krótko mówiąc, takie rzeczy jak na
>&2
pewno działają.Należy jednak zauważyć, że użycie STDIN, STDOUT i STDERR jest subiektywne w stosunku do uruchomienia programu. Jeśli program został uruchomiony z deskryptorem pliku 1 będącym otwartym uchwytem pliku, wówczas program musi go zaakceptować. Nawet jeśli program ma być otwarty
/dev/stdout
, wystarczy otworzyć deskryptor pliku 1, który nadal będzie wskazywał na ten plik.Jeśli właśnie to chcesz obejść, musisz bezpośrednio otworzyć TTY. Zwykle bez żadnych przekierowań STDIN, STDOUT i STDERR są po prostu otwartymi deskryptorami plików wskazującymi ten sam TTY. Nie ma w tym absolutnie nic więcej.
źródło
/proc/self/fd/1
czy/dev/fd/1
jest częścią POSIX?/dev/std???
są tylko dowiązaniami symbolicznymi do/proc/self/fd
Linuksa.POSIX 7 mówi, że są to rozszerzenia.
Podstawowe definicje , sekcja 2.1.1 Wymagania:
Znaleziono przez grepowanie POSIX HTML: Gdzie jest lista funkcji API POSIX C?
Co dziwne,
uuencode
narzędzie daje/dev/stdout
magiczny efekt :Dokumentacja jądra Linuksa mówi, że wszystkie systemy powinny ją mieć.
https://github.com/torvalds/linux/blob/master/Documentation/admin-guide/devices.rst
Nie mogłem jednak znaleźć, gdzie te dowiązania symboliczne są tworzone w jądrze (pod warunkiem dystrybucji?).
źródło
/ dev / {stdout, stdin, stderr} działają w Bash na tych platformach:
Ale csh nie działa na tych:
źródło
bash
jest wyjątkowy, ponieważ można go samodzielnie skompilować w celu obsługi/dev/fd/x
przekierowań w systemach, które go nie mają/dev/fd
Jednym z problemów
/dev/stdout
i znajomych jest to, że w pewnych okolicznościach możesz nie mieć pozwolenia na pisanie do nich. Na przykład zetknąłem się z tym podczas wywoływania skryptów z Nix i wyobrażam sobie podobne narzędzia, które uruchamiają skrypty w więzieniach / piaskownicach / pojemnikach / maszynach wirtualnych / itp. mogą napotkać podobne problemy.Używając składni podobnej do
1>&2
działanej w tych przypadkach, a ponieważ wiedziałem, że będę działał w Bash, mogłem użyć zastępowania procesów dla poleceń, które oczekują nazw plików.źródło