Linux에서 2 개의 디렉토리가 동일한 파티션에서 호스팅되는지 확인


9

/my/dir같은 파티션에 있는지 어떻게 확인할 수 /있습니까?

이것은 스크립트 내 통합을위한 것입니다. 바인드 마운트는 올바르게 처리해야합니다. POSIX 호환 솔루션을 환영합니다.


“바인드 마운트는 올바르게 취급해야합니다.” 그러나 무엇이 옳다고 생각합니까? 귀하의 질문은 어느 쪽이든 해석 될 수 있습니다.
Gilles 'SO- 악마 그만해'

@Gilles 원래 제목에서 "mounted"대신 "hosted"를 작성했으며 누군가 IMHO 혼란을 추가하여 편집했습니다. 그러나 내 질문 본문은 "동일한 파티션에", 즉 두 파일 / 디렉토리에 액세스하는 데 사용 된 경로 나 마운트 포인트에 관계없이 동일한 물리적 파티션에 있다는 것입니다.
Totor

답변:


6

stat로 확인할 수 있습니다.

$ stat -c '%d %m' /proc/sys/
3 /proc

장치 번호와 디렉토리가 마운트 된 위치를 표시합니다.


1
멋지지만 stat쉘 명령은 POSIX가 아닙니다 ...
Totor

아니? 당신은 어떻게 알 수 있습니까?

하지에서 이 목록 .
Totor

오, 나빠 그러나 다음에는이 링크를 미리 보여줍니다.

5

다음 명령은 파일을 포함하는 마운트 지점의 고유 한 이름을 제공합니다 $file.

df -P -- "$file" | awk 'NR==2 {print $1}'

이것은 모든 POSIX 시스템 에서 작동 합니다. 이 -P옵션은 예측 가능한 형식을 적용합니다. 두 번째 줄의 첫 번째 필드는“파일 시스템 이름”입니다. 따라서 두 파일이 동일한 마운트 지점에 있는지 확인하려면 다음을 수행하십시오.

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

또는 몇 가지 프로세스 호출을 저장하려면 다음을 수행하십시오.

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

일부 운영 체제는 볼륨 이름에 공백이있을 수 있습니다. df이 경우 출력 을 구문 분석하는 완전히 신뢰할 수있는 방법은 없습니다 .

후드에서에서 st_dev반환 된 필드로 파일을 포함하는 파일 시스템을 식별 할 수 있습니다 stat. 쉘 스크립트에서 이것을 수행하는 휴대용 방법은 없습니다. 일부 시스템에는 stat유틸리티가 있지만 구문은 다양합니다.

  • 포함되지 않은 Linux, Cygwin 또는 GNU coreutils가있는 기타 시스템에서 호출 stat하면 st_dev필드 가보고 됩니다 stat -c %D -- "$file".
  • 일부 BusyBox 설치에는 statGNU coreutils와 호환되는 파일이 포함되어 있습니다. 다른 사람들은 선택 stat%c여지 가 없습니다 . 사용할 수는 stat -t -- "$file" | awk '{print $8}'있지만 파일 이름에 공백이 포함되어 있지 않거나 stat -t -- "$file" | awk 'END {print $(NF-8)}'임의의 파일 이름을 처리하지만 나중에 stat출력 에 필드를 추가 하지 않는 경우에만 작동합니다 .
  • BSD 시스템에는 다른 stat유틸리티 가 필요합니다 stat -f %d -- "$file".
  • Solaris, AIX 및 기타는 stat유틸리티 가 없습니다 .

Perl을 사용할 수 있다면

perl -e 'print ((stat($ARGV[0]))[0])' -- "$file"

그리고 비교를하기 위해 :

perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- "$file1" "$file2"

원하는 결과가 명확하지 않은 경우가 있습니다. 예를 들어, 리눅스의 바인드 마운트와, 후 mount --bind /foo /bar, /foo/bar같은 파일 시스템으로 간주됩니다. 두 파일이 실제로 동일한 장치에있을 수는 있지만 항상 알 수는 없습니다. 예를 들어, 파일이 두 개의 다른 네트워크 마운트에있는 경우 클라이언트는 서버가 다른 파일 시스템을 내보내는 지 여부를 알 수 없습니다.

