7 votes

Pourquoi les liens symboliques dans /proc/$PID/fd/ agissent-ils comme des liens physiques?

Lorsque la cible d'un lien symbolique est supprimée, il pointe vers rien et il n'y a aucun moyen d'accéder au contenu de la cible supprimée.

Les fichiers dans /proc/$PID/fd/ sont affichés sous forme de liens symboliques, mais ils vous permettent d'accéder au contenu de la cible supprimée, comme expliqué ici : Récupérer des fichiers Linux supprimés avec lsof.

Comment cela fonctionne-t-il ? Pourquoi est-il affiché comme un lien symbolique s'il n'agit pas comme tel ? Est-ce l'implémentation du lien symbolique du système de fichiers proc qui conserve une référence à l'inode du fichier ?

4voto

Kamil Maciorowski Points 57004

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.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X