Aby zapisać deskryptor pliku, powiel go na innym dysku. Zapisanie ścieżki do odpowiedniego pliku nie wystarczy, trzeba zapisać tryb otwierania, flagi otwarcia, bieżącą pozycję w pliku i tak dalej. I oczywiście dla anonimowych rur lub gniazd nie działałoby, ponieważ nie mają one ścieżki. To, co chcesz zapisać, to otwarty opis pliku , do którego odnosi się fd, a powielenie fd faktycznie zwraca nowy fd do tego samego opisu otwartego pliku .
Aby powielić deskryptor pliku na innym, w powłoce Bourne'a, składnia jest następująca:
exec 3>&1
Powyżej, fd 1 jest duplikowane na fd 3.
Cokolwiek fd 3 było już otwarte wcześniej, zostanie zamknięte, ale należy pamiętać, że fds 3 do 9 (zwykle więcej, do 99 z yash
) są zarezerwowane do tego celu (i nie mają specjalnego znaczenia sprzecznego z 0, 1 lub 2), Shell wie, że nie będzie ich używać do własnych celów wewnętrznych. Jedynym powodem, dla którego fd 3 byłby wcześniej otwarty, było to, że zrobiłeś to w skrypcie 1 lub wyciekł z niego dzwoniący.
Następnie możesz zmienić stdout na coś innego:
exec > /dev/null
A później, aby przywrócić standardowe wyjście:
exec >&3 3>&-
( 3>&-
zamykanie deskryptora pliku, którego już nie potrzebujemy).
Problem polega na tym, że z wyjątkiem ksh każde kolejne polecenie exec 3>&1
odziedziczy fd 3. To przeciek fd. Zasadniczo nie jest to wielka sprawa, ale może to powodować problemy.
ksh
ustawia flagę close-on-exec na tych fds (dla fds powyżej 2), ale nie inne powłoki i inne powłoki nie mają możliwości ręcznego ustawienia tej flagi.
Obejściem drugiej powłoki jest zamknięcie fd 3 dla każdego polecenia, na przykład:
exec 3>&-
exec > file.log
ls 3>&-
uname 3>&-
exec >&3 3>&-
Nieporęczny. Tutaj najlepszym sposobem byłoby w ogóle nie używać exec
, ale przekierowywać grupy poleceń:
{
ls
uname
} > file.log
Tam jest to powłoka, która dba o zapisanie stdout i przywrócenie go później (i robi to wewnętrznie, powielając go na fd (powyżej 9, powyżej 99 dla yash
) z ustawioną flagą close-on-exec ).
Uwaga 1
Teraz zarządzanie tymi fds 3 do 9 może być kłopotliwe i problematyczne, jeśli używasz ich intensywnie lub w funkcjach, szczególnie jeśli twój skrypt używa kodu innej firmy, który z kolei może z nich korzystać.
Niektóre muszle ( zsh
, bash
, ksh93
, wszystkie dodane funkcji ( sugerowane przez Oliver Kiddle zzsh
) w tym samym czasie w 2005 roku po to zostało omówione między ich twórców) mają alternatywną składnię przypisywania pierwszego wolnego fd powyżej 10 zamiast co pomaga w tym przypadku:
myfunction() {
local fd
exec {fd}>&1
# stdout was duplicated onto a new fd above 10, whose actual value
# is stored in the fd variable
...
# it should even be safe to re-enter the function here
...
exec >&"$fd" {fd}>&-
}