Jak uzyskać punkt montowania systemu plików zawierającego dany plik

13

Szukam szybkiego sposobu znalezienia punktu podłączenia systemu plików zawierającego dany PLIK. Czy jest coś prostszego lub bardziej bezpośredniego niż moje rozwiązanie poniżej?

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

Podobne pytanie „ Czy istnieje polecenie, aby zobaczyć, gdzie jest zamontowany dysk? ” Używa węzła urządzenia bieżącego dysku jako danych wejściowych, a nie dowolnego pliku z dysku ...

Stu
źródło
1
Ostateczną trrozmowę możesz zlikwidować, używającawk -F'% '...
Joseph R.

Odpowiedzi:

6

Możesz zrobić coś takiego

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

lub nawet

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

Ponieważ awkdomyślnie dzieli się na białe znaki, nie trzeba ich określać, -Fa także nie trzeba przycinać białych znaków tr. Na koniec, określając numer zainteresowania ( NR==2), którego możesz również pozbyć się tail.

terdon
źródło
2. zaklęcie działało od razu po wyjęciu z pudełka, podczas gdy musiałem zmienić 2 na 3 w pierwszym. schludnie
Stu
@Gilles, dzięki za edycję. Jedno pytanie, drugie powinno działać nawet bez -Pprawa? We wszystkich przypadkach ostatnim drukowanym polem awkpowinien być dysk.
terdon
@Stu prawdopodobnie dlatego, że nie użyłem -Popcji, którą właśnie dodał Gilles.
terdon
1
@terdon Tak, rzeczywiście, ostatnie pole ostatniej linii jest takie samo bez -P. Niemniej jednak polecam zawsze używać -Ppodczas analizowania danych wyjściowych df, jest to łatwiejsze niż sprawdzanie, czy to konkretne użycie jest bezpieczne.
Gilles „SO- przestań być zły”
miły. jeśli potrzebujesz teraz wpisu / dev dla $ {FILE} (z jakiegoś powodu)mount | grep " on $(df -P ${FILE} | awk 'END{print $NF}') type" | awk '{print $1}'
niezsynchronizowany
16

W GNU / Linux, jeśli masz GNU statz Coreutils 8.6 lub nowszy, możesz:

stat -c %m -- "$file"

Inaczej:

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

Twoje podejście jest prawidłowe, ale zakładamy, że punkt montowania nie zawiera spacji,%, nowej linii lub innych niedrukowalnych znaków, możesz to nieco uprościć dzięki nowszym wersjom GNU df(8.21 lub nowszym):

df --output=target FILE | tail -n +2
Stéphane Chazelas
źródło
Mój dfnie rozpoznaje --outputopcji.
Joseph R.
@JosephR. czy jest to wersja 8.21 lub wyższa?
terdon
@terdon Nie, to wersja 8.13.
Joseph R.
2
@JosephR. Stephane wyjaśnia w swojej odpowiedzi, że jest to cecha GNU df> = 8,21.
terdon
@terdon Przepraszam, musiałem to przegapić podczas przeglądania.
Joseph R.
8

W przypadku Linuksa znaleźliśmy specjalnie zaprojektowany do tego celu program ut-linux

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

Zauważ, że może zostać zwrócony jakiś losowy punkt montowania, jeśli istnieje kilka montowań powiązań. Korzystanie dfma ten sam problem.

rudimeier
źródło
2
Działa poprawnie nawet z plikami, które są w podwoluminach.
ceremcem
3

Ponieważ statzwraca pole „Urządzenie”, byłem ciekawy, jak stat()można wykorzystać wywołanie biblioteki bazowej, aby uzyskać te informacje programowo w sposób zgodny z POSIX.

Ten fragment kodu 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;
}  

Poda identyfikatory głównych i podrzędnych urządzeń dla urządzenia zawierającego plik wymieniony w wierszu poleceń ( argv[1]). Niestety major()i minor()nie są POSIX-em, chociaż strona podręcznika twierdzi, że są one „obecne w wielu innych systemach” oprócz GNU / linux.

Następnie można uzyskać korespondencję między numerem głównym / podrzędnym urządzenia a węzłem urządzenia z np. /proc/diskstatsI odwzorować, z którego można montować punkty /proc/mounts, inaczej. /etc/mtab.

Tak więc narzędzie wiersza polecenia do tego byłoby całkiem proste.

Złotowłosa
źródło
/proc/diskstatsjest tylko dla urządzeń blokowych, przegapisz NFS, proc, bezpiecznik ... Przynajmniej w Linuksie różne punkty montowania mogą mieć tę samą maj + min
Stéphane Chazelas
Nie wiedziałem tego, dzięki. Wydaje się również, że st_devmoże nie zapewniać sposobu na odróżnienie jednej partycji NFS od drugiej. Ktokolwiek naprawdę chce to napisać, będzie musiał wziąć to pod uwagę;)
goldilocks
+1 za bycie maniakiem, który uważasz, że pisanie kodu C jest „prostsze lub bardziej bezpośrednie” niż to, co robił OP :).
terdon
0

Oto więcej kodu C ++, jeśli chcesz to zrobić z 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();
  }

Więcej linków do metod programistycznych

Mark Lakata
źródło