Das Prüfen /proc/self
ist eine knifflige Angelegenheit, da es sich für jeden Prozess ändert. Wenn Sie dies tun /proc/self/fd/*
, erweitert die Shell den Platzhalter, sodass sie ihre eigenen Dateideskriptoren auflistet. Wenn diese jedoch an einen anderen Befehl wie find
oder übergeben werden ls
, sind die Pfade jetzt für diesen Prozess vorgesehen /proc/self
, und es kann fds mit diesen Nummern geben oder nicht.
Noch schwieriger ist es, wenn die Shell während der Platzhaltererweiterung Dateideskriptoren öffnet.
Ein Vergleich mit /proc/$$/fd
könnte aufschlussreich sein:
bash
::
$ ls -l /proc/self/fd /proc/$$/fd/* &
[1] 5172
$ lrwx------ 1 muru muru 64 Jan 1 20:16 /proc/4932/fd/0 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 1 20:16 /proc/4932/fd/1 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 1 20:16 /proc/4932/fd/2 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 1 20:16 /proc/4932/fd/255 -> /dev/pts/1
/proc/self/fd:
total 0
lrwx------ 1 muru muru 64 Jan 1 20:24 0 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 1 20:24 1 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 1 20:24 2 -> /dev/pts/1
lr-x------ 1 muru muru 64 Jan 1 20:24 3 -> /proc/5172/fd
[1]+ Done ls --color=auto -l /proc/self/fd /proc/$$/fd/*
Indem ich es in den Hintergrund schickte, bekam ich Bash, um die PID zu drucken, und Sie können sehen, dass diese /proc/self/fd/3
Punkte zu ls
"eigenen" gehören /proc/<PID>/fd
, die zum Scannen geöffnet wurden. Die Einträge mit 4932
OTOH sind für bashs fds und der spezielle ist 255. Eine Erklärung finden Sie in diesem SO-Beitrag :
Die geöffneten Dateien sind 0 (stdin), 1 (stdout) und 2 (stderr). 255 ist ein kleiner Trick, mit dem bash eine Kopie davon aufbewahrt, wenn sie umgeleitet werden. Dies ist spezifisch für Bash.
Quelle: https://books.google.com/books?id=wWjqCF9HLfYC&pg=PA231
Mit mksh
:
$ ls -l /proc/self/fd /proc/$$/fd/* &
[1] 5075
$ lrwx------ 1 muru muru 64 Jan 1 20:22 /proc/5074/fd/0 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 1 20:22 /proc/5074/fd/1 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 1 20:22 /proc/5074/fd/10 -> /dev/tty
lrwx------ 1 muru muru 64 Jan 1 20:22 /proc/5074/fd/2 -> /dev/pts/1
/proc/self/fd:
total 0
lrwx------ 1 muru muru 64 Jan 1 20:22 0 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 1 20:22 1 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 1 20:22 2 -> /dev/pts/1
lr-x------ 1 muru muru 64 Jan 1 20:22 3 -> /proc/5075/fd
[1] + Done ls -l /proc/self/fd /proc/$$/fd/*
Praktisch dasselbe, außer dass das zusätzliche fd 10 ist, und ich würde wetten, dass es aus dem gleichen Grund wie bash ist, da der Quellcode angibt, dass fd 10 und höher von der Shell verwendet wird.
Ich habe nicht zwei oder drei zusätzliche FDS erhalten, aber es könnte an einer beliebigen Anzahl von Dingen liegen, die während der Wildcard-Erweiterung passieren, oder an Hintergrundjobs oder einem anderen unbekannten Grund.
Wenn ich deine for
Schleife starte, bekomme ich eine kurzlebige fd 3:
$ for fd in /proc/$$/fd/* ; do ls -l $fd ; done
lrwx------ 1 muru muru 64 Jan 2 17:39 /proc/6012/fd/0 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 2 17:39 /proc/6012/fd/1 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 2 17:39 /proc/6012/fd/2 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 2 17:39 /proc/6012/fd/255 -> /dev/pts/1
ls: cannot access '/proc/6012/fd/3': No such file or directory
Und hier, strace
um die Ausführung zu verfolgen:
strace -e open -o log bash -c 'for fd in /proc/$$/fd/* ; do : ; done'
Wir werden sehen, dass der dritte fd tatsächlich ist /proc/<PID>/fd
:
$ tail log
open("/usr/lib/libreadline.so.7", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/libncursesw.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/dev/tty", O_RDWR|O_NONBLOCK) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/gconv/gconv-modules.cache", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/gconv/gconv-modules", O_RDONLY|O_CLOEXEC) = 3
open("/proc/9975/fd/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
+++ exited with 0 +++
Die Frage ist nun, warum dieses fd in den früheren ls
Tests nicht aufgetaucht ist . Es sieht so aus, als hätte der Hintergrund etwas damit zu tun:
$ ls -l /proc/$$/fd/* &
[1] 10091
$ lrwx------ 1 muru muru 64 Jan 2 17:46 /proc/10076/fd/0 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 2 17:46 /proc/10076/fd/1 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 2 17:46 /proc/10076/fd/2 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 2 17:46 /proc/10076/fd/255 -> /dev/pts/1
[1]+ Done ls --color=auto -l /proc/self/fd /proc/$$/fd/*
$ ls -l /proc/$$/fd/*
ls: cannot access '/proc/10076/fd/3': No such file or directory
lrwx------ 1 muru muru 64 Jan 2 17:46 /proc/10076/fd/0 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 2 17:46 /proc/10076/fd/1 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 2 17:46 /proc/10076/fd/2 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 2 17:46 /proc/10076/fd/255 -> /dev/pts/1
Der Vordergrund ls
zeigt das fehlende fd.
Nun noch einmal verfolgen mit strace
:
strace -fe open,execve,fork -o log bash -ic 'ls -l /proc/self/fd /proc/$$/fd/* &'
Wir sehen:
10731 execve("/usr/bin/bash", ["bash", "-ic", "ls -l /proc/$$/fd/* &"], [/* 67 vars */]) = 0
10731 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
# snip
10734 open("/proc/10731/fd/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
10734 execve("/usr/bin/ls", ["ls", "--color=auto", "-l", "/proc/10731/fd/0", "/proc/10731/fd/1", "/proc/10731/fd/2", "/proc/10731/fd/255"], [/* 68 vars */]) = 0
Beachten Sie die Änderung der PIDs. Es scheint, dass die Platzhaltererweiterung nach dem Gabeln stattfindet, aber die variable Erweiterung erfolgt vorher . Fd 3 existiert also, aber in einem anderen Prozess. Wenn Sie jetzt self
anstelle von verwenden $$
, sehen Sie sowohl 3 als auch 255:
$ strace -fe open,execve -o log bash -ic 'ls -l /proc/self/fd/* &'
[1] 10790
ls: cannot access '/proc/self/fd/255': No such file or directory
ls: cannot access '/proc/self/fd/3': No such file or directory
lrwx------ 1 muru muru 64 Jan 2 18:04 /proc/self/fd/0 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 2 18:04 /proc/self/fd/1 -> /dev/pts/1
lrwx------ 1 muru muru 64 Jan 2 18:04 /proc/self/fd/2 -> /dev/pts/1
Nachtrag
Eine ähnliche Antwort auf Unix & Linux Stack Website zitiert eine Antwort von einer Mail - Liste :
Fd 255 wird intern als Verbindung zum tty verwendet, damit die Verwendung von exec zum Verschieben von fds nicht beeinträchtigt wird. Bash weist aus dem gleichen Grund auch hohe fds zu, wenn eine Prozessersetzung "<(foo)" behandelt wird.
Andreas Schwab
lsof -p $$