본문 바로가기
일반IT/리눅스

🐧 리눅스 find 명령어, 이 글 하나로 완벽하게 마스터하기 (권한, 보안, 백업까지)

by gasbugs 2025. 12. 20.

서버를 운영하다 보면 수만 개의 파일 속에서 특정 조건의 파일을 찾아내야 할 때가 있습니다. 단순히 이름으로 찾는 것을 넘어, "누가 실행할 수 있는지", "보안상 위험한 설정이 되어 있는지", "용량이 큰 파일만 골라내 백업할 것인지" 등의 복잡한 요구사항을 처리해야 하죠.

이때 리눅스 관리자의 '맥가이버 칼'이 되어주는 도구가 바로 find입니다. 오늘은 실무에서 자주 쓰이지만, 정확한 원리를 모르고 쓰면 위험할 수 있는 3가지 핵심 명령어 패턴을 아주 상세하게 뜯어보겠습니다.

 


🔍 첫 번째 미션: 실행 가능한 파일을 찾아라

find . -perm -100

개발 서버나 웹 서버를 관리하다 보면 "권한(Permission)" 문제에 자주 부딪힙니다. 특히 스크립트 파일이 실행되지 않거나, 반대로 실행되어서는 안 될 파일이 실행 권한을 가지고 있어 보안 구멍이 되기도 하죠.

이때 사용하는 명령어가 바로 -perm 옵션입니다.

find . -perm -100

 

이 짧은 명령어에는 비트마스크(Bitmask) 원리가 숨어 있습니다. 하나씩 분해해 볼까요?

1. -perm의 3가지 문법 (이것만 알아도 상위 1%)

많은 분들이 헷갈려 하는 것이 권한 앞의 기호입니다.

  • 100 (기호 없음): 정확하게 일치하는 파일만 찾습니다. 즉, 소유자에게만 실행 권한이 있고 나머지 권한(읽기, 쓰기 등)은 아예 없는(--x------) 파일만 찾습니다. 실무에선 잘 안 씁니다.
  • -100 (하이픈, 중요!): "최소한 이 권한은 가지고 있는" 파일을 찾습니다. 실행 권한(1)만 있다면, 읽기(4)나 쓰기(2) 권한이 추가로 있어도 모두 검색 대상입니다. (AND 조건)
  • /100 (슬래시): 지정한 비트 중 하나라도 켜져 있으면 찾습니다. (OR 조건)

2. 숫자 100의 비밀 (8진수)

리눅스 권한은 3자리 숫자로 표현됩니다. (예: 755, 644)

100을 자리별로 해석하면 다음과 같습니다.

  • 첫 번째 자리 (1): User(소유자) 영역입니다.
    • 4 (Read) + 2 (Write) + 1 (Execute)
    • 즉, "소유자의 실행 권한"을 의미합니다.
  • 두 번째 자리 (0): Group(그룹) 영역입니다. 검사하지 않습니다.
  • 세 번째 자리 (0): Other(기타 사용자) 영역입니다. 검사하지 않습니다.

💡 요약

의미: "현재 디렉토리(.) 아래에서 다른 권한은 신경 쓰지 말고,
파일 주인이 실행할 수 있는(x) 권한이 켜져 있는 모든 파일을 찾아주세요."

 


🛡️ 두 번째 미션: 잠재적 백도어를 제거하라 (SetUID)

find /opt/findme/ -type f -perm -4000 -exec rm {} \;

이 명령어는 시스템 엔지니어나 보안 담당자가 서버 점검 시 가장 눈여겨봐야 할 패턴입니다. 잘못 쓰면 시스템을 망가뜨릴 수 있고, 잘 쓰면 해킹 위협을 제거할 수 있습니다.

1. 4000과 SetUID의 위험성

권한이 4자리(4000)로 늘어났습니다. 맨 앞의 자리는 특수 권한을 의미합니다.

  • 4 (SetUID): 이 파일이 실행될 때, 실행한 사람이 아니라 파일 주인의 권한(ID)으로 실행됩니다.
  • 2 (SetGID): 그룹 권한으로 실행됩니다.
  • 1 (Sticky Bit): 공용 디렉토리에서 본인 파일만 삭제 가능하게 합니다.

왜 위험한가요? 💀

만약 해커가 침입해서 /home/hacker/sh 파일을 만들고, 이 파일의 소유자를 root로 바꾼 뒤 SetUID(4000)를 걸어뒀다고 가정해 봅시다.

나중에 해커가 일반 유저로 로그인해서 이 sh 파일을 실행하면, 그 순간 루트(Root) 권한의 쉘을 얻게 됩니다. 이것이 전형적인 백도어(Backdoor) 수법입니다.

2. 명령어 상세 해부

  • -type f: 디렉토리는 건드리지 않고 일반 파일만 타깃으로 합니다.
  • -perm -4000: 권한이 무엇이든 간에 SetUID 비트가 켜져 있는 파일을 찾습니다.
  • -exec rm {} \;:
    • find가 파일을 찾을 때마다 rm 명령어를 호출합니다.
    • {}는 찾은 파일의 경로로 치환됩니다.
    • \;는 명령어의 끝을 알립니다.

⚠️ 치명적 주의사항

이 명령어는 묻지도 따지지도 않고 삭제(rm)합니다.

하지만 리눅스 시스템에는 passwd, ping, sudo 등 정상적으로 SetUID가 필요한 파일들이 존재합니다. 이 명령어를 실수로 /usr/bin/ 같은 곳에서 돌리면 시스템 주요 기능이 마비될 수 있습니다.

 

[안전한 실무 팁]

삭제하기 전에 반드시 눈으로 먼저 확인하세요!

# 1단계: 먼저 목록과 권한을 확인 (ls -l)
find /opt/findme/ -type f -perm -4000 -exec ls -l {} \;

# 2단계: 확인 후 이상한 파일만 삭제
# (직접 지우거나 검증된 경로에서만 exec rm 사용)

📦 세 번째 미션: 특정 용량 이상의 파일 백업하기

find /opt/findme/ -size +1k -type f -exec cp {} /opt/ \;

로그 파일 관리나 디스크 정리를 할 때 유용한 명령어입니다. 하지만 이 명령어에는 초보자가 반드시 겪게 되는 "데이터 유실"의 함정이 숨어 있습니다.

1. -size 옵션의 디테일

  • +1k: 1KB를 초과(GreaterThan)하는 파일입니다.
    • 만약 -1k라면? 1KB 미만입니다.
    • 그냥 1k라면? 정확히 1KB(반올림 적용)인 파일입니다.
  • 단위:
    • c: 바이트 (Bytes)
    • k: 킬로바이트 (KiB)
    • M: 메가바이트 (MiB)
    • G: 기가바이트 (GiB)

2. cp와 Flat Copy의 함정 (데이터 유실 주의!)

이 명령어는 찾은 파일을 /opt/라는 단일 디렉토리로 복사합니다. 여기서 문제가 발생합니다.

상황 예시:

  1. /opt/findme/projectA/config.xml (크기 5KB)
  2. /opt/findme/projectB/config.xml (크기 10KB)

find는 위 두 파일을 모두 찾아냅니다. 그리고 순서대로 /opt/에 복사를 시도합니다.

  1. projectA/config.xml을 /opt/config.xml로 복사.
  2. projectB/config.xml을 /opt/config.xml로 복사. (덮어쓰기 발생!)

결과적으로 /opt/ 디렉토리에는 마지막에 복사된 파일 하나만 남게 됩니다. 원본의 디렉토리 구조(projectA, projectB)가 무시되기 때문입니다.

🚀 해결책: 디렉토리 구조 유지 복사 (--parents)

이 문제를 해결하려면 cp 명령어에 --parents 옵션을 추가해야 합니다.

find /opt/findme/ -size +1k -type f -exec cp --parents {} /opt/ \;

 

이렇게 하면 복사되는 목적지에 원본의 경로 구조(예: /opt/opt/findme/projectA/...)를 그대로 생성하여 덮어쓰기 문제를 완벽하게 방지할 수 있습니다.


📝 마무리하며

find 명령어는 리눅스라는 거대한 바다에서 원하는 물고기를 낚아 올리는 낚싯대와 같습니다.

  1. -perm -100: 소유자 실행 권한이 있는 파일을 찾을 때 (스크립트 점검)
  2. -perm -4000: SetUID 설정된 파일을 찾을 때 (보안 점검 - 삭제 주의!)
  3. -size +1k: 용량 기반 검색 및 복사 (덮어쓰기 주의!)

이 세 가지 패턴만 확실히 이해하고 계신다면, 파일 관리 자동화 스크립트를 작성하거나 보안 감사를 수행할 때 훨씬 더 자신감 있게 터미널을 다루실 수 있을 것입니다.

오늘 설명드린 명령어들을 테스트 서버에서 직접 입력해 보시면서 감을 익혀보세요! 작은 실수가 큰 사고를 막는 경험이 됩니다.