-g(소문자)와 -G(대문자)의 차이가 시험 핵심이다. -g는 기본 그룹 하나(passwd의 GID)를, -G는 보조 그룹 여럿(group 파일 멤버 목록)을 지정한다. 소문자 g = 기본(하나), 대문자 G = 보조(여럿)로 외운다. 새로 만드는 파일의 소유 그룹은 -g로 정한 기본 그룹이 된다.
-m 옵션은 단순히 빈 홈 디렉터리만 만드는 게 아니라 /etc/skel의 내용을 새 홈으로 복사한다. .bashrc, .profile, .bash_logout 같은 기본 설정 파일이 여기서 온다. 따라서 모든 신규 사용자에게 공통 설정을 배포하고 싶으면 /etc/skel에 파일을 넣어두면 된다. Red Hat 계열은 useradd가 기본으로 홈을 만들지만, Debian 계열의 useradd는 -m이 없으면 홈을 안 만들 수 있어 -m을 명시하는 습관이 안전하다.
⚠️ 함정: useradd와 adduser를 같은 것으로 보는 보기가 있다. useradd는 모든 배포판의 저수준 표준 명령이고, adduser는 Debian/Ubuntu 계열의 대화형 래퍼 스크립트(Perl)로 홈 생성·암호 설정까지 묻는다. 시험에서 "표준 계정 생성 명령"은 useradd다. Red Hat에서 adduser는 useradd의 심볼릭 링크일 뿐이다.
usermod는 기존 계정을 고친다. 옵션 다수가 useradd와 같지만, 보조 그룹 처리에 함정이 있다.
usermod -aG docker alice # alice를 docker 보조 그룹에 "추가"usermod -G docker alice # alice의 보조 그룹을 docker "하나로 교체"(기존 다 날아감!)usermod -L alice # 계정 잠금(shadow 해시 앞 ! 추가)usermod -U alice # 잠금 해제usermod -s /sbin/nologin alice # 셸 변경(로그인 차단)
⚠️ 함정: usermod -G만 쓰면 기존 보조 그룹이 모두 사라지고 지정한 그룹으로 교체된다. 기존 그룹을 유지하며 추가하려면 반드시 -a(append)를 함께 써서 usermod -aG로 해야 한다. 시험에서 "alice를 docker 그룹에 추가하되 기존 그룹 유지" 보기의 정답은 -aG다. -a를 빠뜨린 -G는 위험한 오답이 된다.
userdel은 계정을 지운다.
userdel alice # 계정만 삭제(홈은 남김)userdel -r alice # 홈 디렉터리와 메일 스풀까지 삭제
userdel(옵션 없음)은 passwd/shadow/group의 레코드만 지우고 홈 디렉터리와 그 안의 파일은 남긴다. -r을 붙여야 홈과 /var/mail/사용자 메일 스풀까지 지운다. 단, -r로도 그 사용자가 시스템 다른 곳(예: /tmp, 공유 디렉터리)에 만든 파일은 남는다. 이런 "주인 없는 파일"은 UID만 표시되며 find / -nouser로 찾을 수 있다.
로그인 중이거나 프로세스가 떠 있는 사용자는 userdel이 거부될 수 있다(user X is currently used by process). -f(force)로 강제할 수 있으나 위험하다. 시험에서 "삭제가 안 되는 이유"로 "사용자가 현재 로그인/프로세스 실행 중"이 정답으로 나온다.
passwd는 암호를 설정·변경하고 잠금/해제도 한다. chage는 shadow의 수명 필드(3~8번)를 전담한다.
passwd alice # alice 암호 변경(root만 타인 암호 변경 가능)passwd -l alice # 잠금(shadow 해시 앞 ! )passwd -u alice # 잠금 해제passwd -e alice # 암호 즉시 만료(다음 로그인 시 강제 변경)passwd -d alice # 암호 삭제(무암호 — 위험)chage -l alice # 수명 정책 조회(사람이 읽는 형식)chage -M 90 alice # Max(최대 유효일) 90일로 설정 → shadow 5번chage -m 7 alice # Min(최소 변경 간격) 7일 → shadow 4번chage -W 14 alice # Warn(경고일) 14일 → shadow 6번chage -E 2026-12-31 alice # 계정 만료일 → shadow 8번chage -d 0 alice # 마지막 변경일 0 → 다음 로그인 시 강제 변경
chage의 대문자/소문자 옵션이 shadow 필드와 1:1 대응한다. -M(대문자)=Max=최대 유효일, -m(소문자)=Min=최소 변경 간격, -W=Warn, -E=Expire(계정 만료), -d=마지막 변경일, -I=Inactive. Day 1의 shadow 9개 필드를 떠올리면 옵션이 어느 필드를 건드리는지 즉시 매칭된다.
passwd -e alice(암호 만료)와 chage -d 0 alice(마지막 변경일을 1970-01-01로)는 결과가 같다 — 둘 다 다음 로그인 때 암호를 강제로 바꾸게 한다. 신규 직원 첫 로그인 시 초기 암호를 본인이 직접 재설정하게 만드는 표준 운영 기법이다.
passwd -d(암호 삭제)와 passwd -l(잠금)을 혼동시키는 보기가 있다. -d는 암호를 없애 무암호 로그인이 가능해지는(위험) 상태고, -l은 해시 앞에 !를 붙여 로그인을 차단하는 상태다. 정반대 효과다.
# 직접 쳐보기 — 수명 정책 적용 후 확인sudo chage -M 60 -W 7 testusersudo chage -l testusersudo passwd -S testuser # 한 줄 요약(상태/최종변경/Min/Max/Warn/Inactive)
groupadd -g 2000 webteam # GID 2000으로 그룹 생성groupmod -n devteam webteam # 그룹 이름 변경(webteam → devteam)groupdel webteam # 그룹 삭제(누군가의 기본 그룹이면 거부됨)gpasswd -a alice webteam # alice를 webteam 멤버로 추가gpasswd -d alice webteam # alice를 webteam에서 제거gpasswd -A admin1 webteam # admin1을 webteam의 관리자로 지정(gshadow 3번)gpasswd webteam # 그룹 암호 설정(newgrp용)
gpasswd -a/gpasswd -d는 group과 gshadow를 동시에 갱신해 짝을 맞춘다. 손으로 group만 편집하면 Day 1에서 본 "유령 멤버" 불일치가 생긴다. 그래서 그룹 멤버 변경은 gpasswd(또는 usermod -aG)로 하는 것이 원칙이다.
groupdel은 그 그룹이 어떤 사용자의 기본(primary) 그룹이면 삭제를 거부한다. 먼저 그 사용자의 기본 그룹을 다른 것으로 바꾸거나 사용자를 지운 뒤 그룹을 삭제해야 한다. 보조 그룹인 경우엔 바로 삭제된다.
newgrp 명령은 그룹 암호를 입력해 현재 세션의 기본 그룹을 임시 변경한다. 1970~80년대에는 한 사용자가 여러 그룹을 동시에 가질 수 없었기에(당시 유닉스는 한 번에 하나의 그룹만 활성), 작업할 그룹을 newgrp로 갈아끼웠다. 지금은 보조 그룹을 동시에 여러 개 가질 수 있어 newgrp는 거의 안 쓰지만, 시험에서는 "그룹 암호(gshadow 2번)의 용도"로 그 흔적이 출제된다.
su(substitute user)는 다른 사용자의 셸로 전환한다. 대상의 암호를 알아야 한다.
su alice # alice로 전환, 환경 일부 유지(현재 디렉터리 유지)su - alice # alice로 전환 + alice의 로그인 환경 완전 적용su - # root로 전환(대상 생략 시 root) + 로그인 셸su -c "id" alice # alice 권한으로 단일 명령만 실행
su alice와 su - alice의 차이가 핵심이다. 하이픈(- 또는 -l)이 있으면 로그인 셸로 전환해 대상 사용자의 .bash_profile/.profile을 읽고 환경 변수(PATH, HOME, 작업 디렉터리)를 그 사용자 기준으로 완전히 새로 설정한다. 하이픈이 없으면 환경 일부(특히 PATH)가 원래 사용자의 것을 그대로 물려받아 "명령을 못 찾는" 미묘한 오류가 생긴다. 그래서 root로 갈 때는 거의 항상 su -를 쓴다.
su로 root가 되려면 root의 암호를 알아야 한다. Ubuntu는 기본적으로 root 암호가 잠겨(!) 있어 su -가 막히고 sudo를 쓰도록 유도한다. "Ubuntu에서 su -가 안 되는 이유"의 정답은 "root 계정 암호가 설정/활성화되어 있지 않음"이다.
sudo(superuser do)는 su와 철학이 다르다. su는 대상의 암호로 그 사람이 "되는" 것이고, sudo는 자기 암호로 미리 위임받은 권한만 빌려 단일 명령을 실행하는 것이다.
sudo systemctl restart nginx # 자기 암호로 인증 후 root 권한 명령 실행sudo -u alice whoami # alice 권한으로 실행(→ alice 출력)sudo -i # root의 로그인 셸 진입(su - 유사)sudo -l # 내가 sudo로 할 수 있는 명령 목록 확인
권한 정의는 /etc/sudoers(반드시 visudo로 편집)에 있다. 한 줄의 문법:
# 사용자 호스트=(실행대상사용자:그룹) 명령root ALL=(ALL:ALL) ALLalice ALL=(ALL) ALL%admin ALL=(ALL) ALL # % = 그룹. admin 그룹 전체%wheel ALL=(ALL) NOPASSWD: ALL # 암호 없이 sudo 허용bob web01=(root) /usr/bin/systemctl restart nginx # 특정 명령만
위치
의미
1번 필드
대상 사용자(%=그룹)
ALL= 앞
적용 호스트(ALL=모든 호스트)
(ALL:ALL)
변신 가능한 (사용자:그룹)
마지막
허용 명령(ALL=전체, NOPASSWD:=암호 면제)
sudoers는 반드시 visudo로 편집해야 한다. visudo는 저장 시 문법 검사를 하고 파일에 잠금을 걸어 동시 편집을 막는다. 일반 vi로 직접 편집하다 문법을 틀리면 sudo 전체가 동작 불능이 되고, 그 상태에서 root 암호로 직접 들어가지 못하면 시스템이 잠길 수 있다. "sudoers 편집 시 권장 도구"의 정답은 항상 visudo다.
% 접두사는 그룹을 뜻한다. Red Hat 계열은 wheel 그룹, Debian/Ubuntu 계열은 sudo 그룹을 기본 관리자 그룹으로 쓴다. 따라서 "Ubuntu에서 사용자에게 관리자 권한 부여"의 표준 방법은 usermod -aG sudo alice로 sudo 그룹에 추가하는 것이고, Red Hat이면 wheel 그룹이다. 개별 사용자를 sudoers에 일일이 적기보다 그룹 단위로 위임하는 것이 운영 표준이다.
su는 대상 사용자의 암호를, sudo는 자기 자신의 암호를 묻는다. 이 차이를 뒤바꾼 보기가 오답이다. 그래서 sudo는 root 암호를 팀원에게 공유하지 않고도 특정 명령만 위임할 수 있어 감사·최소권한 원칙에 부합한다. 또 NOPASSWD:는 편하지만 자동화/CI에서만 제한적으로 쓰고, 사람 계정에 남발하면 보안 위협이다.
한 회사가 운영 서버 root 암호를 팀원 전원에게 공유했다가 퇴사자가 생길 때마다 root 암호를 전부 바꿔야 하는 운영 지옥에 빠졌다. sudo 기반으로 전환하자 각자 자기 암호로 인증하고, sudoers에 "누가 어떤 명령을 할 수 있는지"가 기록되며, /var/log/secure(또는 auth.log)에 모든 sudo 사용이 감사 로그로 남았다. 퇴사자는 그 계정만 비활성화하면 끝이었다. 이것이 "su 공유 모델 → sudo 위임 모델"로 넘어가는 표준 보안 진화다.
# 직접 쳐보기 — sudo 권한 확인(편집은 주의)sudo -l # 내가 가진 sudo 권한 목록sudo visudo -c # sudoers 문법 검사만(편집 안 함)groups # 내가 sudo/wheel 그룹에 속했는지
같은 타입의 모듈은 순서대로 쌓여(stack) 실행되고, 제어 플래그가 각 모듈의 성패를 최종 판정에 반영하는 방식을 정한다.
제어 플래그
성공 시
실패 시
required
계속 진행
최종 실패 확정, 나머지 모듈은 끝까지 실행
requisite
계속 진행
즉시 중단하고 실패 반환
sufficient
앞선 required 실패가 없으면 즉시 성공 반환
무시하고 계속 진행
optional
영향 없음
영향 없음(그 타입에 하나뿐일 때만 반영)
대표 모듈
하는 일
pam_unix.so
/etc/passwd·/etc/shadow 기반 전통 인증
pam_cracklib.so → pam_pwquality.so
암호 복잡도 강제. RHEL 7부터 pwquality(/etc/security/pwquality.conf)
pam_tally2.so → pam_faillock.so
로그인 실패 횟수 누적·계정 잠금. RHEL 8부터 faillock
pam_limits.so
/etc/security/limits.conf의 자원 제한 적용(session)
pam_wheel.so / pam_nologin.so
su를 wheel 그룹만 허용 / /etc/nologin 있으면 일반 로그인 차단
sufficient가 성공하면 그 아래 같은 타입 모듈은 아예 실행되지 않는다. 밑에 놓은 실패 횟수 카운터나 추가 검증이 통째로 무력화되므로 스택의 순서가 곧 정책이다. required와 requisite는 실패 시 결과는 같지만, required는 뒤 모듈을 마저 실행해 어느 단계에서 틀렸는지 노출하지 않고requisite는 즉시 끊는다.
/etc/security/limits.conf는 pam_limits.so가 읽어 적용하는 자원 제한 파일이다.
한 줄은 대상 종류 항목 값 네 칸으로 구성된다.
대상: 사용자명 · @그룹명 · *(전체)
종류: soft(현재값) · hard(절대 상한, 상향은 root만)
항목: nproc(프로세스 수) · nofile(열린 파일 수) · core · fsize · cpu · maxlogins 등
alice soft nproc 200@developers hard nofile 8192* soft core 0
현재 셸에 걸린 값은 ulimit -a(soft)·ulimit -Ha(hard)로 본다. limits.conf는 PAM을 거치는 로그인 세션에만 적용되므로 systemd가 직접 띄우는 데몬에는 먹지 않는다. 그런 서비스는 유닛 파일의 LimitNOFILE= 같은 지시어로 따로 지정해야 한다.
계정 통합에는 두 축이 다 필요하다. "누구인가"(정보 조회)는 NSS(/etc/nsswitch.conf의 passwd:/shadow:/group: 행에 ldap 또는 sss 추가)가, "암호가 맞는가"(인증)는 PAM(pam_ldap.so/pam_sss.so)이 담당한다. getent passwd alice로는 보이는데 로그인이 안 되면 NSS만 붙고 PAM이 빠진 것이다. 요즘은 둘을 묶고 캐시까지 해 주는 SSSD(/etc/sssd/sssd.conf)가 표준이다.
nsswitch.conf는 먼저 적힌 쪽을 먼저 조회하므로 files를 앞에 두어야 LDAP 서버가 죽어도 로컬 계정으로 들어갈 수 있다. 순서를 뒤집으면 서버 장애 시 아무도 로그인하지 못한다. 또 LDAP은 기본이 평문이라 StartTLS나 LDAPS(636)를 반드시 켜야 한다.