Qu'est-ce qu'un "montage de liaison"? Comment en faire un? À quoi ça sert?
On m'a dit d'utiliser une monture de liaison pour quelque chose, mais je ne comprends pas ce que c'est ni comment l'utiliser.
Un montage de liaison est une autre vue d'une arborescence de répertoires. Classiquement, le montage crée une vue d'un périphérique de stockage sous forme d'arborescence de répertoires. Un montage de liaison prend à la place une arborescence de répertoires existante et la réplique sous un point différent. Les répertoires et fichiers du montage de liaison sont les mêmes que ceux d'origine. Toute modification d'un côté se reflète immédiatement de l'autre côté, car les deux vues affichent les mêmes données.
Par exemple, après avoir lancé la commande Linux
mount --bind /some/where /else/where
les répertoires /some/where
et /else/where
ont le même contenu.
Contrairement à un lien dur ou un lien symbolique, un montage de liaison n'affecte pas ce qui est stocké sur le système de fichiers. C'est une propriété du système live.
Le système de fichiers bindfs
est un système de fichiers Fuse qui crée une vue d'une arborescence de répertoires. Par exemple, la commande
bindfs /some/where /else/where
fait du /else/where
un point de montage sous lequel le contenu de /some/where
sont visibles.
Étant donné que bindfs est un système de fichiers distinct, les fichiers /some/where/foo
et /else/where/foo
apparaissent comme des fichiers différents des applications (le système de fichiers bindfs a son propre st_dev
valeur). Tout changement d'un côté est "magiquement" reflété de l'autre côté, mais le fait que les fichiers soient les mêmes n'est apparent que lorsque l'on sait comment fonctionne bindfs.
Bindfs n'a aucune connaissance des points de montage, donc s'il y a un point de montage sous /some/where
, il apparaît simplement comme un autre répertoire sous /else/where
. Monter ou démonter un système de fichiers en dessous /some/where
apparaît sous /else/where
comme un changement du répertoire correspondant.
Bindfs peut modifier certaines des métadonnées des fichiers: il peut afficher de fausses autorisations et la propriété des fichiers. Voir manuel pour plus de détails, et voir ci-dessous pour des exemples.
Un système de fichiers bindfs peut être monté en tant qu'utilisateur non root, vous n'avez besoin que du privilège pour monter des systèmes de fichiers Fuse. Selon votre distribution, cela peut nécessiter d'être dans le groupe Fuse
ou être autorisé à tous les utilisateurs. Pour démonter un système de fichiers Fuse, utilisez fusermount -u
au lieu de umount
, par exemple.
fusermount -u /else/where
FreeBSD fournit le système de fichiers nullfs
qui crée une vue alternative d'un système de fichiers. Les deux commandes suivantes sont équivalentes:
mount -t nullfs /some/where /else/where
mount_nullfs /some/where /else/where
Après avoir émis l'une des commandes, /else/where
devient un point de montage auquel le contenu de /some/where
sont visibles.
Étant donné que nullfs est un système de fichiers distinct, les fichiers /some/where/foo
et /else/where/foo
apparaissent comme des fichiers différents des applications (le système de fichiers nullfs a son propre st_dev
valeur). Tout changement d'un côté est "magiquement" reflété de l'autre côté, mais le fait que les fichiers soient les mêmes n'est apparent que lorsque l'on sait comment nullfs fonctionne.
Contrairement aux bindfs Fuse, qui agissent au niveau de l'arborescence des répertoires, les nullfs de FreeBSD agissent plus profondément dans le noyau, donc montez les points sous /else/where
ne sont pas visibles: uniquement l'arborescence faisant partie du même point de montage que /some/where
est reflété sous /else/where
.
Le système de fichiers nullfs peut être utilisable sous d'autres variantes BSD (OS X, OpenBSD, NetBSD) mais il n'est pas compilé dans le cadre du système par défaut.
Sous Linux, les montages de liaison sont disponibles en tant que fonctionnalité du noyau. Vous pouvez en créer un avec la commande mount
, en passant soit la --bind
option de ligne de commande ou l'option de montage bind
. Les deux commandes suivantes sont équivalentes:
mount --bind /some/where /else/where
mount -o bind /some/where /else/where
Ici, le "périphérique" /some/where
n'est pas une partition de disque comme dans le cas d'un système de fichiers sur disque, mais un répertoire existant. Le point de montage /else/where
doit être un répertoire existant comme d'habitude. Notez qu'aucun type de système de fichiers n'est spécifié dans les deux cas: faire un montage de liaison n'implique pas de pilote de système de fichiers, il copie les structures de données du noyau à partir du montage d'origine.
mount --bind
prend également en charge le montage d'un non-répertoire sur un non-répertoire: /some/where
peut être un fichier normal (auquel cas /else/where
doit également être un fichier standard).
Un montage de liaison Linux est généralement impossible à distinguer de l'original. La commande df -T /else/where
montre le même périphérique et le même type de système de fichiers que df -T /some/where
. Les fichiers /some/where/foo
et /else/where/foo
sont indiscernables, comme s'il s'agissait de liens durs. Il est possible de démonter /some/where
, dans quel cas /else/where
reste monté.
Avec les noyaux plus anciens (je ne sais pas exactement quand, je pense jusqu'à environ 3.x), les montures de liaison étaient vraiment indiscernables de l'original. Les noyaux récents suivent les montages de liaison et exposent les informations via PID/mountinfo, ce qui permet à findmnt
d'indiquer le montage de liaison en tant que tel .
Vous pouvez mettre des entrées de montage de liaison dans /etc/fstab
. Incluez simplement bind
(ou rbind
etc.) dans les options, ainsi que toutes les autres options que vous souhaitez. Le "périphérique" est l'arborescence existante. La colonne du système de fichiers peut contenir none
ou bind
(elle est ignorée, mais l'utilisation d'un nom de système de fichiers serait source de confusion). Par exemple:
/some/where /readonly/view none bind,ro
S'il y a des points de montage sous /some/where
, leur contenu n'est pas visible sous /else/where
. Au lieu de bind
, vous pouvez utiliser rbind
, également répliquer les points de montage sous /some/where
. Par exemple, si /some/where/mnt
est alors un point de montage
mount --rbind /some/where /else/where
est équivalent à
mount --bind /some/where /else/where
mount --bind /some/where/mnt /else/where/mnt
De plus, Linux permet de déclarer les montages comme partagés , esclaves , privé ou indissociable . Cela affecte si cette opération de montage est reflétée sous un montage de liaison qui réplique le point de montage. Pour plus de détails, voir la documentation du noya .
Linux fournit également un moyen de déplacer les montures: où --bind
copies, --move
déplace un point de montage.
Il est possible d'avoir différentes options de montage dans deux répertoires montés sur liaison. Il y a cependant une bizarrerie: la création du montage de liaison et la définition des options de montage ne peuvent pas être effectuées de manière atomique, elles doivent être deux opérations successives. (Les noyaux plus anciens ne le permettaient pas.) Par exemple, les commandes suivantes créent une vue en lecture seule, mais il y a une petite fenêtre pendant laquelle /else/where
est en lecture-écriture:
mount --bind /some/where /else/where
mount -o remount,ro,bind /else/where
Si votre système ne prend pas en charge Fuse, une astuce classique pour obtenir le même effet consiste à exécuter un serveur NFS, à lui faire exporter les fichiers que vous souhaitez exposer (autorisant l'accès à localhost
) et à les monter sur le même machine. Cela a un surcoût important en termes de mémoire et de performances, donc les montages de liaison ont un avantage certain lorsqu'ils sont disponibles (ce qui est le cas sur la plupart des variantes Unix grâce à Fuse).
Il peut être utile de créer une vue en lecture seule d'un système de fichiers, soit pour des raisons de sécurité, soit comme couche de sécurité pour vous assurer que vous ne le modifierez pas accidentellement.
Avec bindfs:
bindfs -r /some/where /mnt/readonly
Avec Linux, la manière simple:
mount --bind /some/where /mnt/readonly
mount -o remount,ro,bind /mnt/readonly
Cela laisse un court intervalle de temps pendant lequel /mnt/readonly
est en lecture-écriture. S'il s'agit d'un problème de sécurité, créez d'abord le montage de liaison dans un répertoire auquel seule la racine peut accéder, rendez-le en lecture seule, puis déplacez-le vers un point de montage public. Dans l'extrait ci-dessous, notez qu'il est important que /root/private
(le répertoire au-dessus du point de montage) est privé; les autorisations d'origine sur /root/private/mnt
ne sont pas pertinents car ils sont cachés derrière le point de montage.
mkdir -p /root/private/mnt
chmod 700 /root/private
mount --bind /some/where /root/private/mnt
mount -o remount,ro,bind /root/private/mnt
mount --move /root/private/mnt /mnt/readonly
Les systèmes de fichiers enregistrent les utilisateurs et les groupes par leur ID numérique. Parfois, vous vous retrouvez avec plusieurs systèmes qui attribuent des ID utilisateur différents à la même personne. Ce n'est pas un problème d'accès au réseau, mais cela rend les ID utilisateur sans signification lorsque vous transportez des données d'un système à un autre sur un disque. Supposons que vous ayez un disque créé avec un système de fichiers multi-utilisateurs (par exemple ext4, btrfs, zfs, UFS,…) sur un système où Alice a l'ID utilisateur 1000 et Bob a l'ID utilisateur 1001, et que vous souhaitez rendre ce disque accessible sur un système où Alice a l'ID utilisateur 1001 et Bob a l'ID utilisateur 1000. Si vous montez le disque directement, les fichiers d'Alice apparaîtront comme appartenant à Bob (car l'ID utilisateur est 1001) et les fichiers de Bob apparaîtront comme appartenant à Alice (parce que le l'ID utilisateur est 1000).
Vous pouvez utiliser bindfs pour remapper les ID utilisateur. Montez d'abord la partition de disque dans un répertoire privé, où seul root peut y accéder. Créez ensuite une vue bindfs dans une zone publique, avec un remappage des ID utilisateur et ID de groupe qui permute les ID utilisateur d'Alice et Bob et les ID de groupe.
mkdir -p /root/private/alice_disk /media/alice_disk
chmod 700 /root/private
mount /dev/sdb1 /root/private/alice_disk
bindfs --map=1000/1001:1001/1000:@1000/1001:@1001/1000 /root/private/alice_disk /media/alice_disk
Voir Comment peut-on accéder aux fichiers du dossier de base de l'utilisateur du système non amorcé? et monter --bind un autre utilisateur comme moi-même un autre exemple.
Un chroot jail ou container exécute un processus dans une sous-arborescence de l'arborescence de répertoires du système. Cela peut être utile pour exécuter un programme à accès restreint, par ex. exécuter un serveur réseau avec accès uniquement à ses propres fichiers et aux fichiers qu'il dessert, mais pas aux autres données stockées sur le même ordinateur). Une limitation de chroot est que le programme est limité à un sous-arbre: il ne peut pas accéder à des sous-arbres indépendants. Les montures Bind permettent de greffer d'autres sous-arbres sur cet arbre principal. Cela les rend fondamentaux pour l'utilisation la plus pratique des conteneurs sous Linux.
Par exemple, supposons qu'une machine exécute un service /usr/sbin/somethingd
qui ne devrait avoir accès qu'aux données sous /var/lib/something
. La plus petite arborescence de répertoires contenant ces deux fichiers est la racine. Comment limiter le service? Une possibilité consiste à créer des liens physiques vers tous les fichiers dont le service a besoin (au moins /usr/sbin/somethingd
et plusieurs bibliothèques partagées) sous /var/lib/something
. Mais c'est lourd (les liens durs doivent être mis à jour chaque fois qu'un fichier est mis à niveau), et ne fonctionne pas si /var/lib/something
et /usr
se trouvent sur différents systèmes de fichiers. Une meilleure solution consiste à créer une racine ad hoc et à la remplir à l'aide de montures:
mkdir /run/something
cd /run/something
mkdir -p etc/something lib usr/lib usr/sbin var/lib/something
mount --bind /etc/something etc/something
mount --bind /lib lib
mount --bind /usr/lib usr/lib
mount --bind /usr/sbin usr/sbin
mount --bind /var/lib/something var/lib/something
mount -o remount,ro,bind etc/something
mount -o remount,ro,bind lib
mount -o remount,ro,bind usr/lib
mount -o remount,ro,bind usr/sbin
chroot . /usr/sbin/somethingd &
Linux monter les espaces de noms généraliser les chroots. Les montages de liaison permettent aux espaces de noms d'être remplis de manière flexible. Voir Faire en sorte qu'un processus lise un fichier différent pour le même nom de fichier pour un exemple.
Une autre utilisation des chroots consiste à installer une distribution différente dans un répertoire et à exécuter des programmes à partir de celui-ci, même lorsqu'ils nécessitent des fichiers sur des chemins codés en dur qui ne sont pas présents ou ont un contenu différent sur le système de base. Cela peut être utile, par exemple, pour installer une distribution 32 bits sur un système 64 bits qui ne prend pas en charge les packages mixtes, pour installer des versions plus anciennes d'une distribution ou d'autres distributions pour tester la compatibilité, pour installer une version plus récente pour tester les dernières fonctionnalités tout en maintenant un système de base stable, etc. Voir Comment exécuter des programmes 32 bits sur un Debian/Ubuntu 64 bits? pour un exemple sur Debian/Ubuntu.
Supposons que vous ayez une installation des derniers packages de votre distribution dans le répertoire /f/unstable
, où vous exécutez des programmes en basculant vers ce répertoire avec chroot /f/unstable
. Pour rendre les répertoires personnels disponibles à partir de ces installations, liez-les à monter dans le chroot:
mount --bind /home /f/unstable/home
Le programme schroot le fait automatiquement.
Lorsque vous montez un système de fichiers sur un répertoire, cela masque ce qui se trouve derrière le répertoire. Les fichiers de ce répertoire deviennent inaccessibles jusqu'à ce que le répertoire soit démonté. Étant donné que les montages de liaison BSD nullfs et Linux fonctionnent à un niveau inférieur à l'infrastructure de montage, un montage nullfs ou un montage de liaison d'un système de fichiers expose des répertoires cachés derrière les sous-montages dans l'original.
Par exemple, supposons que vous ayez un système de fichiers tmpfs monté sur /tmp
. S'il y avait des fichiers sous /tmp
lorsque le système de fichiers tmpfs a été créé, ces fichiers peuvent toujours rester, effectivement inaccessibles mais occupant de l'espace disque. Courir
mount --bind / /mnt
(Linux) ou
mount -t nullfs / /mnt
(FreeBSD) pour créer une vue du système de fichiers racine à /mnt
. Le répertoire /mnt/tmp
est celui du système de fichiers racine.
Certains serveurs NFS (tels que le serveur NFS du noyau Linux avant NFSv4) annoncent toujours l'emplacement réel du répertoire lorsqu'ils exportent un répertoire. Autrement dit, lorsqu'un client demande server:/requested/location
, le serveur dessert l'arborescence à l'emplacement /requested/location
. Il est parfois souhaitable de permettre aux clients de demander /request/location
mais sert en fait des fichiers sous /actual/location
. Si votre serveur NFS ne prend pas en charge le service d'un autre emplacement, vous pouvez créer un montage de liaison pour la demande attendue, par exemple.
/requested/location *.localdomain(rw,async)
dans /etc/exports
et les éléments suivants dans /etc/fstab
:
/actual/location /requested/location bind bind
Parfois, vous souhaitez créer un lien symbolique pour créer un fichier /some/where/is/my/file
apparaît sous /else/where
, mais l'application qui utilise file
développe les liens symboliques et rejette /some/where/is/my/file
. Un montage lié peut contourner cela: bind-mount /some/where/is/my
à /else/where/is/my
, puis realpath
signalera /else/where/is/my/file
être sous /else/where
, pas sous /some/where
.
Si vous utilisez des montages de liaison, vous devez prendre soin des applications qui traversent l'arborescence du système de fichiers de manière récursive, telles que les sauvegardes et l'indexation (par exemple, pour créer une base de données Locate ).
Habituellement, les montages de liaison doivent être exclus des traversées de répertoires récursives, de sorte que chaque arborescence de répertoires n'est parcourue qu'une seule fois, à l'emplacement d'origine. Avec bindfs et nullfs, configurez l'outil de traversée pour ignorer ces types de système de fichiers, si possible. Les montages de liaison Linux ne peuvent pas être reconnus comme tels: le nouvel emplacement est équivalent à l'original. Avec les montages de liaison Linux ou avec des outils qui ne peuvent exclure que les chemins et non les types de système de fichiers, vous devez exclure les points de montage des montages de liaison.
Traversées qui s'arrêtent aux limites du système de fichiers (par exemple find -xdev
, rsync -x
, du -x
,…) S'arrêtera automatiquement lorsqu'ils rencontreront un point de montage bindfs ou nullfs, car ce point de montage est un système de fichiers différent. Avec les montages de liaison Linux, la situation est un peu plus compliquée: il n'y a une limite de système de fichiers que si le montage de liaison greffe un autre système de fichiers, pas s'il greffe une autre partie du même système de fichiers.
Les montages de liaison fournissent une vue d'une arborescence de répertoires à un emplacement différent. Ils exposent les mêmes fichiers, éventuellement avec différentes options de montage et (avec bindfs) des propriétaires et des autorisations différents. Les systèmes de fichiers qui présentent une vue modifiée d'une arborescence de répertoires sont appelés systèmes de fichiers en superposition ou systèmes de fichiers empilables . Il existe de nombreux autres systèmes de fichiers de superposition qui effectuent des transformations plus avancées. Voici quelques exemples courants. Si votre cas d'utilisation souhaité n'est pas couvert ici, vérifiez le référentiel des systèmes de fichiers Fuse .
bindfs -r
, juste un peu plus léger.nion mounts - présente plusieurs systèmes de fichiers (appelés branches ) sous un même répertoire: si tree1
contient foo
et tree2
contient bar
puis leur vue d'union contient à la fois foo
et bar
. Les nouveaux fichiers sont écrits dans une branche spécifique ou dans une branche choisie selon des règles plus complexes. Il existe plusieurs implémentations de ce concept, notamment: