sy/dev
Study
14 min read

리눅스 권한 정리 — chmod, chown, sudo와 그 너머

ls -l의 그 알 수 없는 'drwxr-xr-x'를 읽는 법부터, chmod의 숫자/기호 두 가지 표기, chown으로 소유권 옮기기, sudo의 올바른 쓰임, 그리고 setuid·sticky bit까지.

공부하게 된 계기

Permission denied. 리눅스 쓰면서 가장 많이 보는 메시지일지도 모른다. sudo를 붙이면 보통 풀리지만, 그게 정답인 적은 많지 않다. 매번 chmod 777로 때리고 넘어갔다면 — 이 글이 그 습관을 고치는 데 도움이 될 것이다.

권한은 사실 딱 한 줄로 요약된다.

파일마다 사용자 / 그룹 / 기타 세 주체가 있고, 각각 읽기 / 쓰기 / 실행 세 동작이 허용/거부된다.

3 × 3 = 9비트. 끝.

1) ls -l 읽는 법

ls -l
-rw-r--r--  1 sungyeon  staff   1234 May 10 12:34 README.md
drwxr-xr-x  3 sungyeon  staff     96 May 10 12:30 src

첫 컬럼이 권한 표기다. 10글자를 4부분으로 나눠 읽는다.

-  rw-  r--  r--
│   │    │    │
│   │    │    └─ others (기타) 권한
│   │    └────── group 권한
│   └─────────── owner (사용자) 권한
└─────────────── 파일 타입

첫 글자 — 파일 타입

글자의미
-일반 파일
d디렉토리
l심볼릭 링크
c캐릭터 디바이스
b블록 디바이스
s소켓
p파이프

일상에서는 -, d, l 셋만 거의 다.

권한 — rwx 의미

글자파일에서디렉토리에서
r내용 읽기ls로 목록 보기
w내용 쓰기파일 생성/삭제
x실행cd로 들어가기
⚠️

디렉토리의 x는 직관과 다르다. 디렉토리에 r만 있고 x가 없으면 ls는 되지만 안에 들어가지도 못하고 파일 stat도 못 한다. 디렉토리는 거의 항상 rx가 같이 다닌다.

2) chmod — 권한 바꾸기

두 가지 표기법이 있다. 숫자 표기와 기호 표기. 둘 다 알아두는 게 좋다.

숫자 표기 (가장 자주 씀)

rwx를 비트로 보면:

  • r = 4
  • w = 2
  • x = 1

세 비트를 더해 0~7. 사용자·그룹·기타 각각 한 자리씩 쓰면 세 자리 숫자.

숫자권한의미
7rwx모든 권한
6rw-읽기·쓰기
5r-x읽기·실행
4r--읽기만
0---없음

자주 쓰는 조합:

chmod의미
644일반 파일 — 본인 쓰기, 다 읽기 가능
755실행 파일 / 디렉토리 — 본인 쓰기, 다 읽기·실행
600비공개 파일 — 본인만 읽고 씀 (예: .ssh/id_rsa)
700비공개 디렉토리 — 본인만 (예: .ssh/)
777거의 항상 잘못된 답 — 누구나 다 가능
chmod 644 README.md
chmod 755 deploy.sh
chmod 600 ~/.ssh/id_rsa

기호 표기 (부분 변경에 유용)

chmod u+x deploy.sh       # 사용자에게 실행 권한 추가
chmod g-w report.md       # 그룹에서 쓰기 제거
chmod o-rwx secret.txt    # 기타 모두 차단
chmod a+r public.html     # 모두에게 읽기 허용 (a = all)
chmod u=rw,g=r,o=r file   # 절대 지정
대상의미
uuser (소유자)
ggroup
oothers
aall (= ugo)
연산자의미
+권한 추가
-권한 제거
=정확히 이 권한으로 설정

재귀 적용 — -R

# 디렉토리 안 모든 파일·디렉토리에
chmod -R 755 ./public
⚠️

