Untuk menyimpan deskriptor file, Anda menduplikatnya di fd lain. Menyimpan jalur ke file yang sesuai tidak cukup, Anda harus menyimpan mode pembukaan, bendera pembuka, posisi saat ini di dalam file dan sebagainya. Dan tentu saja, untuk pipa anonim, atau soket, itu tidak akan berfungsi karena mereka tidak memiliki jalur. Yang ingin Anda simpan adalah deskripsi file terbuka yang mengacu pada fd, dan menduplikasi fd sebenarnya mengembalikan fd baru ke deskripsi file terbuka yang sama .
Untuk menggandakan deskriptor file ke file lain, dengan shell seperti Bourne, sintaksnya adalah:
exec 3>&1
Di atas, fd 1 diduplikasi ke fd 3.
Apa pun fd 3 yang sudah dibuka sebelumnya akan ditutup, tetapi perhatikan bahwa fds 3 hingga 9 (biasanya lebih, hingga 99 dengan yash
) dicadangkan untuk tujuan itu (dan tidak memiliki arti khusus yang bertentangan dengan 0, 1, atau 2), shell tahu untuk tidak menggunakannya untuk bisnis internalnya sendiri. Satu-satunya alasan fd 3 akan dibuka sebelumnya adalah karena Anda melakukannya di skrip 1 , atau dibocorkan oleh penelepon.
Kemudian, Anda dapat mengubah stdout menjadi sesuatu yang lain:
exec > /dev/null
Dan nanti, untuk mengembalikan stdout:
exec >&3 3>&-
( 3>&-
sedang untuk menutup file descriptor yang tidak lagi kita perlukan).
Sekarang, masalah dengan itu adalah bahwa kecuali dalam ksh, setiap perintah yang Anda jalankan setelah itu exec 3>&1
akan mewarisi fd 3. Itu kebocoran fd. Umumnya bukan masalah besar, tapi itu bisa menimbulkan masalah.
ksh
mengatur flag close-on-exec pada fds tersebut (untuk fds lebih dari 2), tetapi tidak pada shell lain dan shell lain tidak memiliki cara untuk mengatur flag itu secara manual.
Pekerjaan sekitar untuk shell lain adalah untuk menutup fd 3 untuk setiap perintah, seperti:
exec 3>&-
exec > file.log
ls 3>&-
uname 3>&-
exec >&3 3>&-
Tidak praktis. Di sini, cara terbaik adalah tidak menggunakan exec
sama sekali, tetapi mengarahkan ulang grup perintah:
{
ls
uname
} > file.log
Di sana, itu shell yang berhati-hati untuk menyimpan stdout dan mengembalikannya setelah itu (dan ia melakukannya secara internal dengan menduplikasi pada fd (di atas 9, di atas 99 untuk yash
) dengan set flag close-on-exec ).
Catatan 1
Sekarang, manajemen fds 3 hingga 9 dapat menjadi rumit dan bermasalah jika Anda menggunakannya secara luas atau dalam fungsi, terutama jika skrip Anda menggunakan beberapa kode pihak ketiga yang pada gilirannya dapat menggunakan fds tersebut.
Beberapa kerang ( zsh
, bash
, ksh93
, semua ditambahkan fitur ( disarankan oleh Oliver Kiddle darizsh
) sekitar waktu yang sama pada tahun 2005 setelah itu dibahas antara para pengembang mereka) memiliki sintaks alternatif untuk menetapkan fd bebas pertama di atas 10 bukan yang membantu dalam hal ini:
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}>&-
}