Chciałbym, aby skrypt bash wyprowadzał dodatkowe informacje do deskryptorów plików (FD) większe lub równe 3, gdy są otwarte. Aby sprawdzić, czy FD jest otwarty, opracowałem następującą sztuczkę:
if (printf '' 1>&3) 2>&-; then
# File descriptor 3 is open
else
# File descriptor 3 is not open
fi
Jest to wystarczające dla moich potrzeb, ale jestem ciekawy, czy istnieje bardziej idiomatyczny sposób testowania, czy FD jest ważny. Jestem szczególnie zainteresowany tym, czy istnieje odwzorowanie fcntl(1)
syscall na polecenie powłoki, które pozwalają na pobieranie FD flagami ( O_WRONLY
oraz O_RDWR
do badania, czy FD jest zapisywalny, a O_RDONLY
i O_RDWR
do testu czy FD jest czytelny).
źródło
<>
? Powłoka nie będzie czytać ze swojego standardu, dlaczego miałbyś chcieć otworzyć ją w trybie odczytu + zapisu? Co masz na myśli przez to, co się stało z tym, co wewnętrzne? ?W opisie użycia aplikacji POSIX znajdziesz następujące informacje:
command
Właśnie dlatego możesz po prostu:
Lub...
Który napisze ciąg następnie przez
\n
ewline albo do stdout lub 3 i nadal przechodzą na niezerowym wyjścia kiedy 3 nie jest otwarty, ponieważ matematyka zrobić na$?
nakręca braku do konwersji ósemkowy 08 do % przecinku ale obcina do niczego w ogóle ósemka 00 .Lub...
Ale jeśli używasz
ksh93
, możesz po prostu:Aby wyświetlić listę otwartych deskryptorów plików. Dodaj,
-l
aby zobaczyć, gdzie idą.źródło
Otwarte deskryptory plików można znaleźć w
/proc/<pid>/fd
. Aby na przykład wyświetlić listę otwartych deskryptorów plików bieżącej powłoki, możesz wydaćls -l /proc/$$/fd
coś, co powinno dać ci coś takiego:Po otwarciu pliku za pomocą:
Powinien zostać wymieniony według nowego
ls -l /proc/$$/fd
:Jeśli ponownie zamkniesz deskryptor pliku, używając
exec 7>&-
go, nie będzie/proc/$$/fd
już na liście .źródło
pfiles <pid>
aby zobaczyć, który deskryptor pliku jest podłączony do którego pliku podczasls -l
wyświetlania połączenia w systemie Linux.[ -e /proc/$$/fd/3 ]
, ale wolę nie polegać na procfs, ponieważ jest on przestarzały w FreeBSD i ewentualnie innych systemach.pfiles <pid>
lublsof -p <pid>
sprawdzenia, które deskryptory plików są otwarte./proc
w ogóle nie istnieje na OpenBSD. Na FreeBSD i NetBSD musi to byćmount
jawnie otwarte i/proc/<PID>
nie ma podkatalogufd
.Twoja sztuczka wygląda uroczo; ale dla idiomatycznego sposobu zastanawiam się, dlaczego nie użyłeś:
źródło
{ true >&3; } 2> /dev/null
aby ominąć widelec. Lub{ command exec >&3; } 2> /dev/null
jeśli chcesz przekierować na standardowe wyjście.{ true >&3; } 2> /dev/null
nie wpłynie również na bieżące środowisko i nie rozwidli się (z wyjątkiem powłoki Bourne'a). Mam na myśli, że(exec 1>&3) 2>&-
zwróci true dla fd otwartego w trybie tylko do odczytu.exec
bycie specjalnym wbudowanym opuści powłokę, jeśli zawiedzie (dla bash, tylko w trybie zgodności z POSIX).command exec
zapobiega temu.true
nie jest specjalnym wbudowanym. Zauważ, żeexec
icommand exec
wpływają na bieżące środowisko (dlatego powiedziałem, jeśli chcesz przekierować na standardowe wyjście ).Jeśli interesuje Cię rozwiązanie o niskim rozwidleniu, aby móc go używać wielokrotnie, proponuję tę funkcję:
A oto, co produkuje za pomocą
zsh
:źródło
exec >&3
zabije pocisk, gdy 3 nie jest otwarte.zsh
ibash
. Czy możesz podać powłokę, na którejexec
spowodowała awariaexit
?bash
robićset -o posix
i spróbuj ponownie. Wzsh
... myślę, że to kwestia ustawienia env varPOSIX_BUILTINS
na wartość inną niż null - ale zapominam od razu. W każdym raziezsh
nie jest powłoką, która próbuje zachować zgodność z POSIX, a zatem jest zdecydowanie niestandardowa. Obie te powłoki unikają kompatybilności, co zdaniem niektórych jest wygodą.set -o posix
próba kończy się powodzeniem.To wydaje się bardzo łatwe (patrz komentarze):
Jako dodatkowy ... Test [-r plik] nie wskazuje, czy jakieś dane faktycznie czekają na odczyt (/ dev / null przechodzi ten test (patrz komentarze)).
Wymagana jest niewielka liczba argumentu limitu czasu (read -t) lub dane wymagające obliczeń mogą zostać pominięte. Test czytelności ([plik -r]) jest wymagany lub polecenie odczytu zostanie zbombardowane, jeśli plik nie będzie czytelny. To nie odczyta żadnych danych, ponieważ liczba bajtów wynosi zero (odczyt -N 0).
źródło
/proc/<pid>/fdinfo/<fd>
listę wszystkich trybów otwierania plikówflags:
- patrz tutaj . Dlatego twoja druga część (nawet po naprawieniu rażącego błędu):read -t .1 -N0 <&4
nie powie, czy są dane do odczytu na fd 4: po prostu spróbuj4</dev/null
.[ -r /proc/$$/fd/$FD ]
nie mówi ci, czy deskryptor pliku$FD
jest czytelny, ale jeśli plik, z którego był otwarty, może być ponownie otwarty , z innym deskryptorem pliku, do czytania:exec 7>/tmp/foo; [ -r /proc/$$/fd/7 ] && echo fd 7 can be read from && cat <&7
Pytanie jest dość stare - ale zresztą - dlaczego po prostu nie używać wbudowanych?
Wynik:
Tak więc, aby odpowiedzieć na pytanie - sugeruje:
źródło
-t
nie sprawdza, czy deskryptor pliku jest poprawny, ale czy jest podłączony do tty. Przygotuj aecho yup |
do swojego skryptu, a powie, że0 is INVALID FD
chociaż w rzeczywistości jest to bardzo ważny fd, potok.