-R은 위험하다. 디렉토리에 적합한 권한과 파일에 적합한 권한이 다른데, -R은 구분 없이 똑같이 먹인다. 예를 들어 chmod -R 755는 일반 텍스트 파일에도 실행 권한을 준다.

디렉토리/파일을 분리해 적용:
find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;
또는 chmod 자체의 capital X 트릭: chmod -R u=rwX,g=rX,o=rX .X(대문자)는 이미 실행 가능하거나 디렉토리인 경우만 x 적용.

3) chown — 소유권 변경

# 사용자만 변경
sudo chown alice file.txt
 
# 사용자:그룹 같이
sudo chown alice:developers file.txt
 
# 그룹만 변경
sudo chgrp developers file.txt
# 또는
sudo chown :developers file.txt
 
# 재귀
sudo chown -R alice:developers /var/www/myapp

대부분 sudo가 필요하다 — 자기 소유물을 남에게 넘기려면 root 권한이 있어야 함(보안 이유).

자주 만나는 시나리오

# Docker 볼륨 마운트했는데 컨테이너가 root로 만든 파일이라 호스트에서 못 건드림
sudo chown -R $(id -u):$(id -g) ./data
 
# Nginx가 못 읽는다고 할 때
sudo chown -R www-data:www-data /var/www/html

4) umask — 새 파일의 기본 권한

새로 만든 파일은 어떤 권한으로 시작될까?

umask
# 0022

umask빼버릴 비트를 지정한다.

  • 파일 기본: 666umask = 실제 권한
  • 디렉토리 기본: 777umask = 실제 권한

umask 022라면:

  • 파일: 666022 = 644 (본인 rw, 그룹/기타 r)
  • 디렉토리: 777022 = 755

대부분 시스템의 기본값. 좀 더 보수적으로 하고 싶으면:

umask 077    # 본인만 (파일 600, 디렉토리 700)

~/.bashrc~/.zshrc에 넣어두면 영구 적용.

5) sudo — 임시 권한 상승

sudo apt update
sudo systemctl restart nginx

한 명령만 root 권한으로 실행. 입력하는 비밀번호는 자기 비밀번호 (root 비밀번호 아님).

자주 헷갈리는 패턴

# ✗ 동작 안 함 — 리다이렉트는 sudo 권한 안에서 일어나지 않음
sudo echo "127.0.0.1 myapp" >> /etc/hosts
 
# ✓ tee로 우회
echo "127.0.0.1 myapp" | sudo tee -a /etc/hosts
 
# ✓ 또는 셸 자체를 sudo로
sudo bash -c 'echo "127.0.0.1 myapp" >> /etc/hosts'

>>>는 셸이 처리하는데, 그 셸은 일반 사용자 권한이라 /etc/hosts에 못 쓴다. teebash -c로 우회한다.

다른 사용자로

# 한 명령만 다른 사용자로
sudo -u www-data php artisan migrate
 
# 그 사용자의 셸로 진입
sudo -u www-data -i
 
# 완전한 root 셸
sudo -i
# 또는
sudo su -

su와의 차이

su -            # root 비밀번호로 root 됨
sudo -i         # 자기 비밀번호로 root 됨

대부분의 현대 리눅스는 root 계정에 비밀번호를 안 두고 sudo로만 권한 상승하게 설정한다 (Ubuntu 기본 정책).

sudoers — 누가 sudo를 쓸 수 있나

/etc/sudoers 파일이 정의한다. 직접 편집 말고 visudo 사용.

sudo visudo
# 기본 — wheel(또는 sudo) 그룹의 모두
%sudo   ALL=(ALL:ALL) ALL

# 특정 사용자에게 비밀번호 없이
alice ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx

visudo는 저장 시 문법을 검증한다. 직접 편집하다 망치면 sudo 자체를 못 쓰게 되니 꼭 visudo로.

6) 특수 권한 — setuid, setgid, sticky bit

가끔 ls -l에서 st를 보게 된다.

ls -l /usr/bin/passwd
# -rwsr-xr-x  1 root root  ...  /usr/bin/passwd
#    ↑ 이거

