[ { "id": "linux-pwd", "certification": "LFCS / 리눅스마스터", "title": "pwd — 현재 디렉터리 확인", "summary": "현재 쉘의 작업 디렉터리를 절대경로로 출력합니다. 파일 조작 명령은 모두 이 위치를 기준으로 실행되므로 작업 전 확인 습관이 중요합니다.", "example": "pwd\n# /home/ubuntu\ncd /var/log && pwd\n# /var/log", "common_mistake": "상대경로(../dir)는 pwd 결과 기준으로 해석됩니다. 헷갈리면 절대경로를 사용하세요.", "keywords": [ "pwd", "working directory", "absolute path" ], "source_id": "linux-bash-manual", "details": [ "`pwd`는 현재 위치를 절대경로로 출력합니다. 프롬프트에 표시된 경로가 잘릴 때 정확한 위치를 확인하는 용도로 씁니다.", "스크립트에서 `DIR=$(pwd)`로 현재 경로를 저장해두면 `cd` 후 `cd $DIR`로 복귀할 수 있습니다.", "시험에서는 `cd`로 이동 후 `pwd` 결과를 묻거나, 상대경로 명령이 어느 위치에 적용되는지 추론하는 형태로 출제됩니다." ] }, { "id": "linux-ls", "certification": "LFCS / 리눅스마스터", "title": "ls — 디렉터리 목록 확인", "summary": "디렉터리의 파일과 하위 디렉터리를 나열합니다. 권한·소유자·크기·수정시간까지 보려면 `-l`, 숨김파일 포함은 `-a`를 씁니다.", "example": "ls -al /etc\nls -lh /var/log\nls -lt # 수정시간 역순 정렬", "common_mistake": "`ls -l`의 첫 컬럼은 권한 비트(rwxrwxrwx)입니다. d로 시작하면 디렉터리, -면 일반 파일, l이면 심볼릭 링크.", "keywords": [ "ls", "-l", "-a", "-h", "hidden files", "permissions" ], "source_id": "linux-bash-manual", "details": [ "`ls -l` 출력: `권한 링크수 소유자 그룹 크기 날짜 이름` 순서. 권한 비트 읽기를 반드시 익혀야 합니다.", "`-a`는 `.`으로 시작하는 숨김파일 포함. `-h`는 용량을 KB/MB로 사람이 읽기 쉽게 표시합니다.", "시험 패턴: 특정 디렉터리의 파일 권한·소유자를 확인하거나, 최근 수정 파일을 찾는 문제에서 `ls -lt` 조합이 자주 나옵니다." ] }, { "id": "linux-cd", "certification": "LFCS / 리눅스마스터", "title": "cd — 디렉터리 이동", "summary": "작업 디렉터리를 변경합니다. 이후 실행하는 모든 상대경로 명령의 기준이 바뀝니다.", "example": "cd /etc/nginx # 절대경로 이동\ncd .. # 부모 디렉터리\ncd ~ # 홈 디렉터리\ncd - # 이전 디렉터리", "common_mistake": "`cd ..`은 한 단계 위, `cd /`는 루트로 이동. `cd -`는 바로 직전 위치로 돌아옵니다.", "keywords": [ "cd", "relative path", "absolute path", "home" ], "source_id": "linux-bash-cd", "details": [ "`cd 절대경로`는 어디서든 동일 위치로 이동. `cd 상대경로`는 현재 위치 기준으로 이동합니다.", "`cd ~user`는 다른 사용자의 홈 디렉터리로 이동합니다. 관리자 작업 시 자주 활용합니다.", "시험 패턴: 여러 번 `cd`로 이동 후 현재 위치를 묻거나, 올바른 경로 표현식을 고르는 문제가 출제됩니다." ] }, { "id": "linux-mkdir", "certification": "LFCS / 리눅스마스터", "title": "mkdir — 디렉터리 생성", "summary": "새 디렉터리를 만듭니다. `-p` 옵션으로 중간 경로가 없어도 한 번에 생성할 수 있습니다.", "example": "mkdir logs\nmkdir -p /srv/app/config # 중간 디렉터리 자동 생성\nmkdir -m 750 secure_dir # 권한 지정해 생성", "common_mistake": "부모 디렉터리가 없는 경로에 `mkdir`만 쓰면 에러납니다. `-p`를 붙이면 부모까지 자동 생성됩니다.", "keywords": [ "mkdir", "-p", "directory", "create" ], "source_id": "linux-bash-manual", "details": [ "`mkdir -p a/b/c`는 a, a/b, a/b/c를 한 번에 만듭니다. 스크립트에서 경로 준비 시 필수 옵션입니다.", "`-m 모드`로 생성과 동시에 권한을 설정할 수 있습니다: `mkdir -m 700 private`.", "시험 패턴: 실습에서 특정 경로를 만들고 이어서 권한·소유자를 설정하는 흐름으로 자주 등장합니다." ] }, { "id": "linux-touch", "certification": "LFCS / 리눅스마스터", "title": "touch — 파일 생성 / 타임스탬프 갱신", "summary": "빈 파일을 생성하거나, 이미 있는 파일의 수정 시간을 현재 시각으로 갱신합니다.", "example": "touch newfile.txt\ntouch -t 202401010000 old.txt # 특정 시각으로 설정", "common_mistake": "이미 있는 파일에 `touch`를 쓰면 내용을 지우지 않고 시간 정보만 갱신됩니다.", "keywords": [ "touch", "timestamp", "create", "mtime" ], "source_id": "linux-bash-manual", "details": [ "파일이 없으면 빈 파일을 만들고, 있으면 atime(접근)과 mtime(수정) 시각을 현재로 갱신합니다.", "`-t YYYYMMDDhhmm` 형태로 원하는 시각을 직접 지정할 수 있어 테스트 시나리오에서 활용됩니다.", "시험 패턴: 파일 생성 후 `ls -l`로 존재·시각 확인, 또는 `find -newer`로 최근 파일 검색하는 흐름과 연결됩니다." ] }, { "id": "linux-cat", "certification": "LFCS / 리눅스마스터", "title": "cat — 파일 내용 출력", "summary": "파일 내용을 표준 출력으로 보여줍니다. 여러 파일을 연결하거나 리다이렉션으로 파일을 만들 때도 씁니다.", "example": "cat /etc/hostname\ncat file1.txt file2.txt > merged.txt\ncat -n file.txt # 줄 번호 표시", "common_mistake": "큰 파일은 `cat` 대신 `less`(스크롤), `head`/`tail`(일부만)을 사용하세요.", "keywords": [ "cat", "stdout", "concatenate", "-n" ], "source_id": "linux-bash-manual", "details": [ "`cat`은 파일 전체를 한 번에 출력합니다. `/etc/passwd`, `/etc/hosts` 같은 설정 파일 빠르게 볼 때 씁니다.", "`cat file1 file2 > combined`로 두 파일을 합칩니다. `>>` 사용 시 기존 파일에 추가됩니다.", "시험 패턴: `cat > file << EOF … EOF` 형태의 here-doc으로 파일을 직접 작성하는 패턴도 출제됩니다." ] }, { "id": "linux-grep", "certification": "LFCS / 리눅스마스터", "title": "grep — 텍스트 패턴 검색", "summary": "파일이나 표준 입력에서 패턴이 있는 줄을 출력합니다. 로그 분석과 설정 파일 검색에 가장 많이 쓰이는 명령어입니다.", "example": "grep 'ERROR' /var/log/syslog\ngrep -rn 'PermitRootLogin' /etc/ssh/\ngrep -v '^#' /etc/ssh/sshd_config # 주석 제외", "common_mistake": "`grep`은 기본적으로 대소문자를 구분합니다. 구분 없이 찾으려면 `-i`를 추가하세요.", "keywords": [ "grep", "-r", "-n", "-i", "-v", "pattern", "regex" ], "source_id": "linux-grep-manual", "details": [ "주요 옵션: `-r`(재귀), `-n`(줄번호), `-i`(대소문자 무시), `-v`(제외), `-l`(파일명만), `-c`(개수).", "`grep -r 'failed' /var/log/`로 로그 디렉터리 전체에서 오류를 검색할 수 있습니다.", "시험 패턴: `ps aux | grep nginx`처럼 파이프와 함께, 또는 설정 파일에서 특정 값을 찾는 복합 문제로 출제됩니다." ] }, { "id": "linux-chmod", "certification": "LFCS / 리눅스마스터", "title": "chmod — 파일 권한 변경", "summary": "파일·디렉터리의 읽기(r=4), 쓰기(w=2), 실행(x=1) 권한을 소유자·그룹·기타 사용자별로 설정합니다.", "example": "chmod 755 script.sh # rwxr-xr-x\nchmod 644 config.conf # rw-r--r--\nchmod u+x,g-w file.txt # 심볼릭 방식", "common_mistake": "8진수 방식: 7=rwx, 6=rw-, 5=r-x, 4=r--. `chmod 777`은 모든 사용자에 모든 권한 — 보안상 위험합니다.", "keywords": [ "chmod", "permissions", "rwx", "octal", "symbolic" ], "source_id": "ubuntu-server-docs", "details": [ "8진수 표기: 첫째 자리=소유자(u), 둘째=그룹(g), 셋째=기타(o). 각 자리는 r(4)+w(2)+x(1) 합산입니다.", "심볼릭 표기: `u+x`(소유자에 실행 추가), `go-w`(그룹·기타 쓰기 제거), `a=r`(모두 읽기만).", "시험 패턴: 특정 권한 비트를 보고 8진수 숫자를 맞추거나, 요구 조건에 맞는 chmod 명령을 고르는 문제가 출제됩니다." ] }, { "id": "linux-chown", "certification": "LFCS / 리눅스마스터", "title": "chown — 소유자·그룹 변경", "summary": "파일·디렉터리의 소유자와 그룹을 변경합니다. `chmod`는 권한 비트, `chown`은 소유자를 바꾸는 것으로 역할이 다릅니다.", "example": "sudo chown ubuntu:ubuntu /srv/app\nchown -R www-data:www-data /var/www/html\nchown :developers project/ # 그룹만 변경", "common_mistake": "`chown user file`은 소유자만, `chown user:group file`은 소유자와 그룹을 함께 바꿉니다.", "keywords": [ "chown", "owner", "group", "-R", "sudo" ], "source_id": "ubuntu-user-management", "details": [ "`chown 사용자:그룹 파일` 형식. `:그룹`만 쓰면 그룹만 변경. `-R`은 디렉터리를 재귀적으로 변경합니다.", "웹 서버 설정에서 `/var/www/html`의 소유자를 `www-data`로 변경하는 패턴이 자주 등장합니다.", "시험 패턴: `chown`과 `chmod`를 조합해 특정 사용자만 접근하도록 설정하는 실습 문제에 출제됩니다." ] }, { "id": "linux-umask", "certification": "LFCS / 리눅스마스터", "title": "umask — 기본 권한 마스크", "summary": "새로 생성되는 파일·디렉터리의 기본 권한에서 차감할 비트를 지정합니다. 기본 umask 022는 파일 644, 디렉터리 755를 만들어냅니다.", "example": "umask # 현재 마스크 확인\numask 027 # 파일 640, 디렉터리 750\numask -S # 심볼릭 표기로 확인", "common_mistake": "umask 값은 권한이 아니라 '빼는 값'입니다. umask 022 → 파일 기본 666-022=644, 디렉터리 777-022=755.", "keywords": [ "umask", "default permissions", "mask", "022" ], "source_id": "ubuntu-server-docs", "details": [ "파일 기본 최대 권한은 666, 디렉터리는 777. 여기서 umask를 빼면 실제 생성 권한이 됩니다.", "사용자별 umask는 `~/.bashrc` 또는 `/etc/profile`에서 설정합니다. 시스템 전체는 `/etc/login.defs`.", "시험 패턴: umask 값을 주고 파일 생성 시 권한이 무엇인지, 또는 원하는 기본 권한을 만들기 위한 umask 값을 묻습니다." ] }, { "id": "linux-find", "certification": "LFCS / 리눅스마스터", "title": "find — 파일 검색", "summary": "이름, 크기, 수정 시각, 권한, 소유자 등 다양한 조건으로 파일시스템에서 파일을 찾습니다.", "example": "find /etc -name '*.conf'\nfind /var/log -mtime -1 # 하루 이내 수정\nfind / -perm /4000 -type f # SUID 파일", "common_mistake": "`find -name '*.conf'`에서 따옴표를 빠뜨리면 쉘이 glob을 먼저 해석해 예상치 못한 결과가 납니다.", "keywords": [ "find", "-name", "-type", "-mtime", "-perm", "-exec" ], "source_id": "linux-bash-manual", "details": [ "주요 조건: `-name`(이름), `-type f/d`(파일/디렉터리), `-size +10M`(크기), `-mtime -7`(7일 이내 수정), `-user`(소유자).", "`-exec 명령 {} \\;`로 찾은 파일에 명령을 실행합니다: `find . -name '*.tmp' -exec rm {} \\;`.", "시험 패턴: SUID/SGID 파일 찾기(`-perm /4000`), 특정 사용자 파일 찾기(`-user`), 오래된 파일 정리가 자주 출제됩니다." ] }, { "id": "linux-pipe-redirect", "certification": "LFCS / 리눅스마스터", "title": "파이프와 리다이렉션", "summary": "파이프(`|`)는 명령의 출력을 다음 명령의 입력으로 연결하고, 리다이렉션(`>`, `>>`, `<`)은 출력·입력을 파일로 연결합니다.", "example": "cat /etc/passwd | grep root\nls -la > filelist.txt\necho 'append' >> log.txt\ncommand 2>&1 | tee output.log", "common_mistake": "`>`는 파일을 덮어쓰고, `>>`는 추가합니다. 중요한 파일에 실수로 `>`를 쓰면 내용이 사라집니다.", "keywords": [ "pipe", "redirect", ">", ">>", "2>&1", "stdin", "stdout" ], "source_id": "linux-bash-cd", "details": [ "stdout 리다이렉션: `>` 덮어쓰기, `>>` 추가. stderr 리다이렉션: `2>`. `2>&1`은 stderr를 stdout으로 합칩니다.", "`tee` 명령은 stdout을 화면과 파일에 동시에 출력합니다: `command | tee log.txt`.", "시험 패턴: 명령 출력을 파일에 저장하거나, 에러 메시지를 로그에 기록하는 복합 파이프라인 문제가 출제됩니다." ] }, { "id": "linux-tar", "certification": "LFCS / 리눅스마스터", "title": "tar — 아카이브와 압축", "summary": "여러 파일을 하나의 아카이브로 묶거나 압축합니다. `-c`(생성), `-x`(해제), `-z`(gzip), `-j`(bzip2)를 조합해 씁니다.", "example": "tar czf backup.tar.gz /etc\ntar xzf backup.tar.gz -C /tmp\ntar tvf archive.tar.gz # 내용 목록", "common_mistake": "`c`(create)와 `x`(extract)를 혼동하지 마세요. `-C`로 압축 해제 위치를 지정하지 않으면 현재 위치에 풀립니다.", "keywords": [ "tar", "-czf", "-xzf", "gzip", "archive", "backup" ], "source_id": "linux-bash-manual", "details": [ "옵션 의미: `c`=생성, `x`=해제, `t`=목록, `v`=상세출력, `f`=파일지정, `z`=gzip, `j`=bzip2, `J`=xz.", "백업 패턴: `tar czf /backup/etc-$(date +%Y%m%d).tar.gz /etc`로 날짜 포함 백업 파일 생성.", "시험 패턴: 특정 디렉터리를 압축하거나 지정 위치에 풀어내는 명령을 직접 작성하는 문제가 출제됩니다." ] }, { "id": "linux-process-ps-kill", "certification": "LFCS / 리눅스마스터", "title": "ps, kill — 프로세스 확인과 종료", "summary": "`ps`로 실행 중인 프로세스를 조회하고, `kill`로 시그널을 보내 프로세스를 종료하거나 제어합니다.", "example": "ps aux | grep nginx\nkill -15 1234 # SIGTERM (정상 종료 요청)\nkill -9 1234 # SIGKILL (강제 종료)\nkillall nginx # 이름으로 종료", "common_mistake": "`kill -9`는 프로세스가 정리 과정 없이 즉시 종료됩니다. 먼저 `-15`(SIGTERM)을 시도하고, 응답 없을 때만 `-9`를 씁니다.", "keywords": [ "ps", "kill", "SIGTERM", "SIGKILL", "PID", "aux" ], "source_id": "linux-bash-manual", "details": [ "`ps aux`: a=모든 사용자, u=사용자/CPU/메모리 정보, x=터미널 없는 프로세스 포함. PID가 두 번째 컬럼입니다.", "주요 시그널: 1(SIGHUP 재시작), 9(SIGKILL 강제종료), 15(SIGTERM 정상종료 요청), 2(SIGINT Ctrl+C).", "시험 패턴: `ps aux | grep 프로세스명`으로 PID를 찾고 `kill`로 종료하는 두 단계 흐름이 자주 출제됩니다." ] }, { "id": "linux-systemctl", "certification": "LFCS / 리눅스마스터", "title": "systemctl — 서비스 관리", "summary": "systemd 기반 서비스를 시작·중지·재시작하고, 부팅 시 자동 시작 여부를 제어합니다. Ubuntu 16.04 이후 표준입니다.", "example": "systemctl start nginx\nsystemctl enable --now ssh # 즉시 시작 + 부팅 자동 시작\nsystemctl status nginx\nsystemctl list-units --type=service", "common_mistake": "`enable`은 부팅 자동 시작 설정, `start`는 지금 당장 시작. 둘 다 하려면 `enable --now`를 씁니다.", "keywords": [ "systemctl", "enable", "disable", "start", "stop", "status", "systemd" ], "source_id": "linux-systemd-systemctl", "details": [ "주요 서브커맨드: `start/stop/restart/reload`(실행 제어), `enable/disable`(부팅 자동 시작), `status`(상태 확인), `is-active/is-enabled`(조건 확인).", "`systemctl status 서비스`는 현재 상태, 최근 로그, PID, 실행 시간을 함께 보여줍니다.", "시험 패턴: 특정 서비스를 '지금 시작하고 부팅에도 자동 시작'하도록 설정하거나, 서비스 상태를 확인하는 문제가 자주 출제됩니다." ] }, { "id": "linux-journalctl", "certification": "LFCS / 리눅스마스터", "title": "journalctl — systemd 로그 조회", "summary": "systemd journal에 기록된 시스템 로그를 조회합니다. 서비스별, 시간별, 우선순위별 필터링이 강력합니다.", "example": "journalctl -u nginx --since today\njournalctl -p err -n 50\njournalctl -f # 실시간 추적\njournalctl --disk-usage", "common_mistake": "`journalctl`은 journal에 저장된 로그만 봅니다. `/var/log/` 텍스트 파일 로그는 `cat`/`tail`로 확인합니다.", "keywords": [ "journalctl", "-u", "-f", "--since", "-p", "systemd", "journal" ], "source_id": "linux-systemd-systemctl", "details": [ "주요 옵션: `-u 서비스`(서비스별), `-p err`(에러 이상), `--since '2024-01-01'`(시간 범위), `-n 100`(최근 100줄), `-f`(실시간).", "`journalctl -b`는 현재 부팅 이후 로그, `-b -1`은 이전 부팅 로그. 재부팅 후 오류 추적에 활용합니다.", "시험 패턴: 특정 서비스의 오류 로그를 찾거나, 특정 시간 이후 로그를 확인하는 문제로 출제됩니다." ] }, { "id": "linux-ip-ss", "certification": "LFCS / 리눅스마스터", "title": "ip, ss — 네트워크 인터페이스와 소켓 확인", "summary": "`ip`로 네트워크 인터페이스·라우팅·IP 설정을 확인하고, `ss`로 현재 열린 포트와 연결 상태를 조회합니다.", "example": "ip addr show\nip route show\nss -tlnp # TCP 리스닝 포트와 프로세스\nss -s # 소켓 통계 요약", "common_mistake": "`ifconfig`와 `netstat`은 구식 도구입니다. 현재는 `ip`와 `ss`가 표준이며 시험에서도 이쪽이 출제됩니다.", "keywords": [ "ip", "ss", "addr", "route", "netstat", "socket", "-tlnp" ], "source_id": "linux-man7-ip", "details": [ "`ip addr`은 인터페이스별 IP, `ip route`는 라우팅 테이블, `ip link`는 인터페이스 상태를 보여줍니다.", "`ss -tlnp`: t=TCP, l=listening, n=숫자표시, p=프로세스명. 어떤 서비스가 어느 포트를 열었는지 확인합니다.", "시험 패턴: 특정 서비스가 올바른 포트를 리스닝하는지 확인하거나, IP 설정 상태를 조회하는 문제가 출제됩니다." ] }, { "id": "linux-df-du-mount", "certification": "LFCS / 리눅스마스터", "title": "df, du, mount — 디스크 사용량과 마운트", "summary": "`df`는 파일시스템 전체 용량, `du`는 특정 디렉터리 사용량, `mount`는 블록 장치를 파일시스템 트리에 연결합니다.", "example": "df -h\ndu -sh /var/log/*\nmount /dev/sdb1 /mnt/data\nfindmnt # 마운트 트리 확인", "common_mistake": "`df`는 파일시스템 전체, `du`는 특정 경로의 실제 사용 크기. 두 숫자가 다를 수 있습니다(삭제됐지만 열린 파일 등).", "keywords": [ "df", "du", "mount", "-h", "-sh", "filesystem" ], "source_id": "ubuntu-storage", "details": [ "`df -h`는 모든 마운트 파티션의 사용률을 보여줍니다. 디스크 풀 경고 시 먼저 실행하는 명령입니다.", "`du -sh /경로/*`로 어느 하위 디렉터리가 공간을 차지하는지 찾을 수 있습니다.", "시험 패턴: 디스크 사용률 확인, 임시 마운트 명령 작성, `findmnt`로 마운트 정보 확인하는 문제가 출제됩니다." ] }, { "id": "linux-useradd", "certification": "LFCS / 리눅스마스터", "title": "useradd — 사용자 추가", "summary": "새 사용자 계정을 생성합니다. `-m`으로 홈 디렉터리 자동 생성, `-s`로 로그인 쉘, `-G`로 추가 그룹을 지정합니다.", "example": "sudo useradd -m -s /bin/bash -G sudo alice\nuseradd -r -s /usr/sbin/nologin svcuser # 서비스 계정\npasswd alice # 생성 후 비밀번호 설정", "common_mistake": "`useradd`만 쓰면 홈 디렉터리가 생성되지 않습니다. `-m`을 반드시 붙이거나 `adduser`(대화형)를 씁니다.", "keywords": [ "useradd", "-m", "-s", "-G", "adduser", "home directory" ], "source_id": "ubuntu-user-management", "details": [ "주요 옵션: `-m`(홈 디렉터리 생성), `-d 경로`(홈 경로 지정), `-s 쉘`(로그인 쉘), `-G 그룹`(추가 그룹), `-r`(시스템 계정).", "서비스 계정은 `-r -s /usr/sbin/nologin`으로 생성해 로그인을 막고 시스템 서비스 전용으로 씁니다.", "시험 패턴: 특정 조건(홈 디렉터리, 그룹, 쉘)을 만족하는 사용자를 생성하고 비밀번호를 설정하는 실습 문제가 출제됩니다." ] }, { "id": "linux-usermod", "certification": "LFCS / 리눅스마스터", "title": "usermod — 사용자 정보 변경", "summary": "기존 사용자 계정의 그룹, 쉘, 홈 디렉터리, 잠금 상태를 변경합니다.", "example": "usermod -aG docker alice # docker 그룹 추가\nusermod -s /bin/zsh alice # 쉘 변경\nusermod -L alice # 계정 잠금\nusermod -U alice # 잠금 해제", "common_mistake": "`-G`만 쓰면 기존 그룹이 사라집니다. 그룹을 추가할 때는 반드시 `-aG`(append)를 써야 합니다.", "keywords": [ "usermod", "-aG", "-L", "-U", "-s", "group", "lock" ], "source_id": "ubuntu-user-management", "details": [ "`-aG 그룹`은 기존 그룹을 유지하면서 그룹을 추가. 그룹 변경 후 재로그인해야 적용됩니다.", "`-L`(lock) / `-U`(unlock)로 비밀번호 앞에 `!`를 붙여 로그인을 차단하거나 해제합니다.", "시험 패턴: 사용자를 특정 그룹에 추가하거나 계정을 잠금하는 명령을 작성하는 문제가 출제됩니다." ] }, { "id": "linux-passwd", "certification": "LFCS / 리눅스마스터", "title": "passwd — 비밀번호와 계정 잠금", "summary": "사용자 비밀번호를 변경하거나 계정 만료·잠금을 설정합니다. root는 다른 사용자의 비밀번호도 바꿀 수 있습니다.", "example": "passwd # 현재 사용자 비밀번호 변경\nsudo passwd alice # alice 비밀번호 변경\npasswd -l alice # 계정 잠금\nchage -l alice # 만료 정보 확인", "common_mistake": "`passwd -l`로 잠근 계정도 SSH 키 인증으로는 접속 가능합니다. 완전 차단은 `/etc/shadow`의 쉘을 nologin으로 변경해야 합니다.", "keywords": [ "passwd", "-l", "-u", "-e", "chage", "password", "lock" ], "source_id": "ubuntu-user-management", "details": [ "`passwd -l`은 `/etc/shadow`의 비밀번호 앞에 `!`를 붙여 비밀번호 로그인을 차단합니다.", "`chage -M 90 user`로 비밀번호 최대 사용 기간, `chage -E 날짜`로 계정 만료일을 설정합니다.", "시험 패턴: 사용자 비밀번호 변경, 계정 잠금/해제, 비밀번호 만료 정책 설정 명령을 작성하는 문제가 출제됩니다." ] }, { "id": "linux-groups-id", "certification": "LFCS / 리눅스마스터", "title": "id, groups — 사용자·그룹 확인", "summary": "`id`는 현재 사용자의 UID, GID, 소속 그룹을 보여주고, `groups`는 그룹 목록만 출력합니다.", "example": "id\n# uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),27(sudo)\nid alice\ngroups alice", "common_mistake": "`usermod -aG`로 그룹을 추가한 뒤 `id`에 반영되려면 재로그인이 필요합니다. `newgrp 그룹명`으로 즉시 적용할 수 있습니다.", "keywords": [ "id", "groups", "UID", "GID", "whoami" ], "source_id": "ubuntu-user-management", "details": [ "`id` 출력에서 uid(사용자 번호), gid(기본 그룹), groups(모든 소속 그룹)를 확인할 수 있습니다.", "root의 uid와 gid는 0입니다. `id -u`로 숫자만, `id -un`으로 이름만 출력할 수 있습니다.", "시험 패턴: 사용자가 특정 그룹에 속해 있는지 확인하거나, uid/gid로 사용자 정보를 조회하는 문제가 출제됩니다." ] }, { "id": "linux-sudoers", "certification": "LFCS / 리눅스마스터", "title": "sudo와 sudoers — 권한 위임", "summary": "일반 사용자가 특정 명령을 root 권한으로 실행할 수 있도록 허용합니다. `/etc/sudoers`는 반드시 `visudo`로 편집합니다.", "example": "sudo apt update\nvisudo # /etc/sudoers 안전 편집\n# /etc/sudoers.d/alice 내용:\nalice ALL=(ALL) NOPASSWD: /usr/bin/systemctl", "common_mistake": "`/etc/sudoers`를 직접 vi로 열어 수정하면 문법 오류 시 sudo가 완전히 잠길 수 있습니다. 반드시 `visudo`를 사용하세요.", "keywords": [ "sudo", "sudoers", "visudo", "NOPASSWD", "ALL" ], "source_id": "ubuntu-user-management", "details": [ "`sudo` 그룹 또는 wheel 그룹에 속한 사용자는 기본으로 sudo 사용 가능합니다: `usermod -aG sudo alice`.", "`/etc/sudoers.d/` 디렉터리에 개별 파일을 만들면 메인 sudoers를 건드리지 않고 권한을 추가할 수 있습니다.", "시험 패턴: 특정 사용자에게 특정 명령만 sudo 허용하거나, NOPASSWD 설정을 추가하는 문제가 출제됩니다." ] }, { "id": "linux-acl", "certification": "LFCS / 리눅스마스터", "title": "ACL — 확장 접근 제어", "summary": "기본 유닉스 권한(소유자/그룹/기타)만으로는 표현할 수 없는 세밀한 권한을 특정 사용자나 그룹별로 지정합니다.", "example": "getfacl /srv/project\nsetfacl -m u:alice:rwx /srv/project\nsetfacl -m g:dev:r-x /srv/project\nsetfacl -R -m u:bob:r-- /data # 재귀", "common_mistake": "ACL이 설정된 파일은 `ls -l`에서 권한 뒤에 `+`가 붙습니다. 이것을 모르면 권한 설정이 됐는지 확인하기 어렵습니다.", "keywords": [ "ACL", "setfacl", "getfacl", "-m", "-R", "access control" ], "source_id": "ubuntu-server-docs", "details": [ "`setfacl -m u:사용자:rwx 경로`로 특정 사용자에게 권한 추가. `getfacl`로 현재 ACL 확인.", "기본 ACL(`setfacl -d`)을 설정하면 해당 디렉터리에 새로 생성되는 파일에 자동으로 ACL이 적용됩니다.", "시험 패턴: 여러 사용자에게 다른 권한을 주는 시나리오에서 chmod 대신 setfacl을 사용하는 문제가 출제됩니다." ] }, { "id": "linux-special-perms", "certification": "LFCS / 리눅스마스터", "title": "특수 권한 — SUID, SGID, Sticky Bit", "summary": "SUID(4)는 파일 소유자 권한으로 실행, SGID(2)는 그룹 권한 상속, Sticky Bit(1)은 본인 파일만 삭제 가능하게 제한합니다.", "example": "chmod u+s /usr/bin/passwd # SUID\nchmod g+s /srv/shared # SGID (공유 디렉터리)\nchmod +t /tmp # Sticky bit\nls -la /tmp # drwxrwxrwt 에서 t 확인", "common_mistake": "SUID가 디렉터리에 붙으면 의미가 다릅니다. SGID가 디렉터리에 붙으면 생성되는 파일이 부모 그룹을 상속합니다.", "keywords": [ "SUID", "SGID", "sticky bit", "chmod 4755", "chmod 1777" ], "source_id": "ubuntu-server-docs", "details": [ "SUID 설정된 파일을 실행하면 실행한 사람이 아니라 파일 소유자 권한으로 실행됩니다. `/usr/bin/passwd`가 대표 예입니다.", "SGID를 공유 디렉터리에 설정하면 그 안에 만든 파일들이 디렉터리 그룹을 자동으로 상속해 협업에 유용합니다.", "시험 패턴: `ls -l`에서 `s`, `S`, `t`, `T` 표시를 보고 어떤 특수 권한인지, 또는 8진수 4자리 표기를 해석하는 문제가 출제됩니다." ] }, { "id": "linux-ssh", "certification": "LFCS / 리눅스마스터", "title": "SSH — 원격 접속", "summary": "SSH(Secure Shell)로 원격 서버에 암호화된 연결을 맺습니다. 설정 파일은 서버 쪽 `/etc/ssh/sshd_config`, 클라이언트 쪽 `~/.ssh/config`입니다.", "example": "ssh alice@192.168.1.10\nssh -p 2222 user@server\nssh -i ~/.ssh/mykey.pem ubuntu@host\nsystemctl restart sshd # 설정 변경 후 재시작", "common_mistake": "`sshd_config` 변경 후 `systemctl reload sshd`를 해야 적용됩니다. 수정 전 `sshd -t`로 문법 검사를 먼저 하세요.", "keywords": [ "ssh", "sshd", "sshd_config", "-p", "-i", "PermitRootLogin" ], "source_id": "ubuntu-networking", "details": [ "`sshd_config` 주요 설정: `Port`(포트 변경), `PermitRootLogin no`(root 직접 접속 차단), `PasswordAuthentication no`(키 인증만 허용).", "`~/.ssh/config`에 `Host`, `HostName`, `User`, `IdentityFile`을 정의하면 `ssh 별칭`으로 간단히 접속할 수 있습니다.", "시험 패턴: root 로그인 차단, 포트 변경, 키 인증 강제 등 sshd_config 보안 설정을 변경하는 문제가 자주 출제됩니다." ] }, { "id": "linux-ssh-key", "certification": "LFCS / 리눅스마스터", "title": "SSH 키 인증", "summary": "비밀번호 없이 공개키/개인키 쌍으로 SSH 접속합니다. 개인키는 클라이언트에, 공개키는 서버의 `~/.ssh/authorized_keys`에 등록합니다.", "example": "ssh-keygen -t ed25519 -C 'work key'\nssh-copy-id alice@server # 공개키 자동 복사\ncat ~/.ssh/id_ed25519.pub # 공개키 확인", "common_mistake": "`~/.ssh/` 디렉터리는 700, `authorized_keys`는 600 권한이어야 합니다. 권한이 너무 열려 있으면 SSH가 키를 무시합니다.", "keywords": [ "ssh-keygen", "authorized_keys", "ed25519", "public key", "private key" ], "source_id": "ubuntu-networking", "details": [ "`ssh-keygen -t ed25519`로 최신 알고리즘 키 생성. 생성된 공개키(`.pub`)를 서버 `~/.ssh/authorized_keys`에 추가합니다.", "디렉터리/파일 권한: `~/.ssh`=700, `authorized_keys`=600, 개인키=600. 이를 벗어나면 접속 거부됩니다.", "시험 패턴: 키 생성, 공개키 배포, authorized_keys 권한 설정까지 이어지는 실습 문제가 출제됩니다." ] }, { "id": "linux-hostname-hosts", "certification": "LFCS / 리눅스마스터", "title": "hostname과 /etc/hosts", "summary": "`hostname`으로 현재 호스트명을 확인하고, `/etc/hosts`로 DNS 없이 IP-이름 매핑을 설정합니다.", "example": "hostname\nhostnamectl set-hostname webserver01\ncat /etc/hosts\necho '192.168.1.10 db.internal' >> /etc/hosts", "common_mistake": "`hostname 이름`은 임시 변경입니다. 재부팅 후에도 유지하려면 `hostnamectl set-hostname`을 사용하세요.", "keywords": [ "hostname", "hostnamectl", "/etc/hosts", "FQDN" ], "source_id": "ubuntu-networking", "details": [ "`hostnamectl set-hostname 이름`은 `/etc/hostname`을 수정해 영구 변경합니다. `hostnamectl status`로 현재 상태를 확인합니다.", "`/etc/hosts`는 DNS보다 먼저 조회됩니다. 내부망 서버 이름 매핑이나 DNS 차단 테스트에 활용합니다.", "시험 패턴: 서버의 호스트명을 영구 변경하거나, /etc/hosts에 항목을 추가하는 명령을 작성하는 문제가 출제됩니다." ] }, { "id": "linux-dns-resolve", "certification": "LFCS / 리눅스마스터", "title": "DNS 조회 — dig, nslookup, resolvectl", "summary": "도메인 이름을 IP로 해석하는 과정을 확인하고 문제를 진단합니다. DNS 서버는 `/etc/resolv.conf` 또는 `systemd-resolved`가 관리합니다.", "example": "dig google.com\nnslookup google.com\nresolvectl status\ncat /etc/resolv.conf", "common_mistake": "Ubuntu에서 `/etc/resolv.conf`는 `systemd-resolved`의 심볼릭 링크입니다. DNS 서버 변경은 `resolvectl`이나 netplan에서 합니다.", "keywords": [ "dig", "nslookup", "resolv.conf", "nameserver", "systemd-resolved" ], "source_id": "ubuntu-networking", "details": [ "`dig 도메인` 결과에서 ANSWER SECTION의 IP가 실제 해석된 주소입니다. `dig +short 도메인`으로 IP만 출력할 수 있습니다.", "DNS 서버는 `/etc/resolv.conf`의 `nameserver` 줄에서 확인합니다. Ubuntu 22.04는 127.0.0.53(로컬 stub)이 기본입니다.", "시험 패턴: DNS 조회 명령으로 도메인 해석 결과를 확인하거나, DNS 서버 설정 파일 위치를 묻는 문제가 출제됩니다." ] }, { "id": "linux-route", "certification": "LFCS / 리눅스마스터", "title": "라우팅 확인 — ip route", "summary": "패킷이 어느 경로로 나가는지 라우팅 테이블을 확인하고, 임시 라우트를 추가하거나 삭제합니다.", "example": "ip route show\nip route add 10.0.0.0/8 via 192.168.1.1\nip route del 10.0.0.0/8\nip route get 8.8.8.8 # 특정 IP로 가는 경로", "common_mistake": "`ip route add`로 추가한 라우트는 재부팅하면 사라집니다. 영구 설정은 netplan 또는 `/etc/network/interfaces`에서 합니다.", "keywords": [ "ip route", "gateway", "routing table", "default", "via" ], "source_id": "linux-man7-ip", "details": [ "`ip route show`에서 `default via 게이트웨이IP dev 인터페이스` 줄이 기본 게이트웨이입니다.", "`ip route get 목적지IP`는 실제로 그 IP에 패킷을 보낼 때 사용할 경로와 출구 인터페이스를 보여줍니다.", "시험 패턴: 라우팅 테이블에서 기본 게이트웨이를 확인하거나, 특정 네트워크로 임시 라우트를 추가하는 명령을 작성하는 문제가 출제됩니다." ] }, { "id": "linux-netplan", "certification": "LFCS / 리눅스마스터", "title": "netplan — 네트워크 설정", "summary": "Ubuntu 18.04 이후 기본 네트워크 설정 도구입니다. `/etc/netplan/*.yaml` 파일에 설정하고 `netplan apply`로 적용합니다.", "example": "# /etc/netplan/00-installer-config.yaml\nnetwork:\n ethernets:\n eth0:\n addresses: [192.168.1.100/24]\n gateway4: 192.168.1.1\nnetplan apply", "common_mistake": "YAML은 들여쓰기(스페이스만, 탭 금지)가 매우 엄격합니다. 들여쓰기 오류 시 `netplan apply`가 실패합니다.", "keywords": [ "netplan", "yaml", "static IP", "gateway4", "nameservers" ], "source_id": "ubuntu-networking", "details": [ "`netplan generate`는 설정을 백엔드 설정 파일로 변환만 하고, `netplan apply`가 실제 네트워크에 적용합니다.", "정적 IP 설정: `addresses`, `gateway4/routes`, `nameservers.addresses`를 YAML에 정의합니다.", "시험 패턴: 정적 IP를 설정하거나 DNS 서버를 변경하는 netplan YAML 내용을 작성하는 문제가 출제됩니다." ] }, { "id": "linux-curl", "certification": "LFCS / 리눅스마스터", "title": "curl — HTTP 요청과 파일 다운로드", "summary": "HTTP/HTTPS 요청을 보내고 응답을 확인합니다. API 테스트, 파일 다운로드, 서비스 동작 확인에 사용합니다.", "example": "curl http://localhost:8080/health\ncurl -O https://example.com/file.tar.gz\ncurl -H 'Content-Type: application/json' -d '{\"key\":\"val\"}' -X POST http://api/endpoint\ncurl -I https://example.com # 헤더만", "common_mistake": "`curl URL`은 내용을 stdout에 출력합니다. 파일로 저장하려면 `-o 파일명` 또는 URL과 같은 이름으로 저장은 `-O`를 씁니다.", "keywords": [ "curl", "-O", "-o", "-H", "-d", "-X", "-I", "HTTP" ], "source_id": "linux-man7-ip", "details": [ "주요 옵션: `-o 파일`(저장), `-O`(원본 파일명), `-L`(리다이렉트 따라가기), `-k`(SSL 검증 무시), `-s`(silent), `-v`(상세).", "`curl -I URL`은 HTTP 헤더만 확인. 상태 코드(200, 404, 301 등)로 서비스 응답을 빠르게 확인합니다.", "시험 패턴: 서비스 동작 확인, 파일 다운로드, 간단한 API 요청 명령을 작성하는 문제가 출제됩니다." ] }, { "id": "linux-ping", "certification": "LFCS / 리눅스마스터", "title": "ping — 네트워크 연결 확인", "summary": "ICMP echo 요청으로 호스트에 도달 가능한지 확인합니다. 네트워크 문제 진단의 첫 번째 단계입니다.", "example": "ping -c 4 8.8.8.8\nping -c 1 192.168.1.1 # 게이트웨이 확인\nping6 ::1 # IPv6 루프백", "common_mistake": "방화벽이 ICMP를 차단하면 ping이 실패해도 실제로는 연결이 가능한 경우가 있습니다. ping 실패 = 서비스 장애는 아닙니다.", "keywords": [ "ping", "-c", "ICMP", "latency", "packet loss" ], "source_id": "ubuntu-networking", "details": [ "`-c 횟수`로 보낼 패킷 수를 제한합니다. 지정 않으면 Ctrl+C 누를 때까지 계속 전송합니다.", "출력에서 `time=`은 RTT(왕복 시간), `packet loss %`는 패킷 손실률. 100% loss면 경로 문제 또는 방화벽 차단입니다.", "시험 패턴: 특정 호스트의 연결 가능 여부 확인, `-c` 옵션으로 패킷 수 제한하는 명령이 출제됩니다." ] }, { "id": "linux-cron", "certification": "LFCS / 리눅스마스터", "title": "cron — 작업 스케줄링", "summary": "지정한 시각이나 주기에 명령을 자동으로 실행합니다. `crontab -e`로 사용자별 스케줄을 관리합니다.", "example": "crontab -e # 편집\ncrontab -l # 목록 확인\n# 매일 새벽 2시에 백업\n0 2 * * * /usr/local/bin/backup.sh\n# 매 5분마다\n*/5 * * * * /usr/local/bin/check.sh", "common_mistake": "cron 작업에서는 PATH가 일반 쉘과 다릅니다. 명령을 절대경로로 쓰거나 스크립트 안에서 PATH를 직접 설정하세요.", "keywords": [ "cron", "crontab", "-e", "-l", "schedule", "*/5" ], "source_id": "ubuntu-server-docs", "details": [ "crontab 형식: `분 시 일 월 요일 명령`. 별표(*)는 '모든 값', `*/5`는 '5마다', `0,30`은 '0과 30'을 의미합니다.", "시스템 전체 cron은 `/etc/cron.d/`, `/etc/cron.daily/` 등에서 관리합니다. `/var/log/syslog`에 실행 기록이 남습니다.", "시험 패턴: 특정 주기(매일, 매시간, 매 N분)로 스크립트를 실행하는 crontab 항목을 작성하는 문제가 출제됩니다." ] }, { "id": "linux-top", "certification": "LFCS / 리눅스마스터", "title": "top — 실시간 시스템 모니터", "summary": "CPU·메모리·프로세스를 실시간으로 모니터링합니다. 리소스를 많이 쓰는 프로세스를 빠르게 찾을 때 사용합니다.", "example": "top\ntop -u alice # 특정 사용자 프로세스만\ntop -bn 1 # 1회만 출력 (스크립트용)\nhtop # 더 보기 좋은 대안", "common_mistake": "`top` 실행 중 `k` 키로 PID를 입력하면 프로세스를 종료할 수 있습니다. 잘못 누르지 않도록 주의하세요.", "keywords": [ "top", "CPU", "memory", "load average", "%MEM", "%CPU" ], "source_id": "ubuntu-server-docs", "details": [ "상단 요약: load average(1분/5분/15분 평균 부하), Tasks(프로세스 수), %Cpu(us/sy/id), Mem/Swap 사용량.", "컬럼 의미: PID, USER, %CPU, %MEM, RES(실제 메모리), S(상태: R=실행/S=대기/Z=좀비).", "시험 패턴: CPU나 메모리를 가장 많이 쓰는 프로세스 찾기, 로드 애버리지 해석, 프로세스 상태 확인 문제가 출제됩니다." ] }, { "id": "linux-nice", "certification": "LFCS / 리눅스마스터", "title": "nice, renice — 프로세스 우선순위", "summary": "프로세스의 CPU 스케줄링 우선순위를 조정합니다. 값이 낮을수록(-20~+19) 우선순위가 높으며, 높은 우선순위 설정은 root만 가능합니다.", "example": "nice -n 10 gzip big_file.gz # 낮은 우선순위로 시작\nrenice -n -5 -p 1234 # 실행 중인 프로세스 변경\nps -o pid,ni,cmd -p 1234 # 현재 nice 값 확인", "common_mistake": "nice 값이 낮을수록 우선순위가 높습니다(-20이 최고). 일반 사용자는 현재보다 낮게(낮은 우선순위로)만 변경 가능합니다.", "keywords": [ "nice", "renice", "priority", "niceness", "-20", "+19" ], "source_id": "ubuntu-server-docs", "details": [ "기본 nice 값은 0. 백그라운드 배치 작업은 `nice -n 15`처럼 낮은 우선순위로 실행해 시스템 영향을 줄입니다.", "`renice`로 실행 중인 프로세스의 우선순위를 바꿀 수 있습니다. `-p PID`로 프로세스, `-u 사용자`로 사용자 전체를 변경합니다.", "시험 패턴: 특정 nice 값으로 프로세스를 실행하거나 실행 중인 프로세스의 우선순위를 변경하는 명령을 작성하는 문제가 출제됩니다." ] }, { "id": "linux-lsblk", "certification": "LFCS / 리눅스마스터", "title": "lsblk — 블록 장치 확인", "summary": "디스크, 파티션, LVM 등 블록 장치와 마운트 정보를 트리 형태로 보여줍니다.", "example": "lsblk\nlsblk -f # 파일시스템 타입과 UUID 포함\nblkid # UUID와 타입 상세 확인", "common_mistake": "`lsblk`는 블록 장치 구조를 보여주고, `df -h`는 마운트된 파일시스템의 사용량을 보여줍니다. 역할이 다릅니다.", "keywords": [ "lsblk", "blkid", "partition", "UUID", "FSTYPE", "block device" ], "source_id": "ubuntu-storage", "details": [ "출력 컬럼: NAME(장치명), SIZE, TYPE(disk/part/lvm), MOUNTPOINT. `sda`는 디스크, `sda1`은 첫 파티션.", "`lsblk -f`는 파일시스템 타입(ext4, xfs 등)과 UUID를 함께 보여줍니다. `/etc/fstab` 설정 시 UUID를 여기서 복사합니다.", "시험 패턴: 마운트 가능한 파티션 목록 확인, UUID 조회, 디스크 구조 파악 문제에서 활용됩니다." ] }, { "id": "linux-fstab", "certification": "LFCS / 리눅스마스터", "title": "/etc/fstab — 자동 마운트 설정", "summary": "부팅 시 자동으로 마운트할 파일시스템을 정의합니다. UUID, 장치명, 마운트 포인트, 파일시스템 타입, 옵션, dump/pass를 지정합니다.", "example": "# UUID를 사용한 fstab 항목\nUUID=xxxx-yyyy /mnt/data ext4 defaults 0 2\n# 확인 및 테스트\nmount -a # fstab 전체 마운트 시도", "common_mistake": "fstab에 오류가 있으면 부팅 자체가 실패할 수 있습니다. 변경 후 `mount -a`로 테스트하고, UUID는 `blkid`로 확인하세요.", "keywords": [ "fstab", "UUID", "mount -a", "defaults", "auto mount" ], "source_id": "ubuntu-storage", "details": [ "fstab 형식: `장치 마운트포인트 타입 옵션 dump pass`. dump=0(백업 제외), pass=0(검사 안 함)/1(루트)/2(기타).", "장치 지정은 UUID가 안전합니다. `/dev/sda1`은 디스크 추가 시 이름이 바뀔 수 있지만 UUID는 고정입니다.", "시험 패턴: 특정 파티션을 부팅 시 자동 마운트하도록 fstab에 항목을 추가하는 실습 문제가 출제됩니다." ] }, { "id": "linux-swap", "certification": "LFCS / 리눅스마스터", "title": "swap — 스왑 관리", "summary": "물리 메모리가 부족할 때 디스크 일부를 임시 메모리로 사용합니다. 스왑 파티션과 스왑 파일 두 가지 방식이 있습니다.", "example": "swapon --show # 현재 스왑 확인\nfallocate -l 2G /swapfile\nchmod 600 /swapfile\nmkswap /swapfile\nswapon /swapfile", "common_mistake": "스왑 파일은 반드시 root만 읽을 수 있도록 `chmod 600`을 해야 합니다. 권한이 열려 있으면 `swapon`이 실패합니다.", "keywords": [ "swap", "swapon", "swapoff", "mkswap", "swapfile", "/proc/swaps" ], "source_id": "ubuntu-storage", "details": [ "스왑 파일 생성 순서: `fallocate -l 크기 /swapfile` → `chmod 600` → `mkswap` → `swapon` → `/etc/fstab`에 추가.", "영구 활성화: `/etc/fstab`에 `/swapfile none swap sw 0 0` 추가. `swapon -a`로 fstab의 스왑을 모두 활성화합니다.", "시험 패턴: 특정 크기의 스왑 파일을 만들고 활성화하는 전체 과정을 작성하는 실습 문제가 출제됩니다." ] }, { "id": "linux-lvm", "certification": "LFCS / 리눅스마스터", "title": "LVM — 논리 볼륨 관리", "summary": "물리 디스크(PV)를 볼륨 그룹(VG)으로 묶고, 그 안에 유연하게 크기를 조정할 수 있는 논리 볼륨(LV)을 만듭니다.", "example": "pvcreate /dev/sdb\nvgcreate datavg /dev/sdb\nlvcreate -L 10G -n datalv datavg\nmkfs.ext4 /dev/datavg/datalv\nlvextend -L +5G /dev/datavg/datalv && resize2fs /dev/datavg/datalv", "common_mistake": "`lvextend`로 LV 크기를 늘린 뒤 파일시스템도 늘려야 합니다. ext4는 `resize2fs`, xfs는 `xfs_growfs`를 씁니다.", "keywords": [ "LVM", "pvcreate", "vgcreate", "lvcreate", "lvextend", "resize2fs" ], "source_id": "ubuntu-storage", "details": [ "LVM 3계층: PV(물리 볼륨, 실제 디스크/파티션) → VG(볼륨 그룹) → LV(논리 볼륨, 파일시스템이 올라가는 곳).", "확장 절차: `lvextend -L +크기 /dev/VG/LV` 후 `resize2fs /dev/VG/LV`(ext4) 또는 `xfs_growfs /마운트포인트`(xfs).", "시험 패턴: PV→VG→LV 생성 순서, LV 확장 후 파일시스템 확장까지 이어지는 실습 문제가 출제됩니다." ] }, { "id": "linux-logs-var", "certification": "LFCS / 리눅스마스터", "title": "/var/log — 시스템 로그 파일", "summary": "Linux의 주요 로그 파일들은 `/var/log/`에 저장됩니다. 서비스별, 목적별로 파일이 나뉘어 있어 문제 진단의 출발점입니다.", "example": "tail -f /var/log/syslog\ngrep 'ERROR' /var/log/auth.log\nls -lh /var/log/\nzcat /var/log/syslog.1.gz # 회전된 로그", "common_mistake": "`/var/log/syslog`는 일반 시스템 메시지, `/var/log/auth.log`는 인증 관련. journalctl은 이 파일이 아니라 journal을 읽습니다.", "keywords": [ "syslog", "auth.log", "dmesg", "/var/log", "logrotate" ], "source_id": "ubuntu-server-docs", "details": [ "주요 파일: `syslog`(일반 시스템), `auth.log`(SSH/sudo/PAM 인증), `kern.log`(커널), `dpkg.log`(패키지 설치/제거).", "`logrotate`가 자동으로 로그를 회전합니다. 이전 로그는 `.1`, `.2` 또는 `.gz`(압축) 형태로 보관됩니다.", "시험 패턴: 특정 이벤트(로그인 실패, 서비스 오류)를 해당 로그 파일에서 찾는 명령을 작성하는 문제가 출제됩니다." ] }, { "id": "linux-dmesg", "certification": "LFCS / 리눅스마스터", "title": "dmesg — 커널 링 버퍼 로그", "summary": "커널이 부팅 시와 하드웨어 이벤트 발생 시 기록하는 메시지를 출력합니다. 디스크 오류, 네트워크 인터페이스 UP/DOWN 등 하드웨어 문제 진단에 씁니다.", "example": "dmesg | tail -20\ndmesg | grep -i error\ndmesg -T # 사람이 읽을 수 있는 타임스탬프\ndmesg --level=err,warn", "common_mistake": "`dmesg`는 커널 레벨 메시지만 보여줍니다. 서비스 로그는 `journalctl -u 서비스명`으로 확인하세요.", "keywords": [ "dmesg", "kernel", "hardware", "-T", "--level", "ring buffer" ], "source_id": "ubuntu-server-docs", "details": [ "디스크 I/O 오류는 `dmesg | grep -i 'error\\|fail\\|sda'`로 찾을 수 있습니다.", "`dmesg -T`는 타임스탬프를 사람이 읽기 쉬운 날짜 형식으로 변환합니다. 기본 출력은 부팅 이후 초 단위입니다.", "시험 패턴: 시스템 부팅 오류나 하드웨어 문제를 dmesg에서 찾는 문제, 또는 로그 레벨 필터링 명령이 출제됩니다." ] }, { "id": "linux-env-path", "certification": "LFCS / 리눅스마스터", "title": "환경 변수와 PATH", "summary": "환경 변수는 쉘과 프로세스에 설정을 전달합니다. PATH는 명령을 찾는 디렉터리 목록으로, 새 프로그램을 설치 후 PATH에 추가해야 할 수 있습니다.", "example": "echo $PATH\nexport PATH=$PATH:/opt/myapp/bin\nprintenv HOME USER\nenv | grep JAVA\nunset MYVAR", "common_mistake": "`export VAR=값`은 현재 쉘과 자식 프로세스에만 적용됩니다. 영구 설정은 `~/.bashrc` 또는 `/etc/environment`에 추가하세요.", "keywords": [ "PATH", "export", "env", "printenv", "$HOME", "~/.bashrc" ], "source_id": "linux-bash-cd", "details": [ "`export 변수=값`으로 환경 변수를 설정하면 자식 프로세스에 전달됩니다. 없이 `변수=값`만 하면 현재 쉘에만 적용됩니다.", "영구 설정 위치: 사용자별은 `~/.bashrc` 또는 `~/.profile`, 시스템 전체는 `/etc/environment` 또는 `/etc/profile`.", "시험 패턴: PATH에 디렉터리를 추가하거나, 특정 환경 변수를 확인/설정하는 명령, 영구 설정 파일 위치를 묻는 문제가 출제됩니다." ] }, { "id": "linux-wildcard", "certification": "LFCS / 리눅스마스터", "title": "와일드카드와 파일 글로빙", "summary": "쉘이 패턴을 실제 파일 이름으로 확장합니다. `*`(모든 문자), `?`(한 문자), `[abc]`(문자 클래스)를 조합해 씁니다.", "example": "ls *.log\nrm /tmp/test?.txt # test1.txt, test2.txt 등\ncp /etc/[a-z]*.conf /backup/\nls {*.txt,*.md} # brace expansion", "common_mistake": "와일드카드는 쉘이 명령 실행 전에 파일 목록으로 확장합니다. 매칭되는 파일이 없으면 명령이 패턴 문자열을 그대로 인자로 받습니다.", "keywords": [ "wildcard", "glob", "*", "?", "[]", "brace expansion" ], "source_id": "linux-bash-cd", "details": [ "`*`는 0개 이상의 임의 문자, `?`는 정확히 1개 문자, `[0-9]`는 범위 안의 한 문자, `[!abc]`는 제외입니다.", "Brace expansion: `file{1,2,3}.txt`는 file1.txt file2.txt file3.txt로 확장됩니다. 파일이 없어도 동작합니다.", "시험 패턴: 특정 패턴의 파일을 한 번에 처리하거나, 와일드카드 표현식이 어떤 파일에 매칭되는지 판단하는 문제가 출제됩니다." ] }, { "id": "linux-exit-code", "certification": "LFCS / 리눅스마스터", "title": "exit code — 명령 종료 코드", "summary": "명령 실행 후 반환하는 숫자(0~255). 0은 성공, 0이 아니면 오류. 스크립트에서 이전 명령 성공 여부를 `$?`로 확인합니다.", "example": "ls /etc && echo '성공'\nls /없는경로 || echo '실패'\necho $?\ncommand; [ $? -eq 0 ] && echo ok", "common_mistake": "`$?`는 바로 직전 명령의 종료 코드만 담습니다. 다른 명령 실행 후 이전 `$?`를 참조하려면 변수에 저장해야 합니다.", "keywords": [ "exit code", "$?", "&&", "||", "return code", "0=success" ], "source_id": "linux-bash-cd", "details": [ "`&&`는 앞 명령이 성공(exit 0)할 때만 뒤를 실행. `||`는 실패(exit ≠0)할 때만 뒤를 실행합니다.", "자주 보는 코드: 0=성공, 1=일반 오류, 2=명령 오용, 126=실행 권한 없음, 127=명령 없음, 130=Ctrl+C.", "시험 패턴: `&&`와 `||`로 조건부 실행을 작성하거나, `$?` 값으로 이전 명령 성공 여부를 판단하는 스크립트 문제가 출제됩니다." ] }, { "id": "linux-service-port", "certification": "LFCS / 리눅스마스터", "title": "서비스와 포트 연결", "summary": "실행 중인 서비스가 어느 포트를 열고 있는지 확인하고, 방화벽 설정과 함께 포트 접근을 제어합니다.", "example": "ss -tlnp | grep 80\ncat /etc/services | grep ssh\nlsof -i :443\nufw allow 80/tcp", "common_mistake": "포트를 열었어도 방화벽(ufw/firewalld)이 차단하면 외부에서 접근할 수 없습니다. 서비스와 방화벽을 함께 확인하세요.", "keywords": [ "ss", "lsof", "/etc/services", "port", "firewall", "ufw" ], "source_id": "ubuntu-networking", "details": [ "`ss -tlnp`는 TCP 리스닝 포트와 서비스를 보여줍니다. `lsof -i :포트`는 해당 포트를 사용하는 프로세스를 찾습니다.", "`/etc/services`는 포트 번호와 서비스 이름 매핑 파일입니다. 22=ssh, 80=http, 443=https, 3306=mysql.", "시험 패턴: 특정 포트를 리스닝하는 서비스 확인, 방화벽에서 포트 개방, 서비스 포트 번호를 조회하는 문제가 출제됩니다." ] }, { "id": "linux-apt", "certification": "LFCS / 리눅스마스터", "title": "apt — 패키지 관리", "summary": "Ubuntu/Debian 계열의 패키지 관리 도구입니다. 패키지 설치, 업데이트, 검색, 삭제를 담당합니다.", "example": "apt update && apt upgrade -y\napt install nginx\napt search 'web server'\napt show nginx\napt list --installed | grep nginx", "common_mistake": "`apt install` 전에 `apt update`를 먼저 실행해야 최신 패키지 목록에서 설치됩니다. update 없이 설치하면 구버전이 설치될 수 있습니다.", "keywords": [ "apt", "apt update", "apt install", "apt upgrade", "dpkg" ], "source_id": "ubuntu-package-management", "details": [ "`apt update`는 패키지 목록만 갱신, `apt upgrade`는 실제 업데이트 설치. 항상 update → upgrade 순서로 실행합니다.", "`dpkg -l | grep 패키지`로 설치 여부 확인, `dpkg -L 패키지`로 설치된 파일 목록을 볼 수 있습니다.", "시험 패턴: 특정 패키지 설치, 설치 여부 확인, 모든 패키지 업데이트하는 명령을 작성하는 문제가 출제됩니다." ] }, { "id": "linux-repo", "certification": "LFCS / 리눅스마스터", "title": "APT 저장소 관리", "summary": "패키지를 다운로드하는 저장소(repository) 목록을 관리합니다. `/etc/apt/sources.list` 또는 `/etc/apt/sources.list.d/`에 저장소를 추가합니다.", "example": "cat /etc/apt/sources.list\nadd-apt-repository ppa:name/repo\napt-key add key.gpg # 구식\ncurl -fsSL URL | gpg --dearmor > /etc/apt/keyrings/key.gpg", "common_mistake": "외부 저장소를 추가할 때 GPG 키도 함께 등록해야 합니다. 키 없이 저장소만 추가하면 `apt update` 시 서명 오류가 납니다.", "keywords": [ "sources.list", "PPA", "repository", "gpg", "apt-key", "add-apt-repository" ], "source_id": "ubuntu-package-management", "details": [ "`/etc/apt/sources.list.d/`에 개별 `.list` 파일을 넣는 방식이 관리가 쉽습니다. 주 sources.list는 가급적 수정하지 않습니다.", "최신 방식은 GPG 키를 `/etc/apt/keyrings/`에 저장하고 sources 파일에서 `signed-by=` 옵션으로 참조합니다.", "시험 패턴: 저장소 추가 후 `apt update`, 패키지 설치까지 이어지는 절차를 작성하는 문제가 출제됩니다." ] }, { "id": "linux-remove-purge", "certification": "LFCS / 리눅스마스터", "title": "패키지 제거 — remove와 purge", "summary": "`apt remove`는 패키지 바이너리만 제거하고 설정 파일은 남깁니다. `apt purge`는 설정 파일까지 완전히 제거합니다.", "example": "apt remove nginx\napt purge nginx\napt autoremove # 의존성으로만 설치된 불필요 패키지 제거\ndpkg --list | grep ^rc # 설정 남은 제거된 패키지", "common_mistake": "`remove` 후 재설치하면 이전 설정 파일이 남아 있어 예상치 못한 동작을 할 수 있습니다. 깨끗이 제거하려면 `purge`를 씁니다.", "keywords": [ "apt remove", "apt purge", "autoremove", "dpkg --purge" ], "source_id": "ubuntu-package-management", "details": [ "`apt autoremove`는 다른 패키지의 의존성으로 설치됐다가 더 이상 필요 없는 패키지들을 자동으로 제거합니다.", "`dpkg --list | grep '^rc'`로 바이너리는 지워졌지만 설정 파일이 남은 패키지를 찾을 수 있습니다.", "시험 패턴: 패키지를 설정 파일까지 완전히 제거하거나, 불필요 의존성을 정리하는 명령을 작성하는 문제가 출제됩니다." ] }, { "id": "linux-ufw", "certification": "LFCS / 리눅스마스터", "title": "ufw — 방화벽 관리", "summary": "Ubuntu의 간단한 방화벽 관리 도구입니다. iptables 위에서 동작하며 서비스 이름이나 포트로 규칙을 추가할 수 있습니다.", "example": "ufw status verbose\nufw enable\nufw allow 22/tcp\nufw allow 'Nginx Full'\nufw deny 3306\nufw delete allow 80", "common_mistake": "`ufw enable` 전에 반드시 SSH 포트(22)를 허용하세요. 순서를 바꾸면 SSH 연결이 끊겨 서버에 접근하지 못합니다.", "keywords": [ "ufw", "enable", "allow", "deny", "status", "firewall" ], "source_id": "ubuntu-firewall", "details": [ "규칙 추가 형식: `ufw allow/deny 포트/프로토콜` 또는 `ufw allow 'Apache'`처럼 사전 정의된 애플리케이션 프로필 사용.", "`ufw status numbered`로 번호가 붙은 규칙 목록 확인 후 `ufw delete 번호`로 특정 규칙을 삭제합니다.", "시험 패턴: 특정 포트 개방/차단, SSH는 허용하면서 불필요한 포트 차단, 방화벽 상태 확인 명령이 출제됩니다." ] }, { "id": "linux-head-tail", "certification": "LFCS / 리눅스마스터", "title": "head, tail — 파일 앞뒤 확인", "summary": "`head`는 파일 처음 N줄, `tail`은 마지막 N줄을 출력합니다. `tail -f`는 로그 파일에 추가되는 내용을 실시간으로 추적합니다.", "example": "head -n 20 /etc/passwd\ntail -n 50 /var/log/syslog\ntail -f /var/log/nginx/error.log\ntail -f /var/log/syslog | grep ERROR", "common_mistake": "`head`는 파일 시작, `tail`은 파일 끝에서 읽습니다. `-n` 없이 쓰면 기본 10줄을 출력합니다.", "keywords": [ "head", "tail", "-n", "-f", "log", "follow" ], "source_id": "linux-bash-manual", "details": [ "`tail -f`는 파일에 새로 추가되는 내용을 실시간으로 보여줍니다. 서비스 로그 모니터링 시 가장 많이 씁니다.", "`tail -n +5`는 5번째 줄부터 끝까지 출력합니다. 헤더 행을 건너뛸 때 활용합니다.", "시험 패턴: 로그 마지막 N줄 확인, 실시간 로그 추적, 파이프로 grep과 연결하는 명령이 출제됩니다." ] }, { "id": "linux-sed", "certification": "LFCS / 리눅스마스터", "title": "sed — 스트림 편집기", "summary": "파일이나 파이프 입력에서 패턴을 찾아 교체·삭제·출력합니다. 설정 파일 자동 수정과 텍스트 변환 스크립트에 필수입니다.", "example": "sed 's/old/new/g' file.txt\nsed -i 's/localhost/127.0.0.1/g' nginx.conf\nsed -n '5,10p' file.txt # 5~10줄만 출력\nsed '/^#/d' config.txt # 주석 줄 삭제", "common_mistake": "`-i` 없이는 원본을 수정하지 않고 stdout으로만 출력합니다. `-i.bak`으로 원본을 백업하면서 수정할 수 있습니다.", "keywords": [ "sed", "s/old/new/g", "-i", "stream editor", "substitute", "delete" ], "source_id": "linux-bash-manual", "details": [ "치환 명령: `s/패턴/교체/g`. `g` 플래그 없으면 줄당 첫 번째만, `I` 플래그는 대소문자 무시.", "줄 단위 작업: `Nd`(N번 줄 삭제), `Np`(N번 줄만 출력, `-n`과 함께), `/패턴/d`(패턴 줄 삭제).", "시험 패턴: 설정 파일에서 값을 치환하거나(`-i`), 특정 줄을 출력/삭제하는 명령을 작성하는 문제가 출제됩니다." ] }, { "id": "linux-text-pipeline", "certification": "LFCS / 리눅스마스터", "title": "텍스트 처리 — cut, sort, uniq, wc", "summary": "텍스트 파이프라인을 구성하는 핵심 도구들입니다. 필드 추출(cut), 정렬(sort), 중복 제거(uniq), 줄/단어 수 세기(wc)를 파이프로 연결합니다.", "example": "cut -d':' -f1 /etc/passwd | sort | uniq\nwc -l /var/log/syslog\ncat access.log | cut -d' ' -f1 | sort | uniq -c | sort -rn | head -10", "common_mistake": "`uniq`는 연속된 중복만 제거합니다. 전체 중복 제거를 위해서는 반드시 `sort` 후 `uniq`를 써야 합니다.", "keywords": [ "cut", "sort", "uniq", "wc", "-d", "-f", "-c", "-rn" ], "source_id": "linux-bash-manual", "details": [ "`cut -d구분자 -f필드번호`: 콜론 구분자에서 1번 필드 → `cut -d':' -f1`. 여러 필드는 `-f1,3` 또는 `-f1-3`.", "`sort -rn`: r=역순, n=숫자 정렬. `uniq -c`는 중복 개수를 앞에 붙여 줍니다.", "시험 패턴: 로그에서 상위 접속 IP 추출, 중복 제거 후 정렬, 줄 수 세기 등 파이프라인을 조합하는 문제가 출제됩니다." ] }, { "id": "linux-awk", "certification": "LFCS / 리눅스마스터", "title": "awk — 필드 기반 텍스트 처리", "summary": "공백이나 지정 구분자로 나뉜 필드를 처리합니다. `cut`보다 강력하며 조건문, 연산, 합산이 가능합니다.", "example": "awk '{print $1, $3}' access.log\nawk -F':' '{print $1}' /etc/passwd\nawk '$3 > 1000 {print $1}' /etc/passwd\nps aux | awk '{print $1, $11}' | head", "common_mistake": "awk에서 `$0`은 줄 전체, `$1`은 첫 번째 필드입니다. `-F`로 구분자를 바꾸지 않으면 기본으로 공백/탭이 구분자입니다.", "keywords": [ "awk", "-F", "$1", "NR", "NF", "print", "field" ], "source_id": "linux-bash-manual", "details": [ "기본 패턴: `awk '조건 {동작}' 파일`. 조건 없이 `{print $2}`만 쓰면 모든 줄에서 2번째 필드를 출력합니다.", "내장 변수: `NR`=현재 줄 번호, `NF`=필드 개수. `NR==1`은 첫 번째 줄만, `$NF`는 마지막 필드입니다.", "시험 패턴: 특정 필드만 출력하거나, 조건에 맞는 줄만 출력하는 awk 명령을 작성하는 문제가 출제됩니다." ] }, { "id": "linux-ln-symlink", "certification": "LFCS / 리눅스마스터", "title": "ln — 하드 링크와 심볼릭 링크", "summary": "심볼릭 링크(`ln -s`)는 원본 파일의 경로를 가리키는 포인터입니다. 하드 링크는 같은 inode를 직접 참조합니다.", "example": "ln -s /etc/nginx/nginx.conf ~/nginx.conf\nln /data/file.txt /backup/file.txt # 하드 링크\nls -la ~/nginx.conf # -> 원본 경로 표시\nreadlink -f ~/nginx.conf # 실제 경로 확인", "common_mistake": "심볼릭 링크는 원본이 삭제되면 끊긴 링크(dangling symlink)가 됩니다. 하드 링크는 원본 삭제 후에도 데이터가 유지됩니다.", "keywords": [ "ln", "-s", "symlink", "hard link", "inode", "readlink" ], "source_id": "linux-bash-manual", "details": [ "심볼릭 링크: `ln -s 원본경로 링크경로`. `ls -la`에서 `l`로 시작하며 `->` 뒤에 원본 경로가 표시됩니다.", "하드 링크는 같은 파티션 내에서만 가능, 디렉터리에는 사용 불가. 심볼릭 링크는 파티션과 디렉터리 모두 가능합니다.", "시험 패턴: 특정 경로에 심볼릭 링크를 만들거나, 링크 타입을 `ls -la`로 구별하는 문제가 출제됩니다." ] }, { "id": "linux-bg-fg-jobs", "certification": "LFCS / 리눅스마스터", "title": "백그라운드 작업 — jobs, bg, fg, nohup", "summary": "터미널을 블록하지 않고 명령을 백그라운드에서 실행합니다. `&`로 시작, `Ctrl+Z`로 일시 정지, `fg`/`bg`로 전환합니다.", "example": "long_task.sh & # 백그라운드 시작\njobs -l # 작업 목록\nfg %1 # 1번 작업 포그라운드 복귀\nnohup ./script.sh & # 터미널 닫혀도 계속 실행", "common_mistake": "`&`로 실행한 작업은 터미널을 닫으면 종료됩니다. 터미널 종료 후에도 계속 실행하려면 `nohup`을 함께 써야 합니다.", "keywords": [ "jobs", "bg", "fg", "nohup", "&", "Ctrl+Z", "SIGHUP" ], "source_id": "linux-bash-cd", "details": [ "`Ctrl+Z`는 현재 프로세스에 SIGTSTP를 보내 일시 정지. `bg`로 백그라운드 재개, `fg`로 포그라운드 복귀.", "`nohup 명령 &`: SIGHUP 시그널을 무시하므로 터미널 종료 후에도 실행 유지. 출력은 기본으로 `nohup.out`에 저장됩니다.", "시험 패턴: 작업을 백그라운드로 보내거나 복귀시키는 명령, nohup 사용 시나리오 문제가 출제됩니다." ] }, { "id": "linux-shell-script-basics", "certification": "LFCS / 리눅스마스터", "title": "쉘 스크립트 기초", "summary": "반복 작업을 자동화하는 배시 스크립트를 작성합니다. shebang 라인, 변수, 조건문, 반복문, 함수가 핵심 요소입니다.", "example": "#!/bin/bash\nset -euo pipefail\nBACKUP_DIR=/backup\n[ -d $BACKUP_DIR ] || mkdir -p $BACKUP_DIR\nfor f in /etc/*.conf; do\n cp $f $BACKUP_DIR/\ndone", "common_mistake": "`#!/bin/bash`(shebang)가 없으면 `/bin/sh`로 실행돼 bash 전용 문법이 오류납니다. 실행 권한(`chmod +x`)도 반드시 확인하세요.", "keywords": [ "shebang", "#!/bin/bash", "if", "for", "while", "function", "chmod +x" ], "source_id": "linux-bash-cd", "details": [ "`set -euo pipefail`: `-e`(에러 시 즉시 종료), `-u`(미정의 변수 사용 시 에러), `-o pipefail`(파이프 중간 실패 감지). 스크립트 상단에 권장됩니다.", "조건 확인: `[ -f 파일 ]`(파일 존재), `[ -d 디렉터리 ]`(디렉터리 존재), `[ $var -eq 1 ]`(숫자 비교), `[[ $str == 'a' ]]`(문자열).", "시험 패턴: 특정 조건에 따라 분기하는 if문, 파일 목록을 처리하는 for 루프, 함수 정의 등 스크립트 작성 문제가 출제됩니다." ] }, { "id": "linux-cp-mv-rm", "certification": "LFCS / 리눅스마스터", "title": "cp, mv, rm — 파일 복사·이동·삭제", "summary": "파일과 디렉터리를 복사(`cp`), 이동/이름변경(`mv`), 삭제(`rm`)합니다. 각 옵션의 조합이 시험에서 시나리오 형태로 출제됩니다.", "example": "cp -a /etc/nginx /backup/nginx.bak # 권한·타임스탬프 보존 복사\nmv config.txt config.bak # 이름 변경\nrm -rf /tmp/old_build/ # 디렉터리 강제 삭제", "common_mistake": "`cp -r`은 디렉터리를 복사하지만 권한과 타임스탬프를 보존하지 않습니다. 백업 목적이라면 반드시 `cp -a`를 사용하세요.", "keywords": [ "cp", "mv", "rm", "-a", "-r", "-i", "-f", "백업" ], "source_id": "manual-linux-basic", "details": [ "**`cp` 핵심 옵션**: `-r`(디렉터리 재귀), `-a`(archive: `-dR --preserve=all`, 백업 시 표준), `-i`(덮어쓰기 전 확인), `-p`(권한·타임스탬프 보존).", "**`mv`**: 같은 파일시스템 내 이동은 inode만 갱신해 빠릅니다. 다른 파티션 간 이동은 실제 복사 후 삭제가 일어납니다.", "**시험 패턴**: '퍼미션을 유지하면서 백업' → `cp -a`, '실수 없이 삭제' → `rm -i`, 'force 삭제' → `rm -f`." ] }, { "id": "linux-fdisk-parted", "certification": "LFCS / 리눅스마스터", "title": "fdisk, parted — 디스크 파티셔닝", "summary": "새 디스크를 사용하기 전 파티션 테이블을 만들고 파티션을 나눕니다. MBR은 `fdisk`, GPT(2TB 이상)는 `parted` 또는 `gdisk`를 사용합니다.", "example": "fdisk /dev/sdb # MBR 파티션 인터랙티브 편집\n# n(새 파티션) → p → 1 → Enter → +20G → w(저장)\nparted /dev/sdc mklabel gpt\nparted /dev/sdc mkpart primary ext4 1MiB 21GiB", "common_mistake": "`fdisk`는 파티션 테이블을 변경해도 `w`로 저장하기 전까지 디스크에 기록되지 않습니다. 또한 2TB 초과 디스크에는 MBR(fdisk) 대신 GPT(parted/gdisk)를 사용해야 합니다.", "keywords": [ "fdisk", "parted", "gdisk", "MBR", "GPT", "partition table", "lsblk" ], "source_id": "manual-linux-storage", "details": [ "**파티션 테이블 유형**: MBR(최대 4 주파티션, 2TB 한계), GPT(최대 128 파티션, 사실상 무제한 용량).", "**fdisk 흐름**: `n`(새 파티션) → 유형 선택(p/e) → 번호 → 시작/끝 섹터(또는 `+20G`) → `w`(저장 후 종료). `p`로 현재 상태 확인.", "**시험 패턴**: lsblk로 장치 확인 → fdisk로 파티션 생성 → mkfs로 포맷 → mount 순서가 전체 스토리지 설정 흐름으로 자주 출제됩니다." ] }, { "id": "linux-mkfs-fsck", "certification": "LFCS / 리눅스마스터", "title": "mkfs, fsck — 파일시스템 생성과 검사", "summary": "파티션에 파일시스템을 생성(`mkfs`)하고 오류를 검사·수정(`fsck`)합니다. 포맷 후 마운트해야 실제로 사용할 수 있습니다.", "example": "mkfs.ext4 /dev/sdb1 # ext4 파일시스템 생성\nmkfs.xfs /dev/sdb2 # XFS 파일시스템 생성\numount /dev/sdb1 && fsck /dev/sdb1 # 검사 전 반드시 언마운트", "common_mistake": "`fsck`는 마운트된 파일시스템에서 실행하면 데이터가 손상될 수 있습니다. 반드시 언마운트하거나 싱글 유저 모드에서 실행해야 합니다.", "keywords": [ "mkfs", "mkfs.ext4", "mkfs.xfs", "fsck", "e2fsck", "tune2fs", "파일시스템" ], "source_id": "manual-linux-storage", "details": [ "**주요 파일시스템**: ext4(리눅스 기본, 저널링), xfs(대용량·고성능, RHEL 기본), btrfs(스냅샷·서브볼륨 지원).", "**`tune2fs -l /dev/sdb1`**: ext4 파일시스템 메타데이터(UUID, 마운트 횟수, 생성일 등)를 확인합니다. UUID는 fstab 설정 시 필요합니다.", "**시험 패턴**: 파티션 생성 후 mkfs → UUID 확인(`blkid`) → fstab에 등록 → mount -a 순서가 통합 스토리지 시나리오로 출제됩니다." ] }, { "id": "linux-groupadd", "certification": "LFCS / 리눅스마스터", "title": "groupadd, groupmod, groupdel — 그룹 관리", "summary": "그룹을 생성(`groupadd`), 수정(`groupmod`), 삭제(`groupdel`)합니다. 사용자를 보조 그룹에 추가하는 `usermod -aG`와 함께 사용합니다.", "example": "groupadd developers # 그룹 생성\ngroupmod -n devops developers # 그룹 이름 변경\nusermod -aG developers alice # alice를 developers 그룹에 추가\ngetent group developers # 그룹 멤버 확인", "common_mistake": "`groupdel`은 해당 그룹이 누군가의 기본 그룹(primary group)이면 삭제할 수 없습니다. 먼저 그 사용자의 기본 그룹을 변경해야 합니다.", "keywords": [ "groupadd", "groupmod", "groupdel", "usermod -aG", "/etc/group", "GID" ], "source_id": "ubuntu-user-management", "details": [ "**`/etc/group` 구조**: `그룹명:암호:GID:멤버목록` 형식. `getent group <이름>`으로 특정 그룹 정보를 확인합니다.", "**보조 그룹 추가**: `usermod -aG groupname username`. `-a`(append) 없이 `-G`만 쓰면 기존 보조 그룹이 교체됩니다.", "**시험 패턴**: 새 팀 생성 → 그룹 만들기 → 여러 사용자를 그룹에 추가 → 그룹 공유 디렉터리에 SGID 설정하는 복합 시나리오가 자주 나옵니다." ] }, { "id": "linux-chage", "certification": "LFCS / 리눅스마스터", "title": "chage — 비밀번호 만료 정책", "summary": "사용자 계정의 비밀번호 만료일, 최대 사용 기간, 경고 기간을 설정합니다. 보안 정책 적용과 계정 만료 시나리오에서 출제됩니다.", "example": "chage -l alice # 현재 만료 정책 확인\nchage -M 90 alice # 최대 90일마다 변경 강제\nchage -E 2025-12-31 alice # 계정 만료일 설정\nchage -d 0 alice # 다음 로그인 시 즉시 비밀번호 변경 강제", "common_mistake": "`chage -d 0`은 마지막 비밀번호 변경일을 에포크(1970-01-01)로 설정해 다음 로그인 시 즉시 변경하게 합니다. `-E 0`은 계정을 즉시 만료시켜 로그인 자체를 차단합니다.", "keywords": [ "chage", "-l", "-M", "-E", "-d", "/etc/shadow", "password aging" ], "source_id": "ubuntu-user-management", "details": [ "**주요 옵션**: `-M`(최대 사용일), `-m`(최소 사용일), `-W`(만료 전 경고일), `-I`(만료 후 비활성화 유예일), `-E`(계정 만료일), `-d`(마지막 변경일).", "**`/etc/shadow`에 저장**: 만료 정책은 shadow 파일에 콜론으로 구분된 필드로 저장됩니다. `chage`는 이 파일을 안전하게 편집하는 래퍼입니다.", "**시험 패턴**: '신규 사용자가 첫 로그인 시 비밀번호를 변경하게' → `chage -d 0`, '90일마다 변경 강제' → `chage -M 90` 형태로 출제됩니다." ] }, { "id": "linux-systemd-unit", "certification": "LFCS / 리눅스마스터", "title": "systemd 서비스 유닛 파일 작성", "summary": "커스텀 프로세스를 systemd 서비스로 등록해 부팅 시 자동 시작하고 재시작 정책을 적용합니다. `/etc/systemd/system/`에 `.service` 파일을 작성합니다.", "example": "# /etc/systemd/system/myapp.service\n[Unit]\nDescription=My Application\nAfter=network.target\n\n[Service]\nExecStart=/usr/local/bin/myapp\nRestart=on-failure\nUser=myapp\n\n[Install]\nWantedBy=multi-user.target\n\nsystemctl daemon-reload && systemctl enable --now myapp", "common_mistake": "유닛 파일을 수정한 후 `systemctl daemon-reload` 없이 재시작하면 변경 사항이 반영되지 않습니다. 파일 수정 후에는 항상 daemon-reload가 먼저입니다.", "keywords": [ "service unit", "ExecStart", "WantedBy", "daemon-reload", "enable", "After", "Restart" ], "source_id": "manual-linux-systemd", "details": [ "**[Unit] 섹션**: `Description`(설명), `After`(이 유닛보다 늦게 시작), `Requires`(의존성, 없으면 실패).", "**[Service] 섹션**: `ExecStart`(실행 명령), `Restart=on-failure`(실패 시 재시작), `User`(실행 계정), `Environment`(환경 변수).", "**시험 패턴**: 스크립트를 서비스로 등록 → 부팅 시 자동 시작 설정 → 재시작 정책 적용의 전체 흐름, daemon-reload 누락 오류 진단이 출제됩니다." ] }, { "id": "linux-at", "certification": "LFCS / 리눅스마스터", "title": "at — 일회성 작업 스케줄링", "summary": "cron이 반복 작업용이라면 `at`은 특정 시각에 한 번만 실행하는 명령에 사용합니다. 대화형으로 명령을 입력하거나 파이프로 전달합니다.", "example": "echo 'tar -czf /backup/home.tar.gz /home' | at 02:00\nat now + 2 hours << 'EOF'\n/usr/local/bin/report.sh\nEOF\natq # 예약 목록 확인\natrm 3 # 3번 작업 취소", "common_mistake": "`at`은 cron과 달리 환경 변수가 최소화된 상태로 실행됩니다. 스크립트에 절대 경로를 사용하거나 환경 변수를 명시적으로 설정해야 합니다.", "keywords": [ "at", "atq", "atrm", "at now", "batch", "일회성 스케줄" ], "source_id": "manual-linux-basic", "details": [ "**시간 표현**: `at 14:30`, `at now + 1 hour`, `at midnight`, `at noon`, `at 2:00 tomorrow`.", "**`batch`**: 시스템 부하가 낮을 때 명령을 실행. at의 변형으로, 부하 기반 스케줄링이 필요할 때 사용합니다.", "**시험 패턴**: cron vs at 선택 기준(반복 vs 일회성), 특정 시각 후 실행 예약, atq로 대기열 확인, atrm으로 취소하는 시나리오가 출제됩니다." ] }, { "id": "linux-docker-basics", "certification": "LFCS / 리눅스마스터", "title": "Docker — 컨테이너 기초", "summary": "2023년 개편된 LFCS에 컨테이너 관리가 추가됐습니다. 이미지 pull, 컨테이너 실행·중지·삭제, 로그 확인 등 기본 라이프사이클을 다룹니다.", "example": "docker pull nginx:latest\ndocker run -d -p 8080:80 --name webserver nginx\ndocker ps # 실행 중인 컨테이너 목록\ndocker logs webserver\ndocker stop webserver && docker rm webserver", "common_mistake": "`docker stop`은 SIGTERM으로 정상 종료를 요청하고, `docker kill`은 SIGKILL로 강제 종료합니다. 데이터 일관성을 위해 가능하면 `stop`을 사용하세요.", "keywords": [ "docker", "pull", "run", "ps", "stop", "rm", "logs", "images", "-d", "-p" ], "source_id": "manual-linux-docker", "details": [ "**`docker run` 주요 옵션**: `-d`(백그라운드), `-p 호스트:컨테이너`(포트 매핑), `-v`(볼륨 마운트), `--name`(이름 지정), `--rm`(종료 시 자동 삭제).", "**이미지 vs 컨테이너**: `docker images`(로컬 이미지 목록), `docker ps -a`(중지된 것 포함 전체 컨테이너). `docker rmi`로 이미지, `docker rm`으로 컨테이너를 삭제합니다.", "**시험 패턴**: 이미지 pull → 포트 매핑해 백그라운드 실행 → 로그 확인 → 중지 후 삭제 흐름, 컨테이너 내부 접근(`docker exec -it`)이 출제됩니다." ] }, { "id": "linux-grub-boot", "certification": "LFCS / 리눅스마스터", "title": "부팅 프로세스와 GRUB", "summary": "BIOS/UEFI → GRUB → 커널 → initramfs → systemd 순으로 부팅됩니다. GRUB 설정을 수정하고 복구 모드로 진입하는 방법이 시험에 출제됩니다.", "example": "# GRUB 기본 설정 수정\nvim /etc/default/grub\n# GRUB_TIMEOUT=5, GRUB_CMDLINE_LINUX=\"quiet splash\"\nupdate-grub # Ubuntu (grub2-mkconfig -o /boot/grub2/grub.cfg on RHEL)\nsystemctl get-default # 현재 기본 target 확인\nsystemctl set-default multi-user.target", "common_mistake": "`/etc/default/grub`을 수정해도 `update-grub`(Ubuntu) 또는 `grub2-mkconfig`(RHEL)을 실행하지 않으면 실제 부트로더 설정에 반영되지 않습니다.", "keywords": [ "GRUB", "update-grub", "grub2-mkconfig", "systemd target", "initramfs", "boot" ], "source_id": "manual-linux-boot", "details": [ "**부팅 순서**: BIOS/UEFI → MBR/ESP의 GRUB → `/boot/grub/grub.cfg` 로드 → 커널+initramfs 메모리 적재 → systemd PID 1 시작.", "**systemd target**: `multi-user.target`(CLI, runlevel 3), `graphical.target`(GUI, runlevel 5), `rescue.target`(단일 사용자 복구).", "**시험 패턴**: 부팅 실패 시 GRUB에서 커널 파라미터 수정(e키), 기본 target 변경, `update-grub` 실행 타이밍이 자주 출제됩니다." ] } ]