Saya ingin membuat bash script menghasilkan informasi tambahan ke file descriptors (FDs) lebih besar dari atau sama dengan 3, ketika mereka terbuka. Untuk menguji apakah FD terbuka, saya menyusun trik berikut:
if (printf '' 1>&3) 2>&-; then
# File descriptor 3 is open
else
# File descriptor 3 is not open
fi
Ini cukup untuk kebutuhan saya, tapi saya ingin tahu apakah ada cara yang lebih idiomatis untuk menguji apakah FD itu valid. Saya terutama tertarik tentang apakah ada pemetaan fcntl(1)
syscall ke perintah shell, yang akan memungkinkan pengambilan bendera FD ( O_WRONLY
dan O_RDWR
untuk menguji apakah FD dapat ditulisi, dan O_RDONLY
dan O_RDWR
untuk menguji apakah FD dapat dibaca).
sumber
<>
? Shell tidak akan membaca dari stderrnya, mengapa Anda ingin membukanya di read + write? Apa maksud Anda dengan apa yang terjadi pada intrinsik? ?Dalam deskripsi Penggunaan Aplikasi POSIX Anda akan menemukan yang berikut:
command
Inilah sebabnya mengapa Anda bisa melakukan:
Atau...
Yang akan menulis string diikuti oleh
\n
ewline baik ke stdout atau 3 dan masih meneruskan status keluar non-nol ketika 3 tidak terbuka karena matematika dilakukan pada$?
gagal gagal mengubah oktal 08 ke % desimal tetapi memotong apa-apa sama sekali oktal 00 .Atau...
Tetapi jika Anda menggunakan
ksh93
, Anda bisa melakukan:Untuk daftar deskriptor file terbuka. Tambahkan
-l
untuk melihat ke mana mereka pergi.sumber
Deskriptor file terbuka dapat ditemukan di
/proc/<pid>/fd
. Untuk membuat daftar, misalnya, deskriptor file terbuka dari shell saat ini Anda dapat mengeluarkanls -l /proc/$$/fd
yang seharusnya memberi Anda sesuatu seperti:Saat Anda membuka file menggunakan:
Itu harus terdaftar oleh yang baru
ls -l /proc/$$/fd
:Jika Anda menutup file deskriptor lagi menggunakannya
exec 7>&-
juga tidak terdaftar/proc/$$/fd
lagi.sumber
pfiles <pid>
untuk melihat deskriptor file mana yang terhubung ke file mana saatls -l
menampilkan koneksi di Linux.[ -e /proc/$$/fd/3 ]
, tapi saya lebih suka untuk tidak bergantung pada procfs, karena sudah usang di FreeBSD dan mungkin juga un * ces lainnya.pfiles <pid>
ataulsof -p <pid>
untuk melihat file deskriptor mana yang terbuka./proc
sama sekali tidak ada di OpenBSD. Pada FreeBSD dan NetBSD harusmount
-ed secara eksplisit, dan/proc/<PID>
tidak memiliki subdirektorifd
.Trik Anda terlihat lucu; tetapi untuk cara idiomatis saya bertanya-tanya mengapa Anda tidak menggunakan:
sumber
{ true >&3; } 2> /dev/null
untuk menghindari garpu. Atau{ command exec >&3; } 2> /dev/null
jika Anda ingin mengarahkan stdout ke sana.{ true >&3; } 2> /dev/null
tidak akan memengaruhi lingkungan saat ini juga dan tidak akan bercabang (kecuali di shell Bourne). Maksud saya,(exec 1>&3) 2>&-
akan mengembalikan true untuk membuka fd dalam mode read-only.exec
menjadi builtin khusus akan keluar dari shell jika gagal (untuk bash, hanya ketika dalam mode kepatuhan POSIX).command exec
mencegah itu.true
bukan builtin khusus. Catat ituexec
dancommand exec
mempengaruhi lingkungan saat ini (itu sebabnya saya katakan jika Anda ingin mengarahkan stdout ke sana ).Jika Anda tertarik pada solusi forking rendah sehingga menggunakannya berulang kali, saya akan menyarankan fungsi ini:
Dan inilah yang ia hasilkan dengan
zsh
:sumber
exec >&3
akan membunuh shell ketika 3 tidak terbuka.zsh
danbash
. Bisakah Anda memberikan shell yangexec
menyebabkan kegagalanexit
?bash
lakukanset -o posix
dan coba lagi. Dalamzsh
... saya pikir ini masalah pengaturan env varPOSIX_BUILTINS
ke nilai tidak-nol - tetapi saya lupa begitu saja. Dalam kasus apa pun,zsh
ini bukan shell yang berupaya untuk kepatuhan POSIX, dan karenanya merupakan standar non-standar. Kedua cangkang itu menghindari kompatibilitas untuk apa yang beberapa orang yakini kenyamanan.set -o posix
mencoba berhasil.Ini tampaknya sangat mudah (lihat komentar):
Sebagai tambahan ... Tes [-r file] tidak menunjukkan apakah ada data yang benar-benar menunggu untuk dibaca (/ dev / null melewati tes ini (lihat komentar)).
Sejumlah kecil untuk argumen batas waktu (baca -t) diperlukan atau data yang perlu perhitungan mungkin terlewatkan. Tes yang dapat dibaca ([-r file]) diperlukan atau perintah baca akan gagal jika file tidak dapat dibaca. Ini tidak akan benar-benar membaca data apa pun karena jumlah byte adalah nol (baca -N 0).
sumber
/proc/<pid>/fdinfo/<fd>
, yang mencantumkan semua mode file terbuka di bawahflags:
- lihat di sini . Untuk alasan mengapa bagian kedua Anda (bahkan setelah memperbaiki kesalahan mencolok):read -t .1 -N0 <&4
tidak akan memberi tahu apakah ada data untuk dibaca di fd 4: coba saja4</dev/null
.[ -r /proc/$$/fd/$FD ]
tidak memberi tahu Anda apakah deskriptor file$FD
dapat dibaca, tetapi jika file itu dibuka dapat dibuka lagi , dengan deskriptor file lain, untuk membaca:exec 7>/tmp/foo; [ -r /proc/$$/fd/7 ] && echo fd 7 can be read from && cat <&7
Pertanyaannya sudah cukup lama - tetapi bagaimanapun juga - mengapa tidak menggunakan builtin?
Keluaran:
Jadi, untuk menjawab pertanyaan - akan menyarankan:
sumber
-t
tidak menguji apakah deskriptor file valid, tetapi jika itu terhubung ke tty. Tambahkanecho yup |
ke skrip Anda, dan akan mengatakan bahwa0 is INVALID FD
, meskipun sebenarnya itu sangat valid, sebuah pipa.