Como obter o ponto de montagem do sistema de arquivos que contém o arquivo especificado

13

Estou procurando uma maneira rápida de encontrar o ponto de montagem do sistema de arquivos que contém um determinado arquivo. Existe algo mais simples ou mais direto do que minha solução abaixo?

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

Uma pergunta semelhante " Existe um comando para ver onde um disco está montado? " Usa o nó do dispositivo do disco atual como entrada e não um arquivo arbitrário do disco ...

Stu
fonte
1
Você pode acabar com a final trchamada utilizandoawk -F'% '...
Joseph R.

Respostas:

6

Você poderia fazer algo como

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

ou mesmo

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

Como as awkdivisões nos espaços em branco, por padrão, não é necessário especificar o -Fe também não é necessário apará-lo tr. Por fim, especificando o número da linha de interesse ( NR==2), você também pode eliminar tail.

terdon
fonte
o segundo encantamento funcionou imediatamente, enquanto eu tive que mudar de 2 para 3 no primeiro. arrumado
Stu
@Gilles, obrigado pela edição. Uma pergunta, a segunda deve funcionar mesmo sem -Pcerto? Em todos os casos, o último campo impresso por awkdeve ser o disco.
terdon
@Stu é provavelmente porque eu não tinha usado a -Popção que Gilles acabou de adicionar.
terdon
1
@terdon Sim, de fato, o último campo da última linha é o mesmo sem -P. No entanto, eu recomendo sempre usar -Pquando você estiver analisando a saída de df, é mais fácil do que verificar se esse uso específico é seguro.
Gilles 'SO- stop be evil'
legais. se você precisar agora a entrada / dev para $ {FILE} (por algum motivo)mount | grep " on $(df -P ${FILE} | awk 'END{print $NF}') type" | awk '{print $1}'
não sincronizado
16

No GNU / Linux, se você possui o GNU statdo coreutils 8.6 ou superior, você pode:

stat -c %m -- "$file"

De outra forma:

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

Sua abordagem é válida, mas assume que o ponto de montagem não contém espaço,%, nova linha ou outros caracteres não imprimíveis; você pode simplificá-lo um pouco com as versões mais recentes do GNU df(8.21 ou superior):

df --output=target FILE | tail -n +2
Stéphane Chazelas
fonte
Meu dfnão reconhece a --outputopção.
11743 Joseph R.
@JosephR. é a versão 8.21 ou superior?
terdon
@terdon Não, é a versão 8.13.
Joseph R.
2
@JosephR. Stephane explica em sua resposta que esse é um recurso do GNU df> = 8.21.
terdon
@terdon Desculpe, deve ter esquecido enquanto deslizava.
Joseph R.
8

Para Linux, temos o findmnt do util-linux feito exatamente para isso

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

Observe que algum tipo de ponto de montagem aleatório pode ser retornado caso haja várias montagens de ligação. O uso dftem o mesmo problema.

rudimeier
fonte
2
Funciona corretamente, mesmo com os arquivos que estão nos subvolumes.
ceremcem
3

Como statretorna um campo "Dispositivo", fiquei curioso para ver como a stat()chamada de biblioteca subjacente poderia ser usada para obter essas informações programaticamente de maneira compatível com POSIX.

Este trecho de código 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;
}  

Fornecerá os IDs principais e secundários do dispositivo que contém o arquivo listado na linha de comando ( argv[1]). Infelizmente, major()e minor()não são POSIX, embora a página de manual afirme que eles estão "presentes em muitos outros sistemas" além do GNU / linux.

Você pode obter uma correspondência entre o número principal / menor do dispositivo e o nó do dispositivo, por exemplo /proc/diskstats, e mapear isso para montar pontos /proc/mounts, também conhecido como. /etc/mtab.

Portanto, um utilitário de linha de comando para fazer isso seria bastante simples.

Cachinhos Dourados
fonte
/proc/diskstatsé apenas para dispositivos de bloco, você vai perder o NFS, proc, fusível ... No Linux, pelo menos, diferentes pontos de montagem pode ter o mesmo maj + min
Stéphane Chazelas
Não sabia disso, thx. Parece também que st_devpode não oferecer uma maneira de distinguir uma partição NFS da outra. Quem realmente quer escrever isso terá que levar isso em conta;)
Goldilocks
+1 por ser um nerd o suficiente para considerar escrever o código C "mais simples ou mais direto" do que o OP estava fazendo :).
terdon
0

Aqui está mais código C ++, se você quiser fazer isso em 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();
  }

Mais links para formas programáticas

Mark Lakata
fonte