Come ottenere il punto di montaggio del filesystem contenente un determinato file


13

Sto cercando un modo rapido per trovare il punto di montaggio del file system contenente un determinato FILE. C'è qualcosa di più semplice o più diretto della mia soluzione di seguito?

df -h FILE |tail -1 | awk -F% '{print $NF}' | tr -d ' '

Una domanda simile " Esiste un comando per vedere dove è montato un disco? " Utilizza il nodo del dispositivo del disco corrente come input e non un file arbitrario dal disco ...


1
Puoi eliminare l'ultima trchiamata usandoawk -F'% '...
Joseph R.,

Risposte:


6

Potresti fare qualcosa del genere

df -P FILE | awk 'NR==2{print $NF}'

o anche

df -P FILE | awk 'END{print $NF}'

Dal momento che si awkdivide su spazi bianchi per impostazione predefinita, non è necessario specificare il -Fe non è nemmeno necessario tagliare lo spazio bianco tr. Infine, specificando il numero di riga di interesse ( NR==2) puoi anche eliminare tail.


il secondo incantesimo ha funzionato immediatamente, mentre ho dovuto cambiare da 2 a 3 nel primo. pulito
Stu

@Gilles, grazie per la modifica. Una domanda, la seconda dovrebbe funzionare anche senza -Pgiusto? In tutti i casi, l'ultimo campo stampato awkdovrebbe essere il disco.
terdon

@Stu probabilmente perché non avevo usato l' -Popzione che Gilles ha appena aggiunto.
terdon

1
@terdon Sì, infatti, l'ultimo campo dell'ultima riga è lo stesso senza -P. Tuttavia, ti consiglio di utilizzare sempre -Pquando analizzi l'output di df, è più facile che verificare che questo particolare utilizzo sia sicuro.
Gilles 'SO- smetti di essere malvagio' l'

simpatico. se è necessario ora la voce / dev per $ {FILE} (per qualche motivo)mount | grep " on $(df -P ${FILE} | awk 'END{print $NF}') type" | awk '{print $1}'
non sincronizzato

16

Su GNU / Linux, se hai GNU statda coreutils 8.6 o successivo, puoi fare:

stat -c %m -- "$file"

Altrimenti:

mount_point_of() {
  f=$(readlink -e -- "$1") &&
    until mountpoint -q -- "$f"; do
      f=${f%/*}; f=${f:-/}
    done &&
    printf '%s\n' "$f"
}

Il tuo approccio è valido ma presuppone che il punto di montaggio non contenga spazio,%, newline o altri caratteri non stampabili, puoi semplificarlo leggermente con le versioni più recenti di GNU df(8.21 o successive):

df --output=target FILE | tail -n +2

Il mio dfnon riconosce l' --outputopzione.
Joseph R.,

@JosephR. è la versione 8.21 o successiva?
Terdon

@terdon No, è la versione 8.13.
Joseph R.,

2
@JosephR. Stephane spiega nella sua risposta che questa è una caratteristica di GNU df> = 8.21.
terdon

@terdon Mi dispiace averlo perso durante la scrematura.
Joseph R.,

8

Per Linux abbiamo trovato da util-linux esattamente fatto per questo

findmnt -n -o TARGET --target /path/to/FILE

Si noti che un certo tipo di mountpoint casuale può essere restituito nel caso in cui siano presenti diversi attacchi di bind. L'utilizzo dfha lo stesso problema.


2
Funziona correttamente anche con i file che si trovano nei sottovolumi.
ceremcem,

3

Poiché statrestituisce un campo "Dispositivo", ero curioso di vedere come la stat()chiamata alla libreria sottostante potesse essere utilizzata per ottenere queste informazioni a livello di codice in modo conforme a POSIX.

Questo frammento di codice C:

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>

int main (int argc, const char *argv[]) {
    struct stat info;
    stat(argv[1], &info);
    printf("min: %d maj: %d\n",
        minor(info.st_dev),
        major(info.st_dev)
    );

    return 0;
}  

Fornirà gli ID dei dispositivi principali e secondari per il dispositivo contenente il file elencato nella riga di comando ( argv[1]). Sfortunatamente, major()e minor()non sono POSIX, sebbene la pagina man affermi che sono "presenti su molti altri sistemi" oltre a GNU / linux.

È quindi possibile ottenere una corrispondenza tra il numero maggiore / minore del dispositivo e il nodo del dispositivo da, ad esempio /proc/diskstats, e mappare da cui montare i punti /proc/mounts, ovvero. /etc/mtab.

Quindi un'utilità della riga di comando per farlo sarebbe piuttosto semplice.


/proc/diskstatsè solo per i dispositivi a blocchi, mancherai NFS, proc, miccia ... Su Linux almeno, diversi mountpoint possono avere lo stesso maj + min
Stéphane Chazelas,

Non lo sapevo, grazie. Sembra anche che st_devpotrebbe non fornire un modo per distinguere una partizione NFS da un'altra. Chiunque voglia davvero scrivere questo dovrà tenerne conto;)
Riccioli d'oro,

+1 per essere abbastanza geek da considerare di scrivere il codice C "più semplice o più diretto" di quello che stava facendo l'OP :).
Terdon

0

Ecco altro codice C ++ se vuoi farlo da C ++ ...

  #include <boost/filesystem.hpp>
  #include <sys/stat.h>

  /// returns true if the path is a mount point
  bool Stat::IsMount(const std::string& path)
  {

      if (path == "") return false;
      if (path == "/") return true;

      boost::filesystem::path path2(path);
      auto parent = path2.parent_path();

      struct stat sb_path;
      if (lstat(path.c_str(), &sb_path) == -1) return false; // path does not exist
      if (!S_ISDIR(sb_path.st_mode)) return false; // path is not a directory

      struct stat sb_parent;
      if (lstat(parent.string().c_str(), &sb_parent) == -1 ) return false; // parent does not exist

      if (sb_path.st_dev == sb_parent.st_dev) return false; // parent and child have same device id

      return true;

  }

  /// returns the path to the mount point that contains the path
  std::string Stat::MountPoint(const std::string& path0)
  {
      // first find the first "real" part of the path, because this file may not exist yet
      boost::filesystem::path path(path0);
      while(!boost::filesystem::exists(path) )
      {
          path = path.parent_path();
      }

      // then look for the mount point
      path = boost::filesystem::canonical(path);
      while(! IsMount(path.string()) )
      {
          path = path.parent_path();
      }

      return path.string();
  }

Più collegamenti per vie programmatiche

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.