Si sa cible est supprimée, une entité dans /proc/$PID/fd/
apparaît comme un lien symbolique brisé lorsque vous utilisez ls(1)
ou file(1)
, mais elle agit en réalité différemment lorsqu'elle est ouverte avec open(2)
.
Sur mon Debian 9, j'ai utilisé strace(1)
pour voir ce qui se passe lorsque j'essaie de lire un lien symbolique. La commande est sudo strace cat "$symlink"
. La ligne pertinente de stderr est
-
soit OK
open("$symlink", O_RDONLY) = 3
-
ou ENOENT
open("$symlink", O_RDONLY) = -1 ENOENT (Aucun fichier ou dossier de ce type)
(Remarque : Je ne dis pas que ce sont toutes les résultats possibles de open(2)
en général).
Les résultats :
| lien symbolique ordinaire | /proc/$PID/fd/$N |
---------------+-----------------+------------------+
existe, valide | OK | OK |
existe, brisé | ENOENT | OK | <- la différence
n'existe pas | ENOENT | ENOENT |
---------------+-----------------+------------------+
J'ai aussi appris que lorsque j'exécute file "$symlink"
, cela appelle lstat(2)
, readlink(2)
et stat(2)
. Ce sont des appels système qui se basent sur des chemins, pas des descripteurs de fichiers. Si le lien symbolique existe (valide ou brisé), open(2)
n'est jamais appelé pour l'ouvrir ou ouvrir sa cible. ENOENT
provenant de stat(2)
indique que le lien est cassé.
Ma conclusion est : un "lien brisé" est une propriété dérivée de la sortie de certains appels système ; mais lorsque vous ouvrez un lien depuis /proc/$PID/fd/
, open(2)
sait simplement quoi en faire et ne se soucie pas de ce que tout autre outil pourrait indiquer.
Remarquez que tout le /proc
ne fait que simuler un système de fichiers "normal". Quelques particularités :
- Les fichiers peuvent avoir un contenu dynamique, mais ils ne sont pas modifiés avec des appels système (essayez
inotifywait
).
- Les objets peuvent (dis)paraître, mais ils ne sont ni créés ni supprimés avec des appels système (encore une fois,
inotifywait
).
- En un sens, les objets peuvent ne pas exister tant que vous n'interagissez pas avec eux. Exécutez
bash
et attendez quelques minutes. Appelez ls -l /proc/$$/fd
pour voir ses descripteurs de fichiers. Probablement, les ctimes afficheront "ce moment précis". Pourtant, si vous répétez la commande toutes les quelques secondes, vous remarquerez que les ctimes ne changent jamais. (Anecdote : au début, je pensais pouvoir répondre à cette question Déterminer depuis combien de temps un fichier est ouvert avec stat
et des liens symboliques dans /proc/$PID/fd/
mais j'avais tort ; maintenant vous savez pourquoi).
Il n'est donc pas étonnant que ces liens symboliques dont vous parlez ne se comportent pas comme des liens symboliques normaux dans certaines circonstances. Tout le /proc
a été conçu pour se comporter de manière quelque peu différente. Je suppose que open(2)
a été délibérément doté de la capacité d'en tirer parti.