setuid (s, 사용자 자리)

이 비트가 켜진 실행 파일은 소유자 권한으로 실행된다. passwd가 대표적 예 — 일반 사용자가 자기 비밀번호 바꿀 때 /etc/shadow(root 소유)에 써야 하는데, setuid 덕분에 가능하다.

chmod u+s file
chmod 4755 file   # 4가 setuid 비트

setgid (s, 그룹 자리)

디렉토리에 걸면, 그 안에서 만들어지는 파일은 부모 디렉토리의 그룹을 상속받는다. 팀 공유 디렉토리에 유용.

chmod g+s /shared/team-docs
chmod 2755 /shared/team-docs

sticky bit (t)

디렉토리에 걸면, 그 안의 파일은 소유자만 삭제할 수 있다. /tmp가 대표적인 예 — 누구나 파일을 만들 수 있지만 남의 파일은 못 지운다.

ls -ld /tmp
# drwxrwxrwt  ...  /tmp
#         ↑ 이거
chmod +t /tmp
chmod 1777 /tmp
특수 비트숫자디렉토리 효과파일 효과
setuid4(의미 없음)소유자 권한으로 실행
setgid2그룹 상속그룹 권한으로 실행
sticky1소유자만 삭제 가능(현대 시스템에서 의미 없음)

평소엔 잘 안 만지지만 봤을 때 당황하지 말 것.

7) 실전 패턴 5개

A. SSH 키가 거부됨 — "Permissions are too open"

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 600 ~/.ssh/authorized_keys

SSH는 키 파일이 본인만 읽을 수 있어야 하고, 그렇지 않으면 거부한다.

B. 웹 디렉토리 권한 정리

# 소유자
sudo chown -R www-data:www-data /var/www/myapp
 
# 디렉토리 / 파일 분리 적용
sudo find /var/www/myapp -type d -exec chmod 755 {} \;
sudo find /var/www/myapp -type f -exec chmod 644 {} \;
 
# 업로드 폴더는 쓰기까지
sudo chmod -R 775 /var/www/myapp/storage

C. Docker 볼륨 호스트에서 못 건드림

# 컨테이너 내부에서 root로 만든 파일이라 호스트에서 권한 없음
sudo chown -R $USER:$USER ./data

근본 해결은 컨테이너에서 호스트와 같은 UID로 실행하기:

docker run --user $(id -u):$(id -g) ...

D. 그 디렉토리 누가 들어갈 수 있나

ls -ld /var/log/private
# drwxr-x--- 2 root admin 4096 May 10 12:00 /var/log/private
 
# admin 그룹 멤버 누구?
getent group admin

E. 실수로 chmod 777 ~을 했다면

기본 권한으로 빠르게 되돌리기:

chmod 700 ~
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_*
chmod 644 ~/.bashrc ~/.zshrc ~/.profile

홈 디렉토리 전체를 일괄 복구하는 마법 명령은 없다 — 파일별 적정 권한이 달라서. 위 핵심 몇 개만 먼저 잡으면 일상 사용은 가능.

정리

기억할 것 단 3개:

  1. ls -l의 10글자 — 타입 1 + (소유자 / 그룹 / 기타) 각 3글자
  2. chmod 644 (파일), chmod 755 (디렉토리·실행) — 90%는 이 둘
  3. chmod 777은 거의 항상 답이 아니다. 막힐 때 일단 멈추고 어느 주체가 어느 권한이 부족한지 따져볼 것.

권한은 처음 헷갈려도, 한 번 정리해두면 두고두고 안정적이다. Permission denied를 만났을 때 sudo 대신 ls -l을 먼저 치는 습관이 가장 큰 진전이다.

시리즈 정리

이번 편으로 5편이다.

다음 편 후보: 네트워크 디버깅(ss/curl/tcpdump), SSH·SCP·Rsync 묶음, 또는 텍스트 처리(sed/awk/cut/sort/uniq).

참고 자료

Comments