Ich möchte, dass ein Bash-Skript zusätzliche Informationen an Dateideskriptoren (FDs) ausgibt, die größer oder gleich 3 sind, wenn sie geöffnet sind. Um zu testen, ob ein FD geöffnet ist, habe ich den folgenden Trick entwickelt:
if (printf '' 1>&3) 2>&-; then
# File descriptor 3 is open
else
# File descriptor 3 is not open
fi
Dies ist ausreichend für meine Bedürfnisse, aber ich bin gespannt, ob es eine idiomatischere Möglichkeit gibt, zu testen, ob ein FD gültig ist. Ich bin besonders über interessiert , ob es existiert eine Zuordnung des fcntl(1)
syscall zu einem Shell - Befehl, der dem Abrufen von FD - Flags erlauben würde ( O_WRONLY
und O_RDWR
zu testen , ob die FD beschreibbar ist, und O_RDONLY
und O_RDWR
zu testen , ob die FD lesbar sind).
quelle
<>
? Die Shell wird nicht von ihrem stderr lesen. Warum sollten Sie sie in read + write öffnen? Was meinst du mit dem, was mit intrinsic passiert ist? ?In der Beschreibung der Verwendung der POSIX- Anwendung finden Sie Folgendes:
command
Deshalb können Sie einfach Folgendes tun:
Oder...
Dadurch wird eine Zeichenfolge gefolgt von einer
\n
Ewline entweder auf stdout oder 3 geschrieben, und es wird immer noch ein Exit-Status ungleich Null weitergegeben, wenn 3 nicht geöffnet ist, da die beim Aufwickeln durchgeführte Berechnung$?
das Oktal 08 nicht in % decimal konvertiert, aber überhaupt nicht abgeschnitten wird das Oktal 00 .Oder...
Aber wenn Sie verwenden
ksh93
, können Sie einfach tun:Für eine Liste der offenen Dateideskriptoren. Fügen Sie hinzu, um
-l
zu sehen, wohin sie gehen.quelle
Offene Dateideskriptoren finden Sie in
/proc/<pid>/fd
. Um beispielsweise die offenen Dateideskriptoren der aktuellen Shell aufzulisten,ls -l /proc/$$/fd
die Sie ausgeben können , sollten Sie Folgendes erhalten:Wenn Sie eine Datei öffnen mit:
Es sollte durch ein neues aufgeführt werden
ls -l /proc/$$/fd
:Wenn Sie den Dateideskriptor erneut schließen,
exec 7>&-
wird er ebenfalls nicht/proc/$$/fd
mehr aufgeführt.quelle
pfiles <pid>
zu sehen, welcher Dateideskriptor mit welcher Datei verbunden ist, währendls -l
die Verbindung unter Linux angezeigt wird.[ -e /proc/$$/fd/3 ]
, aber ich ziehe es vor, mich nicht auf procfs zu verlassen, da es in FreeBSD und möglicherweise auch in anderen Un * ces veraltet ist.pfiles <pid>
oderlsof -p <pid>
zu sehen, welche Dateideskriptoren geöffnet sind./proc
existiert überhaupt nicht unter OpenBSD. Unter FreeBSD und NetBSD muss esmount
explizit angegeben werden und darf/proc/<PID>
kein Unterverzeichnis habenfd
.Dein Trick sieht süß aus; aber für eine idiomatische Weise frage ich mich, warum Sie nicht verwendet haben:
quelle
{ true >&3; } 2> /dev/null
, um die Gabel zu vermeiden. Oder{ command exec >&3; } 2> /dev/null
wenn Sie stdout dorthin umleiten möchten.{ true >&3; } 2> /dev/null
wirkt sich auch nicht auf die aktuelle Umgebung aus und teilt sich nicht (außer in der Bourne-Shell). Ich meine, das(exec 1>&3) 2>&-
wird true für ein fd zurückgeben, das im schreibgeschützten Modus geöffnet ist.exec
Wenn Sie ein spezielles integriertes Element sind, wird die Shell beendet, wenn dies fehlschlägt (für Bash nur im POSIX-Konformitätsmodus).command exec
verhindert das.true
ist kein spezielles eingebautes. Beachten Sie diesexec
undcommand exec
wirken Sie sich auf die aktuelle Umgebung aus (deshalb habe ich gesagt, wenn Sie stdout dorthin umleiten möchten ).Das scheint super einfach zu sein (siehe Kommentare):
Als Extra ... Der Test [-r Datei] zeigt nicht an, ob tatsächlich Daten darauf warten, gelesen zu werden (/ dev / null besteht diesen Test (siehe Kommentare)).
Eine kleine Zahl für das Timeout-Argument (read -t) ist erforderlich, oder Daten, für die eine Berechnung erforderlich ist, werden möglicherweise übersehen. Der lesbare Test ([-r Datei]) ist erforderlich, oder der Lesebefehl wird bombardiert, wenn die Datei nicht lesbar ist. Dadurch werden keine Daten gelesen, da die Byteanzahl Null ist (read -N 0).
quelle
/proc/<pid>/fdinfo/<fd>
, in dem alle Modi für geöffnete Dateien aufgeführt sindflags:
- siehe hier . Warum Ihr 2. Teil (auch nach Behebung des grellen Fehlers):read -t .1 -N0 <&4
wird nicht sagen, ob auf fd 4 Daten zu lesen sind: versuchen Sie es einfach mit4</dev/null
.[ -r /proc/$$/fd/$FD ]
sagt Ihnen natürlich nicht, ob der Dateideskriptor$FD
lesbar ist, aber ob die Datei, aus der er geöffnet wurde , mit einem anderen Dateideskriptor zum Öffnen wieder geöffnet werden könnte :exec 7>/tmp/foo; [ -r /proc/$$/fd/7 ] && echo fd 7 can be read from && cat <&7
Wenn Sie an einer Lösung mit geringer Gabelung interessiert sind, um sie wiederholt zu verwenden, würde ich diese Funktion vorschlagen:
Und hier ist, was es mit einem produziert
zsh
:quelle
exec >&3
wird die Muschel getötet, wenn 3 nicht geöffnet ist.zsh
undbash
. Könnten Sie die Shell bereitstellen, auf der der Fehler eineexec
verursacht hatexit
?bash
doset -o posix
und versuchen Sie es erneut. Inzsh
... ich denke, es geht darum, die env varPOSIX_BUILTINS
auf einen Wert ungleich Null zu setzen - aber ich vergesse es sofort. In jedem Fallzsh
handelt es sich nicht um eine Shell, die versucht, die POSIX-Konformität zu gewährleisten, und daher definitiv nicht dem Standard entspricht. Beide Schalen vermeiden Kompatibilität, was manche für Bequemlichkeit halten.set -o posix
ein Versuch erfolgreich.