파일이 디렉토리이고 파일에 쓸 수있는 경우 다른 방법은 임시 파일을 작성하고 하드 링크를 작성하는 것입니다. 이것은 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언제나처럼 언젠가 심볼릭 링크를 장치 이름을 제공하지 않지만 /dev/disk/by-uuid/ca09b761-ae1b-450f-8a46-583327b48fb4제작 df하지 신뢰성. 지금까지 신뢰할 수있는 유일한 옵션은 stat기반 솔루션을 사용하는 것입니다.
Totor

@Totor 그것은 중요하지 않습니다 : 어떤 이름 df이 장치에 대해보고 하든 그것은 두 호출간에 일관성이 있으므로 비교해도 좋습니다.
Gilles 'SO- 악마 그만'

아니요, 작동하지 않습니다. 테스트했습니다. 여기 데비안 위지에, 하나의 df보고서 /dev/sda6와는 /dev/disk/by-uuid/ca09b...모두 동일한 장치를 참조하지만, 다른 지점을 탑재합니다. 각 마운트 지점에서 파일을 시도 할 때 문자열 비교 테스트는 분명히 실패합니다.
Totor

@Totor 일반적으로 동일한 블록 장치를 두 번 마운트 할 수 없습니다. 내 대답에서 알 수 있듯이 바인드 마운트와 같이 뚜렷한 것으로보고되거나 그렇지 않을 수있는 코너 케이스가 있습니다.
Gilles 'SO- 악의를 멈춰라'

: 그러나 그것은 데비안 짜기와 위지에 완벽하게 작동 mount /dev/sda6 /mnt1다음에 mount /dev/sda6 /mnt2매력처럼 작동합니다. cat /proc/mounts그것으로 괜찮습니다. 그러나 Wheezy 이후에만 루트 파일 시스템의 장치로 /dev/disk/by-uuid/ca09b...표시됩니다 df. 또한 시도는이 simlink를 사용하거나 탑재 UUID=ca09b...구문보다 다른 것을 보여주는 끝나지 않는 마운트 /dev/sda6에서을 df(나는 그것이 부팅 과정에서 무슨 짓을 재현하는 방법을 몰라,하지만 여기에 문제가되지 않습니다).
Totor

4
test $(df -P $path1 $path2 | awk '{if (NR!=1) {print $6}}' | uniq | wc -l) -eq 1

여러 경로에서 작동합니다.


출력을 분석하는 것이 항상 좋은 생각df아닙니다 .
Joseph R.

1
@Totor $6장치 이름 ( $1)이 아닌 마운트 포인트 ( )를 확인 하므로 문제가되지 않습니다.
n.st

1
@JosephR POSIX에있는 것이 최고입니다. n.st : 왜 첫 번째 필드를 확인하지 않습니까? 장치에 액세스하는 데 사용 된 경로는 중요하지 않습니다. 동일한 마운트 포인트 인 경우 출력이 일관됩니다.
Gilles 'SO- 악의를 멈춰라'

바인드 마운트에서는 작동하지 않습니다.
Totor

0

POSIX에서 사용할 수있는 가장 확실한 솔루션 은 stat (2) 함수가 제공 하는 파일의 장치 ID를 비교하는 것입니다 .

펄은 Gilles가 지적한 것과 비슷한 통계 기능 을 가지고 있습니다 .

perl -e 'exit((stat($ARGV[0]))[0] != (stat($ARGV[1]))[0])' -- file1 file2

"POSIX 방식"은 다음과 같은 C 프로그램을 사용하는 것입니다.

./checksamedev file1 file2

소스 코드는 다음과 같습니다.

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

두 파일의 장치 ID가 같으면 동일한 파일 시스템에서 호스트됩니다.이 경우 위의 명령은 0을 반환합니다 (그렇지 않으면 다른 값). 로 확인하십시오 echo $?.

이것은 바인드 마운트에서는 잘 작동하지만 네트워크 마운트에서는 그렇지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.