Como posso verificar se /my/dir
está na mesma partição que /
?
Isto é para integração dentro de um script. As montagens de ligação devem ser manuseadas corretamente. As soluções compatíveis com POSIX são bem-vindas.
Como posso verificar se /my/dir
está na mesma partição que /
?
Isto é para integração dentro de um script. As montagens de ligação devem ser manuseadas corretamente. As soluções compatíveis com POSIX são bem-vindas.
Respostas:
Você pode verificar isso com stat:
$ stat -c '%d %m' /proc/sys/
3 /proc
Mostra o número do dispositivo e onde seu diretório foi montado.
stat
comando shell não é POSIX ...
O comando a seguir fornece um nome exclusivo para o ponto de montagem que contém o arquivo $file
:
df -P -- "$file" | awk 'NR==2 {print $1}'
Isso funciona em qualquer sistema POSIX . A -P
opção impõe um formato previsível; o primeiro campo da segunda linha é o "nome do sistema de arquivos". Portanto, para verificar dois arquivos estão no mesmo ponto de montagem:
if [ "$(df -P -- "$file1" | awk 'NR==2 {print $1}')" = \
"$(df -P -- "$file2" | awk 'NR==2 {print $1}')" ]; then
echo "$file1 and $file2 are on the same filesystem" ; fi
Ou, para salvar algumas invocações de processo:
if df -P -- "$file1" "$file2" |
awk 'NR!=1 {dev[NR] = $1} END {exit(dev[2] != dev[3])}'; then
echo "$file1 and $file2 are on the same filesystem" ; fi
Alguns sistemas operacionais podem ter espaços nos nomes dos volumes. Não há uma maneira completamente confiável de analisar a df
saída neste caso.
Sob o capô, você pode identificar o sistema de arquivos que contém um arquivo pelo st_dev
campo retornado por stat
. Não há maneira portátil de fazer isso a partir de um script de shell. Alguns sistemas têm um stat
utilitário, mas sua sintaxe varia:
stat
relata o st_dev
campo quando chamado como stat -c %D -- "$file"
.stat
compatível com os coreutils GNU. Outros têm stat
sem a %c
opção; você pode usar, stat -t -- "$file" | awk '{print $8}'
mas isso só funcionará se o nome do arquivo não contiver espaço em branco ou stat -t -- "$file" | awk 'END {print $(NF-8)}'
lidar com nomes arbitrários de arquivos, mas não com futuras adições de campos à stat
saída.stat
utilitário diferente que requer stat -f %d -- "$file"
.stat
utilidade.Se o Perl estiver disponível, você poderá usar
perl -e 'print ((stat($ARGV[0]))[0])' -- "$file"
e para fazer a comparação:
perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- "$file1" "$file2"
Observe que existem alguns casos de canto em que o resultado desejado não é claro. Por exemplo, com montagens bind do Linux, depois de mount --bind /foo /bar
, /foo
e /bar
são considerados o mesmo sistema de arquivos. Sempre é possível que os dois arquivos estejam realmente localizados no mesmo dispositivo, mas você nunca saberá: por exemplo, se os arquivos estiverem em duas montagens de rede diferentes, o cliente não terá como saber se o servidor está exportando sistemas de arquivos diferentes.
Se os arquivos são diretórios e você pode gravá-los, outro método é criar um arquivo temporário e tentar criar um link físico. Este relata um resultado negativo nas montagens de ligação do Linux.
tmp1=$(TMPDIR=$dir1 mktemp)
tmp2=$(TMPDIR=$dir2 mktemp)
if ln -f -- "$tmp1" "$tmp2"; then
echo "$dir1 and $dir2 are on the same filesystem, which supports hard links"
fi
rm -f "$tmp1" "$tmp2"
df
nem sempre fornece o nome do dispositivo, mas às vezes um link simbólico para ele, como /dev/disk/by-uuid/ca09b761-ae1b-450f-8a46-583327b48fb4
tornar df
não confiável. Até agora, a única opção confiável é usar uma stat
solução baseada em.
df
relatado para o dispositivo, ele é consistente entre as duas invocações; portanto, é bom fazer uma comparação.
df
relatório /dev/sda6
e /dev/disk/by-uuid/ca09b...
, ambos referentes ao mesmo dispositivo, mas com pontos de montagem diferentes. O teste de comparação de cadeias obviamente falha ao tentar com arquivos de cada ponto de montagem.
mount /dev/sda6 /mnt1
seguido de mount /dev/sda6 /mnt2
trabalhos como um encanto. cat /proc/mounts
está bem com isso. No entanto, somente a partir do Wheezy /dev/disk/by-uuid/ca09b...
é mostrada df
como o dispositivo para o sistema de arquivos raiz. Tentativas adicionais de montá-lo usando este simlink ou a UUID=ca09b...
sintaxe mount não terminam mostrando nada além de /dev/sda6
in df
(não sei como reproduzir o que ele fez durante o processo de inicialização, mas essa não é a preocupação aqui).
test $(df -P $path1 $path2 | awk '{if (NR!=1) {print $6}}' | uniq | wc -l) -eq 1
Funciona com qualquer número de caminhos.
df
é não sempre uma boa idéia .
$6
), não o nome do dispositivo ( $1
), para que não seja um problema.
A melhor solução infalível disponível no POSIX é a comparação dos IDs de dispositivos dos arquivos fornecidos pela função stat (2) .
Perl tem uma função stat semelhante à que Gilles apontou :
perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- file1 file2
mas a "maneira POSIX" é usar um programa C como:
./checksamedev file1 file2
qual código fonte é o seguinte:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
struct stat s1, s2;
if( argc==3 && lstat(argv[1], &s1)==0 && lstat(argv[2], &s2)==0 )
return !(s1.st_dev == s2.st_dev);
return 2;
}
Se os IDs de dispositivo dos dois arquivos forem iguais, eles serão hospedados no mesmo sistema de arquivos; nesse caso, os comandos acima retornarão 0 (outro valor, caso contrário). Verifique com echo $?
.
Isso funciona bem com montagens de ligação, mas provavelmente não funcionará com montagens de rede.