10TB 이상의 디렉터리에서 사용자 10명의 소유자 UID를 선택적으로 변경합니다.

10TB 이상의 디렉터리에서 사용자 10명의 소유자 UID를 선택적으로 변경합니다.

100명 이상의 사용자와 공용 폴더를 보유하는 10TB 이상의 NFS/home이 있습니다. 사용자 중 10명의 사용자 이름과 UID를 변경해야 합니다. 처음에는 다음 명령을 실행하고 싶었습니다.

 find /home -uid 812 -exec chown NEWUSER {} \;

이제 문제는 10TB 전체를 한 번에 처리하고 uid 812에서 찾은 모든 파일을 내가 원하는 NEWUSER로 변경한다는 것입니다. 그러나 이 작업은 꽤 오랜 시간이 걸리며 해당 사용자에 대해서만 수행됩니다. 그러면 다른 9명의 사용자에 대해 명령을 다시 실행해야 하므로 꽤 오랜 시간이 걸립니다*9.

내가 스크립트를 좋아하지 않는다는 사실을 제외하면 스크립트가 여기서 친구가 될 것이라고 상상하지만 어디서부터 시작해야 할지 모르겠습니다. 이 find명령을 사용하여 /home의 모든 파일을 확인하고 싶습니다 . 그 다음에:

IF FILEOWNER IS 813 then NEWOWNER IS NEWUSER1
IF FILEOWNER IS 814 then NEWOWNER IS NEWUSER2

... 등.

10GB의 데이터를 10번 스캔하지 않고 한 번만 스캔할 수 있는 방법이 있다고 생각하시나요?

답변1

하다모든 일사용 find.

find /home ! -type l \( \
     -uid 812 -exec chown NEWUSER {} + \
  -o -uid 813 -exec chown ANOTHER {} + \
  -o -uid 814 -exec chown SOMEONE {} + \
  -o -uid 815 -exec chown SOMEGUY {} + \)

디렉토리 구조 탐색. 모든 것이 chown완료되었습니다.

chown심볼릭 링크의 대상에 적용되는 심볼릭 링크는 제외됩니다 . 일부 시스템에서는 를 사용하여 심볼릭 링크의 소유자를 변경할 수 있습니다 chown -h. 여기에 추가 -h하고 제거 할 수 있습니다 ! -type l.

setuid파일 중 하나라도 있으면 엉망이 될 것입니다 . 이것도 처리할 수 있어요사용 find.

find중요한 것은 파일을 찾는 것이 아니라 표현식을 평가하는 것입니다. 예, find물론 파일을 찾을 수 있지만 실제로는 부작용일 뿐입니다.

— 유닉스 전동 공구

답변2

첫째, 전체 10TB를 실제로 스캔할 필요가 없고 디렉토리 구조만 스캔할 필요가 있으므로 기본 조회를 수행하는 것이 생각보다 나쁘지 않습니다.

둘째, 기본 작업을 수행하고 동시에 10개를 모두 시작하면 읽기 캐싱으로 인해 더 나은 성능을 얻을 수 있습니다.

아니면 이렇게 할 수도 있습니다 find /home -uid 812 -o uid 813 -o...-printf '%U:%p\0'| sed -zre 's!["$]!\\&!g' -e 's/^812:(.*)$/chown NEWUSER1 "\1"/'e -e 's/^813

주요 문제를 찾은 것 같지만 sed eval은 항상 위험합니다. GNU sed를 사용하지 않는 경우 출력을 셸로 파이프할 수 있습니다.

이것은 참조를 더 잘 처리하기 위해 Gnu 도구를 사용하는 더 깔끔한 버전입니다.

find /home -uid 812 -o uid 813 -o ` ... ` -printf '%U:' -print0| \
sed -zre "s/'/'\''/g" \
   -e 's/^812:(.*)$/chown NEWUSER1 '"'\1'/e" \
   -e 's/^813:(.*)$/chown NEWUSER2 '"'\1'/e" \
   ...

작동 방식:

조회의 첫 번째 부분은 ORed uid 검사입니다. 가장 중요한 것은 printf(또는 두 번째 버전의 printf 및 print0)입니다. 이는 숫자 uid, 콜론, 파일 이름을 c 이스케이프(두 번째 버전에서는 이스케이프되지 않음)로 인쇄합니다. 버전) 및 각 파일에 대한 null 값입니다. 그런 다음 sed는 null 구분 기호와 확장 정규식을 사용하여 달러 기호와 큰따옴표를 인용합니다. 그런 다음 각 사용자는 uid 및 콜론으로 구분된 파일 이름과 일치하는 표현식을 사용하여 쉘 명령줄을 생성하여 chown을 실행하고 쉘을 사용하여 이를 평가합니다. 아마도 printf에서 이스케이프 목록을 확인하는 데 몇 분을 더 소비해야 했지만 s 명령에서 e 플래그 없이 테스트하면 시작하기에 충분합니다. 두 번째 버전에서 이스케이프된 유일한 문자는 작은따옴표입니다. 이스케이프하지 않는 이유는 엄격하게 정의된 헤더 이후에 null을 제외한 모든 문자가 특별한 의미 없이 전달되도록 허용되므로 이스케이프를 제거할 필요가 없기 때문입니다.

관련 정보