Як отримати точку монтажу файлової системи, що містить даний файл


13

Я шукаю швидкий спосіб знайти точку кріплення файлової системи, що містить заданий ФАЙЛ. Чи є щось більш просте чи пряме, ніж моє рішення нижче?

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

Аналогічне запитання " Чи є команда побачити, де встановлений диск? " Використовує вузол пристрою поточного диска як вхід, а не довільний файл з диска ...


1
Ви можете піти з остаточного trдзвінка, скориставшисьawk -F'% '...
Джозеф Р.

Відповіді:


6

Ви могли зробити щось подібне

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

або навіть

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

Оскільки awkрозділяється на пробіли (місця) за замовчуванням, вам не потрібно вказувати, -Fі вам також не потрібно обрізати пробіли tr. Нарешті, вказавши номер рядка, що цікавить ( NR==2), який ви також можете усунути tail.


2-я заклинання працювала нестандартно, тоді як мені довелося змінити 2 на 3 в першій. акуратний
Ст

@Gilles, дякую за редагування Одне питання, друге має працювати навіть без -Pправа? У всіх випадках останнім полем, надрукованим, awkповинен бути диск.
terdon

@ Сюди, мабуть, тому, що я не використовував -Pваріант, який Джилс щойно додав.
тердон

1
@terdon Так, дійсно, останнє поле останнього рядка таке ж і без -P. Тим не менш, я рекомендую завжди використовувати, -Pколи ви аналізуєте вихід df, простіше, ніж перевірити, чи саме це використання є безпечним.
Жил "ТАК - перестань бути злим"

приємно. якщо вам потрібно зараз записати / dev за $ {FILE} (чомусь)mount | grep " on $(df -P ${FILE} | awk 'END{print $NF}') type" | awk '{print $1}'
несинхронізований

16

У GNU / Linux, якщо у вас є GNU statз coreutils 8.6 або вище, ви можете зробити:

stat -c %m -- "$file"

Інакше:

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

Ваш підхід дійсний, але передбачається, що точка монтажу не містить пробілу,%, нової лінії чи інших символів, які не можна роздрукувати, ви можете трохи спростити його з новішими версіями GNU df(8.21 або вище):

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

Моя dfне визнає --outputваріант.
Джозеф Р.

@JosephR. це версія 8.21 або вище?
terdon

@terdon Ні, це версія 8.13.
Джозеф Р.

2
@JosephR. У своїй відповіді Стефан пояснює, що це особливість GNU df> = 8,21.
тердон

@terdon Вибачте, напевно, це пропустили під час скимування.
Джозеф Р.

8

Для Linux ми знайшли findmnt з util-linux, саме для цього створений

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

Зверніть увагу, що якась випадкова точка монтажу може бути повернута у випадку, якщо є кілька кріплень. Використання dfмає ту саму проблему.


2
Працює правильно навіть з файлами, що знаходяться в підтомниках.
ceremcem

3

Оскільки statповертається поле "Пристрій", мені було цікаво побачити, як базовий stat()виклик бібліотеки може бути використаний для отримання цієї інформації програмно в POSIX-сумісний спосіб.

Цей фрагмент коду С:

#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;
}  

Дасть ідентифікатори основних та другорядних пристроїв для пристрою, що містить файл, вказаний у командному рядку ( argv[1]). На жаль, major()і minor()НЕ POSIX, хоча сторінок претензій людини вони «присутня в багатьох інших системах» , крім GNU / Linux.

Потім ви можете отримати відповідність між основним / другорядним номером пристрою та вузлом пристрою, наприклад /proc/diskstats, та зіставити це місце для монтажу точок з /proc/mountsака. /etc/mtab.

Отже, утиліта командного рядка зробити це було б досить просто.


/proc/diskstatsлише для блокових пристроїв, ви пропустите NFS, proc, fuse ... У Linux, принаймні, різні
точки монтажу

Не знав цього, THX. Також здається, що це st_devможе не дати способу відрізнити один розділ NFS від іншого. Хто насправді хоче це написати, повинен це врахувати;)
goldilocks

+1 за те, що вистачає видовища, який ви вважаєте писати код C "простішим або прямішим", ніж те, що робив ОП :).
terdon

0

Ось ще код C ++, якщо ви хочете зробити це з 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();
  }

Більше посилань на програмні способи

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.