Kentlo's picture
Sync from GitHub 37f011465a0aa2abdfdd94d8bd5f31cfe932c669
28677d8 verified
Raw
History Blame Contribute Delete
48.9 kB
[
{
"id": "linux-q29",
"lesson_id": "linux-passwd",
"question_type": "multiple_choice",
"question": "`passwd -l devuser`의 의미로 가장 맞는 것은?",
"options": [
"devuser 계정을 잠가 비밀번호 로그인을 막는다",
"devuser 비밀번호를 강제 만료시킨다",
"devuser 계정을 완전히 삭제한다",
"devuser 비밀번호를 빈 값으로 초기화한다"
],
"answer": "devuser 계정을 잠가 비밀번호 로그인을 막는다",
"explanation": "`passwd -l`은 계정을 잠가 해당 사용자가 비밀번호로 로그인할 수 없게 합니다. 잠금 해제는 `passwd -u`입니다.",
"difficulty": "easy",
"source_id": "ubuntu-user-management"
},
{
"id": "linux-q30",
"lesson_id": "linux-groups-id",
"question_type": "multiple_choice",
"question": "현재 사용자의 UID, GID, 보조 그룹 목록을 한 번에 확인하는 명령은?",
"options": [
"id",
"groups",
"whoami",
"ls -l"
],
"answer": "id",
"explanation": "`id`는 UID, GID, 속한 그룹 목록을 모두 보여줍니다. `groups`는 그룹 이름만, `whoami`는 사용자 이름만 보여줍니다.",
"difficulty": "easy",
"source_id": "ubuntu-user-management"
},
{
"id": "linux-q31",
"lesson_id": "linux-acl",
"question_type": "multiple_choice",
"question": "파일에 설정된 ACL 권한 내역을 확인하는 명령은?",
"options": [
"getfacl",
"setfacl",
"chmod",
"ls -l"
],
"answer": "getfacl",
"explanation": "`getfacl`로 현재 ACL 설정을 확인합니다. `setfacl -m`으로 ACL을 설정합니다. `ls -l`만으로는 ACL 전체가 보이지 않습니다.",
"difficulty": "easy",
"source_id": "manual-linux-basic"
},
{
"id": "linux-q32",
"lesson_id": "linux-ssh",
"question_type": "multiple_choice",
"question": "SSH 접속 실패 원인으로 관련이 없는 것은?",
"options": [
"사용자의 Python 버전",
"SSH 서비스 실행 여부",
"방화벽 22번 포트 허용 여부",
"authorized_keys 파일 권한"
],
"answer": "사용자의 Python 버전",
"explanation": "SSH 접속은 서비스 실행, 방화벽, 키 파일 권한이 모두 맞아야 합니다. Python 버전은 SSH 접속과 무관합니다.",
"difficulty": "easy",
"source_id": "ubuntu-server-docs"
},
{
"id": "linux-q33",
"lesson_id": "linux-hostname-hosts",
"question_type": "multiple_choice",
"question": "`/etc/hosts` 파일의 주된 역할은?",
"options": [
"DNS 조회 전에 참조되는 로컬 이름 해석 파일이다",
"방화벽 규칙을 저장한다",
"사용자 비밀번호를 저장한다",
"swap 공간을 정의한다"
],
"answer": "DNS 조회 전에 참조되는 로컬 이름 해석 파일이다",
"explanation": "`/etc/hosts`는 DNS 조회보다 먼저 참조되는 로컬 이름 해석 파일입니다. 테스트 환경이나 특정 호스트 이름 재정의에 자주 씁니다.",
"difficulty": "easy",
"source_id": "ubuntu-networking"
},
{
"id": "linux-q34",
"lesson_id": "linux-netplan",
"question_type": "multiple_choice",
"question": "Ubuntu에서 netplan 네트워크 설정을 시스템에 적용하는 명령은?",
"options": [
"sudo netplan apply",
"sudo ifconfig apply",
"sudo ip apply",
"sudo ufw apply"
],
"answer": "sudo netplan apply",
"explanation": "`sudo netplan apply`는 `/etc/netplan/*.yaml` 설정을 파싱해 시스템에 적용합니다. YAML 들여쓰기 오류가 있으면 실패합니다.",
"difficulty": "easy",
"source_id": "ubuntu-networking"
},
{
"id": "linux-q35",
"lesson_id": "linux-curl",
"question_type": "multiple_choice",
"question": "`curl -I https://example.com`의 `-I` 옵션 역할은?",
"options": [
"HTTP 헤더만 요청해 응답 상태를 확인한다",
"데이터를 POST로 전송한다",
"SSL 인증서 검증을 건너뛴다",
"JSON 형식으로만 출력한다"
],
"answer": "HTTP 헤더만 요청해 응답 상태를 확인한다",
"explanation": "`-I`는 HEAD 요청을 보내 응답 헤더만 받습니다. 서비스가 올바른 상태 코드를 반환하는지 빠르게 확인할 때 유용합니다.",
"difficulty": "easy",
"source_id": "ubuntu-networking"
},
{
"id": "linux-q36",
"lesson_id": "linux-ping",
"question_type": "multiple_choice",
"question": "ping이 성공하더라도 보장되지 않는 것은?",
"options": [
"HTTP 서비스가 정상 동작하는 것",
"ICMP 통신이 가능하다는 것",
"네트워크 경로가 있다는 것",
"IP 통신이 가능하다는 것"
],
"answer": "HTTP 서비스가 정상 동작하는 것",
"explanation": "ping은 ICMP 응답만 확인합니다. 방화벽이 ICMP를 허용해도 HTTP 서비스가 내려가 있을 수 있고, 반대로 HTTP가 되어도 ICMP가 막힐 수 있습니다.",
"difficulty": "easy",
"source_id": "ubuntu-networking"
},
{
"id": "linux-q37",
"lesson_id": "linux-top",
"question_type": "multiple_choice",
"question": "`top` 명령어가 가장 적합한 상황은?",
"options": [
"CPU/메모리 사용량이 높은 프로세스를 실시간으로 확인할 때",
"파일 이름 패턴으로 검색할 때",
"패키지를 설치할 때",
"파일시스템 사용량을 볼 때"
],
"answer": "CPU/메모리 사용량이 높은 프로세스를 실시간으로 확인할 때",
"explanation": "`top`은 CPU, 메모리 사용량과 프로세스 목록을 실시간으로 갱신해 보여줍니다. 서버 부하 원인 파악에 자주 씁니다.",
"difficulty": "easy",
"source_id": "ubuntu-server-docs"
},
{
"id": "linux-q38",
"lesson_id": "linux-nice",
"question_type": "multiple_choice",
"question": "`nice -n 10 command`에서 nice 값이 높을수록 어떻게 되는가?",
"options": [
"다른 프로세스에 CPU를 양보하는 낮은 우선순위를 가진다",
"CPU 코어를 더 많이 사용한다",
"지정된 분 후에 실행된다",
"메모리를 더 많이 차지한다"
],
"answer": "다른 프로세스에 CPU를 양보하는 낮은 우선순위를 가진다",
"explanation": "nice 값이 높을수록 다른 프로세스에게 CPU를 더 양보합니다. 범위는 -20(가장 높은 우선순위)에서 19(가장 낮은 우선순위)입니다.",
"difficulty": "easy",
"source_id": "ubuntu-server-docs"
},
{
"id": "linux-q39",
"lesson_id": "linux-swap",
"question_type": "multiple_choice",
"question": "swap 사용량이 매우 높을 때 시스템 상태를 가장 잘 나타내는 것은?",
"options": [
"물리 메모리가 부족해 디스크를 보조 메모리로 사용하고 있다",
"CPU가 과부하 상태다",
"디스크 공간이 꽉 찼다",
"네트워크 연결이 끊겼다"
],
"answer": "물리 메모리가 부족해 디스크를 보조 메모리로 사용하고 있다",
"explanation": "swap 과사용은 물리 RAM 부족의 신호입니다. 디스크가 RAM보다 훨씬 느려서 swap 과다 사용은 심각한 성능 저하로 이어집니다.",
"difficulty": "easy",
"source_id": "ubuntu-storage"
},
{
"id": "linux-q40",
"lesson_id": "linux-lvm",
"question_type": "multiple_choice",
"question": "LVM에서 물리 볼륨(PV)들이 합쳐지는 중간 계층은?",
"options": [
"Volume Group (VG)",
"Logical Volume (LV)",
"/etc/fstab",
"partition table"
],
"answer": "Volume Group (VG)",
"explanation": "LVM 계층은 PV(물리 볼륨) → VG(볼륨 그룹) → LV(논리 볼륨) 순입니다. VG는 PV들을 묶고, LV는 VG에서 용량을 나눠 씁니다.",
"difficulty": "easy",
"source_id": "ubuntu-storage"
},
{
"id": "linux-q41",
"lesson_id": "linux-logs-var",
"question_type": "multiple_choice",
"question": "`/var/log` 디렉터리에서 주로 볼 수 있는 것은?",
"options": [
"서비스, 인증, 시스템의 로그 파일",
"사용자 홈 디렉터리",
"실행 가능한 패키지 바이너리",
"네트워크 설정 파일"
],
"answer": "서비스, 인증, 시스템의 로그 파일",
"explanation": "`/var/log`는 nginx, syslog, auth.log, kern.log 같은 다양한 로그 파일이 모이는 표준 위치입니다.",
"difficulty": "easy",
"source_id": "ubuntu-server-docs"
},
{
"id": "linux-q42",
"lesson_id": "linux-dmesg",
"question_type": "multiple_choice",
"question": "`dmesg | tail`로 확인하기에 가장 적합한 정보는?",
"options": [
"부팅과 하드웨어 관련 커널 메시지",
"HTTP 서버 접속 로그",
"사용자 비밀번호 정책",
"cron 실행 이력"
],
"answer": "부팅과 하드웨어 관련 커널 메시지",
"explanation": "`dmesg`는 커널 링 버퍼를 출력합니다. 부팅 과정, 하드웨어 감지, 드라이버 오류 같은 시스템 수준 메시지를 볼 때 유용합니다.",
"difficulty": "easy",
"source_id": "ubuntu-server-docs"
},
{
"id": "linux-q43",
"lesson_id": "linux-env-path",
"question_type": "multiple_choice",
"question": "cron 작업이 터미널에서는 되지만 cron에서만 실패할 때 먼저 의심할 원인은?",
"options": [
"PATH 환경 변수가 cron과 터미널에서 다르다",
"디스크 공간이 부족하다",
"SSH 키 파일이 없다",
"systemctl이 중지됐다"
],
"answer": "PATH 환경 변수가 cron과 터미널에서 다르다",
"explanation": "cron은 로그인 shell보다 훨씬 제한된 PATH를 씁니다. 스크립트에서 절대 경로를 사용하거나 crontab에서 PATH를 직접 설정하면 해결됩니다.",
"difficulty": "easy",
"source_id": "linux-bash-cd"
},
{
"id": "linux-q44",
"lesson_id": "linux-wildcard",
"question_type": "multiple_choice",
"question": "`ls *.log` 명령에서 `*.log` 패턴을 파일 목록으로 확장하는 주체는?",
"options": [
"Shell (bash/zsh)",
"ls 명령어 자체",
"kernel",
"파일시스템 드라이버"
],
"answer": "Shell (bash/zsh)",
"explanation": "와일드카드 글로빙(glob)은 shell이 명령 실행 전에 파일명 목록으로 확장합니다. ls가 아니라 shell이 처리합니다.",
"difficulty": "easy",
"source_id": "linux-bash-cd"
},
{
"id": "linux-q45",
"lesson_id": "linux-service-port",
"question_type": "multiple_choice",
"question": "`systemctl is-active nginx`가 active인데도 80포트에 연결이 안 될 때 확인 대상이 아닌 것은?",
"options": [
"사용자의 SSH 공개 키",
"방화벽 80포트 허용 여부",
"nginx가 80포트에서 listen 중인지",
"nginx 설정 파일 문법 오류"
],
"answer": "사용자의 SSH 공개 키",
"explanation": "서비스가 active여도 방화벽, 포트 listen 설정, 설정 파일 오류로 연결이 안 될 수 있습니다. SSH 공개 키는 80포트 연결과 무관합니다.",
"difficulty": "easy",
"source_id": "linux-man7-ip"
},
{
"id": "linux-q46",
"lesson_id": "linux-repo",
"question_type": "multiple_choice",
"question": "`apt update` 실행 시 특정 repository에서 오류가 날 때 먼저 의심할 원인은?",
"options": [
"repository URL이나 GPG 키 설정 문제",
"CPU 온도가 높다",
"swap 공간이 부족하다",
"실행 중인 프로세스 수가 많다"
],
"answer": "repository URL이나 GPG 키 설정 문제",
"explanation": "`apt update` 실패는 repository URL 오류, 네트워크 차단, GPG 서명 키 문제가 주된 원인입니다.",
"difficulty": "easy",
"source_id": "ubuntu-package-management"
},
{
"id": "linux-q47",
"lesson_id": "linux-head-tail",
"question_type": "multiple_choice",
"question": "증가하는 로그 파일을 실시간으로 계속 추적하는 명령으로 가장 적합한 것은?",
"options": [
"tail -f /var/log/syslog",
"head -f /var/log/syslog",
"cat -f /var/log/syslog",
"watch /var/log/syslog"
],
"answer": "tail -f /var/log/syslog",
"explanation": "`tail -f`는 파일 끝에 추가되는 내용을 실시간으로 계속 보여줍니다. 로그 모니터링에 가장 많이 씁니다.",
"difficulty": "easy",
"source_id": "manual-linux-basic"
},
{
"id": "linux-q48",
"lesson_id": "linux-sed",
"question_type": "multiple_choice",
"question": "`sed 's/old/new/g' file.txt`의 역할은?",
"options": [
"file.txt의 old를 모두 new로 교체해 표준 출력으로 보낸다",
"file.txt를 정렬해 출력한다",
"file.txt에서 old 줄을 삭제한다",
"file.txt를 새 파일로 복사한다"
],
"answer": "file.txt의 old를 모두 new로 교체해 표준 출력으로 보낸다",
"explanation": "`sed 's/패턴/교체/g'`는 파일에서 패턴을 찾아 교체한 결과를 출력합니다. `-i` 없이는 원본 파일을 바꾸지 않습니다.",
"difficulty": "easy",
"source_id": "manual-linux-basic"
},
{
"id": "linux-q49",
"lesson_id": "linux-text-pipeline",
"question_type": "multiple_choice",
"question": "파일 전체에서 중복 줄을 제거하려 할 때 `uniq` 전에 일반적으로 필요한 명령은?",
"options": [
"sort",
"cut",
"wc",
"grep"
],
"answer": "sort",
"explanation": "`uniq`은 연속된 중복 줄만 제거합니다. 파일 전체에서 중복을 제거하려면 먼저 `sort`로 정렬한 뒤 `uniq`을 적용해야 합니다.",
"difficulty": "easy",
"source_id": "manual-linux-basic"
},
{
"id": "linux-q50",
"lesson_id": "linux-awk",
"question_type": "multiple_choice",
"question": "`awk '{print $2}' access.log`가 하는 일은?",
"options": [
"각 줄의 두 번째 필드를 출력한다",
"두 번째 줄만 출력한다",
"두 번째 파일을 연다",
"필드 구분자를 2번으로 바꾼다"
],
"answer": "각 줄의 두 번째 필드를 출력한다",
"explanation": "awk에서 `$1`, `$2`, `$N`은 공백으로 구분된 각 필드를 의미합니다. `$2`는 각 줄의 두 번째 필드를 출력합니다.",
"difficulty": "easy",
"source_id": "manual-linux-basic"
},
{
"id": "linux-q51",
"lesson_id": "linux-ln-symlink",
"question_type": "multiple_choice",
"question": "`ln -s /etc/nginx/nginx.conf ~/nginx.conf`로 만들어지는 것은?",
"options": [
"nginx.conf를 가리키는 심볼릭 링크",
"nginx.conf의 하드 복사본",
"nginx.conf라는 디렉터리",
"nginx.conf의 이름만 변경한 것"
],
"answer": "nginx.conf를 가리키는 심볼릭 링크",
"explanation": "`ln -s`는 원본 파일을 가리키는 심볼릭 링크를 만듭니다. `ls -l`에서 `->` 표시로 확인할 수 있습니다.",
"difficulty": "easy",
"source_id": "manual-linux-basic"
},
{
"id": "linux-q52",
"lesson_id": "linux-bg-fg-jobs",
"question_type": "multiple_choice",
"question": "터미널이 닫혀도 작업이 계속 실행되도록 백그라운드로 실행하는 명령은?",
"options": [
"nohup long-command &",
"long-command &",
"bg long-command",
"jobs -r long-command"
],
"answer": "nohup long-command &",
"explanation": "`nohup`은 터미널 종료 시 보내는 HUP 시그널을 무시해 작업이 계속 실행되도록 합니다. `&`만으로는 터미널이 닫히면 작업이 종료됩니다.",
"difficulty": "easy",
"source_id": "ubuntu-server-docs"
},
{
"id": "linux-q53",
"lesson_id": "linux-shell-script-basics",
"question_type": "multiple_choice",
"question": "쉘 스크립트에서 스크립트에 전달된 첫 번째 인수를 참조하는 변수는?",
"options": [
"$1",
"$0",
"$@",
"$$"
],
"answer": "$1",
"explanation": "`$0`은 스크립트 이름, `$1`은 첫 번째 인수, `$@`는 모든 인수 목록, `$$`는 현재 프로세스 PID입니다.",
"difficulty": "easy",
"source_id": "linux-bash-cd"
},
{
"id": "linux-q54",
"lesson_id": "linux-ls",
"question_type": "multiple_choice",
"question": "숨김 파일을 포함해 상세 정보를 보는 ls 옵션 조합은?",
"options": [
"ls -rh",
"ls -al",
"ls -d",
"ls -t"
],
"answer": "ls -al",
"explanation": "`-a`는 점으로 시작하는 숨김 파일 포함, `-l`은 권한·소유자·크기·날짜를 포함한 긴 형식 출력입니다.",
"source_id": "manual-linux-basic",
"difficulty": "easy"
},
{
"id": "linux-q55",
"lesson_id": "linux-cd",
"question_type": "multiple_choice",
"question": "`cd -` 명령어의 결과는?",
"options": [
"루트 디렉터리로 이동",
"이전 디렉터리로 이동",
"홈 디렉터리로 이동",
"상위 디렉터리로 이동"
],
"answer": "이전 디렉터리로 이동",
"explanation": "`cd -`는 OLDPWD에 저장된 직전 디렉터리로 돌아갑니다. 두 디렉터리 사이를 빠르게 오갈 때 유용합니다.",
"source_id": "manual-linux-basic",
"difficulty": "easy"
},
{
"id": "linux-q56",
"lesson_id": "linux-cat",
"question_type": "multiple_choice",
"question": "파일 내용을 줄 번호와 함께 출력하는 cat 옵션은?",
"options": [
"-n",
"-v",
"-e",
"-s"
],
"answer": "-n",
"explanation": "`cat -n`은 모든 줄에 번호를 붙여 출력합니다. 스크립트 디버깅이나 특정 줄 위치 확인에 유용합니다.",
"source_id": "manual-linux-basic",
"difficulty": "easy"
},
{
"id": "linux-q57",
"lesson_id": "linux-process-ps-kill",
"question_type": "multiple_choice",
"question": "실행 중인 모든 프로세스를 사용자 이름과 함께 전체 목록으로 보는 명령은?",
"options": [
"ps aux",
"ps -e",
"top -n1",
"kill -l"
],
"answer": "ps aux",
"explanation": "`ps aux`는 모든 사용자의 전체 프로세스를 CPU/메모리 사용량과 함께 보여줍니다. 시험에서 가장 자주 쓰이는 ps 옵션 조합입니다.",
"source_id": "manual-linux-basic",
"difficulty": "easy"
},
{
"id": "linux-q58",
"lesson_id": "linux-cp-mv-rm",
"question_type": "multiple_choice",
"question": "운영 중인 서버의 `/etc/nginx/nginx.conf`를 수정하기 전 권한과 타임스탬프를 보존해 같은 디렉터리에 백업하려 합니다. 올바른 명령은?",
"options": [
"cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak",
"cp -a /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak",
"cp -r /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak",
"mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak"
],
"answer": "cp -a /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak",
"explanation": "`cp -a`는 권한·소유자·타임스탬프를 모두 보존합니다(`-dR --preserve=all`). `-r`은 디렉터리 재귀 복사용이며 속성을 보존하지 않습니다. `mv`는 원본이 사라집니다.",
"source_id": "manual-linux-basic",
"difficulty": "medium"
},
{
"id": "linux-q59",
"lesson_id": "linux-cp-mv-rm",
"question_type": "multiple_choice",
"question": "`rm -rf /var/log/old/`를 실행했을 때 발생하는 일은?",
"options": [
"/var/log/old/ 디렉터리와 하위 모든 파일이 즉시 삭제된다",
"각 파일마다 삭제 확인을 요청한다",
"/var/log/old/가 휴지통으로 이동한다",
"심볼릭 링크만 삭제하고 실제 파일은 남긴다"
],
"answer": "/var/log/old/ 디렉터리와 하위 모든 파일이 즉시 삭제된다",
"explanation": "`-r`은 재귀 삭제, `-f`는 확인 없이 강제 삭제입니다. 리눅스에는 휴지통이 없어 복구가 매우 어렵습니다. 중요 경로에서는 먼저 `ls`로 대상을 확인하세요.",
"source_id": "manual-linux-basic",
"difficulty": "easy"
},
{
"id": "linux-q60",
"lesson_id": "linux-fdisk-parted",
"question_type": "multiple_choice",
"question": "3TB 용량의 새 디스크 `/dev/sdc`에 파티션을 만들 때 fdisk 대신 parted를 사용해야 하는 이유는?",
"options": [
"fdisk는 MBR 방식으로 2TB 초과 디스크를 지원하지 않기 때문",
"parted가 더 빠르기 때문",
"fdisk는 ext4 파일시스템만 지원하기 때문",
"parted만 RAID 설정을 지원하기 때문"
],
"answer": "fdisk는 MBR 방식으로 2TB 초과 디스크를 지원하지 않기 때문",
"explanation": "MBR 파티션 테이블은 최대 2TB를 지원합니다. 3TB 디스크는 GPT가 필요하며 `parted`나 `gdisk`로 GPT 테이블을 생성해야 합니다.",
"source_id": "manual-linux-storage",
"difficulty": "medium"
},
{
"id": "linux-q61",
"lesson_id": "linux-fdisk-parted",
"question_type": "multiple_choice",
"question": "`fdisk /dev/sdb` 실행 후 새 주 파티션을 만들고 저장하는 키 순서는?",
"options": [
"n → p → w",
"p → n → w",
"n → e → q",
"w → n → p"
],
"answer": "n → p → w",
"explanation": "`n`(new partition) → `p`(primary) → 번호·섹터 입력 → `w`(write & quit). `q`는 저장 없이 종료, `p`는 현재 테이블 출력(Print)이기도 합니다.",
"source_id": "manual-linux-storage",
"difficulty": "medium"
},
{
"id": "linux-q62",
"lesson_id": "linux-mkfs-fsck",
"question_type": "multiple_choice",
"question": "다음 스토리지 설정 순서 중 올바른 것은?",
"options": [
"파티션 생성 → 파일시스템 생성(mkfs) → 마운트 포인트 생성 → mount",
"마운트 → mkfs → 파티션 생성 → fstab 등록",
"mkfs → 파티션 생성 → mount → fstab 등록",
"파티션 생성 → mount → mkfs → fstab 등록"
],
"answer": "파티션 생성 → 파일시스템 생성(mkfs) → 마운트 포인트 생성 → mount",
"explanation": "fdisk로 파티션 생성 → mkfs로 포맷 → mkdir로 마운트 포인트 생성 → mount로 연결이 올바른 순서입니다. 영구 마운트는 마지막에 fstab에 등록합니다.",
"source_id": "manual-linux-storage",
"difficulty": "medium"
},
{
"id": "linux-q63",
"lesson_id": "linux-mkfs-fsck",
"question_type": "multiple_choice",
"question": "마운트된 파일시스템에서 `fsck`를 실행하면 어떻게 되는가?",
"options": [
"데이터 손상이 발생할 수 있다",
"자동으로 언마운트 후 검사한다",
"읽기 전용으로 전환 후 검사한다",
"정상적으로 오류를 수정한다"
],
"answer": "데이터 손상이 발생할 수 있다",
"explanation": "`fsck`는 언마운트된 파일시스템에서만 실행해야 합니다. 마운트 상태에서 실행하면 OS와 fsck가 동시에 파일시스템에 쓰기를 시도해 데이터가 손상될 수 있습니다.",
"source_id": "manual-linux-storage",
"difficulty": "medium"
},
{
"id": "linux-q64",
"lesson_id": "linux-groupadd",
"question_type": "multiple_choice",
"question": "`usermod -G developers alice`를 `-a` 없이 실행했을 때 발생하는 문제는?",
"options": [
"alice의 기존 보조 그룹이 모두 제거되고 developers만 남는다",
"alice가 developers 그룹에서 제거된다",
"명령이 실패하고 오류가 출력된다",
"alice의 기본 그룹이 developers로 변경된다"
],
"answer": "alice의 기존 보조 그룹이 모두 제거되고 developers만 남는다",
"explanation": "`-G`는 보조 그룹을 지정한 목록으로 교체합니다. 기존 그룹을 유지하면서 추가하려면 반드시 `-aG`(append)를 사용해야 합니다.",
"source_id": "ubuntu-user-management",
"difficulty": "medium"
},
{
"id": "linux-q65",
"lesson_id": "linux-chage",
"question_type": "multiple_choice",
"question": "신규 입사자 bob이 첫 로그인 시 반드시 비밀번호를 변경하게 하려 합니다. 적절한 명령은?",
"options": [
"chage -d 0 bob",
"chage -M 0 bob",
"passwd -l bob",
"chage -E 0 bob"
],
"answer": "chage -d 0 bob",
"explanation": "`chage -d 0`은 마지막 비밀번호 변경일을 에포크(1970-01-01)로 설정해 다음 로그인 시 즉시 변경을 강제합니다. `-E 0`은 계정 자체를 만료시켜 로그인을 차단합니다.",
"source_id": "ubuntu-user-management",
"difficulty": "medium"
},
{
"id": "linux-q66",
"lesson_id": "linux-chage",
"question_type": "multiple_choice",
"question": "보안 정책상 모든 사용자가 90일마다 비밀번호를 바꿔야 합니다. alice에게 적용하는 명령은?",
"options": [
"chage -M 90 alice",
"chage -d 90 alice",
"passwd -M 90 alice",
"chage -W 90 alice"
],
"answer": "chage -M 90 alice",
"explanation": "`-M`은 비밀번호 최대 사용 기간(Maximum days)을 설정합니다. `-W`는 만료 전 경고일, `-d`는 마지막 변경일, `-E`는 계정 만료일입니다.",
"source_id": "ubuntu-user-management",
"difficulty": "medium"
},
{
"id": "linux-q67",
"lesson_id": "linux-systemd-unit",
"question_type": "multiple_choice",
"question": "`/etc/systemd/system/myapp.service` 파일을 수정한 뒤 변경 사항을 적용하는 올바른 순서는?",
"options": [
"systemctl daemon-reload → systemctl restart myapp",
"systemctl restart myapp → systemctl daemon-reload",
"reboot → systemctl restart myapp",
"systemctl reload myapp만 실행"
],
"answer": "systemctl daemon-reload → systemctl restart myapp",
"explanation": "유닛 파일 수정 후 systemd가 변경을 인식하려면 `daemon-reload`가 먼저 필요합니다. 그 다음 `restart`로 서비스를 재시작해야 새 설정이 적용됩니다.",
"source_id": "manual-linux-systemd",
"difficulty": "medium"
},
{
"id": "linux-q68",
"lesson_id": "linux-systemd-unit",
"question_type": "multiple_choice",
"question": "서비스 유닛 파일에서 `WantedBy=multi-user.target`의 역할은?",
"options": [
"systemctl enable 시 multi-user.target 실행 단계에서 서비스가 자동 시작되도록 등록한다",
"서비스가 multi-user 이후에만 중지됨을 의미한다",
"서비스를 그래픽 환경에서만 실행하게 한다",
"다른 서비스보다 먼저 시작하게 한다"
],
"answer": "systemctl enable 시 multi-user.target 실행 단계에서 서비스가 자동 시작되도록 등록한다",
"explanation": "`WantedBy`는 `systemctl enable` 실행 시 어느 target의 `.wants/` 디렉터리에 심볼릭 링크를 생성할지 결정합니다. `multi-user.target`은 네트워크 서비스가 준비된 CLI 환경(runlevel 3)입니다.",
"source_id": "manual-linux-systemd",
"difficulty": "easy"
},
{
"id": "linux-q69",
"lesson_id": "linux-at",
"question_type": "multiple_choice",
"question": "매일 반복이 아닌 내일 새벽 3시에 한 번만 백업 스크립트를 실행하려 합니다. 적절한 도구는?",
"options": [
"at",
"cron",
"systemd timer",
"nohup"
],
"answer": "at",
"explanation": "`at`은 일회성 예약 실행을 위한 도구입니다. cron은 반복 스케줄에 적합하고, nohup은 터미널 종료 후에도 프로세스를 유지하기 위한 도구로 스케줄링 기능은 없습니다.",
"source_id": "manual-linux-basic",
"difficulty": "medium"
},
{
"id": "linux-q70",
"lesson_id": "linux-docker-basics",
"question_type": "multiple_choice",
"question": "nginx 컨테이너를 백그라운드로 실행하고 호스트 포트 8080을 컨테이너 포트 80에 연결하는 명령은?",
"options": [
"docker run -d -p 8080:80 nginx",
"docker run -p 80:8080 nginx",
"docker start -p 8080:80 nginx",
"docker run --port 8080=80 -b nginx"
],
"answer": "docker run -d -p 8080:80 nginx",
"explanation": "`-d`는 detach(백그라운드), `-p 호스트포트:컨테이너포트`로 포트를 매핑합니다. `8080:80`은 호스트의 8080을 컨테이너의 80으로 포워딩합니다.",
"source_id": "manual-linux-docker",
"difficulty": "medium"
},
{
"id": "linux-q71",
"lesson_id": "linux-docker-basics",
"question_type": "multiple_choice",
"question": "실행 중이거나 중지된 모든 컨테이너 목록을 보는 명령은?",
"options": [
"docker ps -a",
"docker ps",
"docker images",
"docker container ls"
],
"answer": "docker ps -a",
"explanation": "`docker ps`는 실행 중인 컨테이너만 표시합니다. `-a`(all) 플래그를 추가하면 중지된 컨테이너까지 모두 표시합니다.",
"source_id": "manual-linux-docker",
"difficulty": "easy"
},
{
"id": "linux-q72",
"lesson_id": "linux-grub-boot",
"question_type": "multiple_choice",
"question": "`/etc/default/grub`에서 `GRUB_TIMEOUT=10`으로 변경 후 적용하는 명령은? (Ubuntu 기준)",
"options": [
"update-grub",
"grub-install",
"systemctl restart grub",
"reboot"
],
"answer": "update-grub",
"explanation": "`/etc/default/grub`은 템플릿 역할을 하며, `update-grub`(Ubuntu) 또는 `grub2-mkconfig -o /boot/grub2/grub.cfg`(RHEL)를 실행해야 실제 GRUB 설정 파일에 반영됩니다.",
"source_id": "manual-linux-boot",
"difficulty": "medium"
},
{
"id": "linux-q73",
"lesson_id": "linux-grub-boot",
"question_type": "multiple_choice",
"question": "시스템이 그래픽 환경 없이 CLI 다중 사용자 모드로 기본 부팅되게 하는 명령은?",
"options": [
"systemctl set-default multi-user.target",
"systemctl set-default graphical.target",
"update-grub --target=cli",
"systemctl disable gdm"
],
"answer": "systemctl set-default multi-user.target",
"explanation": "`multi-user.target`은 GUI 없이 네트워크와 다중 사용자 환경을 제공하는 target(runlevel 3 상당)입니다. `graphical.target`(runlevel 5)에서 변경하면 다음 재시작부터 CLI로 부팅됩니다.",
"source_id": "manual-linux-boot",
"difficulty": "medium"
},
{
"id": "linux-q74",
"lesson_id": "linux-find",
"question_type": "multiple_choice",
"question": "7일 이상 수정되지 않은 `/var/log`의 `.log` 파일을 찾아 일괄 삭제하려 합니다. 올바른 명령은?",
"options": [
"find /var/log -name '*.log' -mtime +7 -delete",
"find /var/log -name '*.log' -mtime 7 -rm",
"grep -r '.log' /var/log | xargs rm",
"ls -lt /var/log/*.log | tail -n +8 | xargs rm"
],
"answer": "find /var/log -name '*.log' -mtime +7 -delete",
"explanation": "`-mtime +7`은 마지막 수정 후 7일 초과된 파일, `-delete`는 find 내장 삭제 액션입니다. `-mtime 7`(정확히 7일)과 `-mtime +7`(7일 초과)의 차이에 주의하세요.",
"source_id": "manual-linux-basic",
"difficulty": "hard"
},
{
"id": "linux-q75",
"lesson_id": "linux-pipe-redirect",
"question_type": "multiple_choice",
"question": "`ls /notexist 2>/dev/null && echo OK`의 실행 결과는?",
"options": [
"아무것도 출력되지 않는다",
"OK가 출력된다",
"오류 메시지가 출력된다",
"OK와 오류 메시지가 함께 출력된다"
],
"answer": "아무것도 출력되지 않는다",
"explanation": "`2>/dev/null`로 stderr를 버리고, `ls /notexist`가 실패(exit code != 0)하므로 `&&` 뒤의 `echo OK`는 실행되지 않습니다. 결과적으로 아무것도 출력되지 않습니다.",
"source_id": "manual-linux-basic",
"difficulty": "medium"
},
{
"id": "linux-q76",
"lesson_id": "linux-systemctl",
"question_type": "multiple_choice",
"question": "서버 재시작 후에도 nginx가 자동으로 시작되게 하려 합니다. 현재 실행 중이며 enable만 빠진 상태입니다. 필요한 명령은?",
"options": [
"systemctl enable nginx",
"systemctl start nginx",
"systemctl enable --now nginx",
"systemctl restart nginx"
],
"answer": "systemctl enable nginx",
"explanation": "이미 실행 중이므로 `start`는 불필요합니다. `enable`만 하면 부팅 시 자동 시작 심볼릭 링크가 생성됩니다. `enable --now`는 enable + start를 동시에 처리합니다.",
"source_id": "manual-linux-basic",
"difficulty": "easy"
},
{
"id": "linux-q77",
"lesson_id": "linux-acl",
"question_type": "multiple_choice",
"question": "`/project` 디렉터리를 `devteam` 그룹 멤버 모두가 읽고 쓸 수 있게 하고, 새로 생성된 파일도 같은 그룹 소유가 되게 하는 설정은?",
"options": [
"chmod 2775 /project && chgrp devteam /project",
"chmod 777 /project",
"setfacl -m g:devteam:rw /project",
"chown devteam /project && chmod 755 /project"
],
"answer": "chmod 2775 /project && chgrp devteam /project",
"explanation": "`2775`의 앞 자리 2는 SGID(Set Group ID) 비트입니다. SGID가 설정된 디렉터리에서 생성된 파일은 자동으로 디렉터리의 그룹 소유가 됩니다. `775`는 소유자·그룹 읽기/쓰기/실행, 기타 읽기/실행을 부여합니다.",
"source_id": "manual-linux-basic",
"difficulty": "hard"
},
{
"id": "linux-q78",
"lesson_id": "linux-fstab",
"question_type": "multiple_choice",
"question": "`/etc/fstab`에 UUID 기반으로 항목을 추가할 때 UUID를 확인하는 명령은?",
"options": [
"blkid",
"lsblk -f",
"fdisk -l",
"mount -l"
],
"answer": "blkid",
"explanation": "`blkid`는 블록 디바이스의 UUID, TYPE(파일시스템), LABEL을 출력합니다. `lsblk -f`도 유사한 정보를 트리 형태로 보여줍니다. fstab에는 장치명(/dev/sdb1) 대신 UUID를 쓰는 것이 재부팅 시 장치 순서 변경에 안전합니다.",
"source_id": "manual-linux-basic",
"difficulty": "medium"
},
{
"id": "linux-q79",
"lesson_id": "linux-lvm",
"question_type": "multiple_choice",
"question": "LVM에서 논리 볼륨의 크기를 20GB로 늘리고 ext4 파일시스템도 함께 확장하는 명령 순서는?",
"options": [
"lvextend -L 20G /dev/vg0/lv0 → resize2fs /dev/vg0/lv0",
"resize2fs /dev/vg0/lv0 → lvextend -L 20G /dev/vg0/lv0",
"vgextend vg0 → resize2fs /dev/vg0/lv0",
"lvextend -r -L 20G /dev/vg0/lv0 만으로 완료"
],
"answer": "lvextend -r -L 20G /dev/vg0/lv0 만으로 완료",
"explanation": "`lvextend -r`(또는 `--resizefs`)은 LV 확장과 파일시스템 확장을 한 번에 처리합니다. 별도로 `resize2fs`를 실행해도 되지만 `-r` 옵션 하나로 통합 가능합니다.",
"source_id": "manual-linux-basic",
"difficulty": "hard"
},
{
"id": "linux-q80",
"lesson_id": "linux-ssh",
"question_type": "multiple_choice",
"question": "SSH 서버에서 root 계정의 비밀번호 로그인을 차단하고 키 기반 인증만 허용하려면 `sshd_config`에서 설정할 항목은?",
"options": [
"PermitRootLogin prohibit-password",
"PermitRootLogin no",
"PasswordAuthentication no",
"PermitRootLogin prohibit-password 와 PasswordAuthentication no 모두"
],
"answer": "PermitRootLogin prohibit-password 와 PasswordAuthentication no 모두",
"explanation": "`PermitRootLogin prohibit-password`는 root의 비밀번호 인증만 차단(키 인증은 허용). `PasswordAuthentication no`는 모든 사용자의 비밀번호 인증을 차단합니다. 둘을 함께 적용해야 root 비밀번호 로그인이 완전히 차단됩니다.",
"source_id": "manual-linux-basic",
"difficulty": "medium"
},
{
"id": "linux-cmd-1",
"lesson_id": "linux-cp-mv-rm",
"question_type": "command",
"question": "`/etc/hosts` 파일을 권한·소유자·타임스탬프를 보존하며 `/tmp/hosts.bak`으로 복사하는 명령을 입력하세요.",
"options": [],
"answer": "cp -a /etc/hosts /tmp/hosts.bak",
"explanation": "`cp -a`는 `-dR --preserve=all`의 단축으로 속성을 완전히 보존합니다. 단순 `cp`는 타임스탬프와 권한을 보존하지 않습니다.",
"source_id": "manual-linux-basic",
"difficulty": "medium"
},
{
"id": "linux-cmd-2",
"lesson_id": "linux-grep",
"question_type": "command",
"question": "`/etc/ssh/sshd_config` 파일에서 주석(#으로 시작하는 줄)을 제외하고 내용을 출력하는 명령을 입력하세요.",
"options": [],
"answer": "grep -v '^#' /etc/ssh/sshd_config",
"explanation": "`-v`는 패턴과 일치하지 않는 줄을 출력(반전), `^#`은 줄의 시작이 #인 줄을 의미합니다.",
"source_id": "manual-linux-basic",
"difficulty": "medium"
},
{
"id": "linux-cmd-3",
"lesson_id": "linux-find",
"question_type": "command",
"question": "시스템 전체에서 SUID 비트가 설정된 파일을 찾는 명령을 입력하세요.",
"options": [],
"answer": "find / -perm -4000 -type f",
"explanation": "`-perm -4000`은 SUID 비트(4000)가 설정된 파일을 찾습니다. `-`를 앞에 붙이면 해당 비트가 포함된 파일 모두를 찾습니다.",
"source_id": "manual-linux-basic",
"difficulty": "hard"
},
{
"id": "linux-cmd-4",
"lesson_id": "linux-tar",
"question_type": "command",
"question": "`/var/log` 디렉터리를 gzip 압축해 `/tmp/log_backup.tar.gz`로 만드는 명령을 입력하세요.",
"options": [],
"answer": "tar -czf /tmp/log_backup.tar.gz /var/log",
"explanation": "`-c`(create), `-z`(gzip 압축), `-f`(파일 이름 지정). 생성할 아카이브 이름 → 원본 경로 순서로 인수를 씁니다.",
"source_id": "manual-linux-basic",
"difficulty": "medium"
},
{
"id": "linux-cmd-5",
"lesson_id": "linux-tar",
"question_type": "command",
"question": "`/tmp/log_backup.tar.gz`의 내용을 현재 디렉터리에 압축 해제하는 명령을 입력하세요.",
"options": [],
"answer": "tar -xzf /tmp/log_backup.tar.gz",
"explanation": "`-x`(extract), `-z`(gzip), `-f`(파일 이름). `-C /경로`를 추가하면 특정 디렉터리에 압축 해제할 수 있습니다.",
"source_id": "manual-linux-basic",
"difficulty": "easy"
},
{
"id": "linux-cmd-6",
"lesson_id": "linux-chmod",
"question_type": "command",
"question": "`/srv/app` 디렉터리와 그 하위 모든 파일에 소유자는 rwx, 그룹은 rx, 기타는 아무 권한도 없게 재귀적으로 설정하는 명령을 입력하세요.",
"options": [],
"answer": "chmod -R 750 /srv/app",
"explanation": "`750` = 소유자(7=rwx), 그룹(5=r-x), 기타(0=---). `-R`은 재귀 적용입니다.",
"source_id": "manual-linux-basic",
"difficulty": "medium"
},
{
"id": "linux-cmd-7",
"lesson_id": "linux-acl",
"question_type": "command",
"question": "`/project` 디렉터리에 `devteam` 그룹이 읽기·쓰기·실행 권한을 갖도록 ACL을 설정하는 명령을 입력하세요.",
"options": [],
"answer": "setfacl -m g:devteam:rwx /project",
"explanation": "`setfacl -m`(modify) `g:그룹명:권한` 형식으로 그룹 ACL을 설정합니다. 기존 권한은 유지됩니다.",
"source_id": "manual-linux-basic",
"difficulty": "hard"
},
{
"id": "linux-cmd-8",
"lesson_id": "linux-useradd",
"question_type": "command",
"question": "홈 디렉터리를 자동 생성하면서 `alice`라는 사용자를 만들고 기본 셸을 `/bin/bash`로 설정하는 명령을 입력하세요.",
"options": [],
"answer": "useradd -m -s /bin/bash alice",
"explanation": "`-m`은 홈 디렉터리 생성, `-s`는 기본 셸 지정입니다. 이 옵션 없이 useradd만 실행하면 홈 디렉터리가 생성되지 않습니다.",
"source_id": "ubuntu-user-management",
"difficulty": "medium"
},
{
"id": "linux-cmd-9",
"lesson_id": "linux-chage",
"question_type": "command",
"question": "`bob` 사용자의 비밀번호 만료 정책(최대 사용일, 경고일 등)을 확인하는 명령을 입력하세요.",
"options": [],
"answer": "chage -l bob",
"explanation": "`chage -l`(list)은 사용자의 비밀번호 정책(마지막 변경일, 최대 사용일, 경고일, 계정 만료일)을 보기 좋게 출력합니다.",
"source_id": "ubuntu-user-management",
"difficulty": "medium"
},
{
"id": "linux-cmd-10",
"lesson_id": "linux-systemctl",
"question_type": "command",
"question": "`nginx` 서비스가 현재 실행 중인지 확인하는 명령을 입력하세요.",
"options": [],
"answer": "systemctl status nginx",
"explanation": "`systemctl status`는 서비스 상태, 최근 로그, PID, 메모리 사용량을 한눈에 보여줍니다. `is-active nginx`는 active/inactive만 출력합니다.",
"source_id": "manual-linux-basic",
"difficulty": "easy"
},
{
"id": "linux-cmd-11",
"lesson_id": "linux-systemd-unit",
"question_type": "command",
"question": "유닛 파일 수정 후 systemd가 변경 사항을 인식하도록 새로고침하는 명령을 입력하세요.",
"options": [],
"answer": "systemctl daemon-reload",
"explanation": "유닛 파일(`/etc/systemd/system/*.service`)을 수정하면 systemd가 자동으로 감지하지 않습니다. `daemon-reload` 후 `restart`해야 변경이 적용됩니다.",
"source_id": "manual-linux-systemd",
"difficulty": "medium"
},
{
"id": "linux-cmd-12",
"lesson_id": "linux-journalctl",
"question_type": "command",
"question": "`nginx` 서비스의 로그를 최근 50줄만 출력하는 명령을 입력하세요.",
"options": [],
"answer": "journalctl -u nginx -n 50",
"explanation": "`-u`는 특정 유닛(서비스) 필터, `-n 50`은 최근 50줄 출력입니다. `-f`를 추가하면 실시간 스트리밍됩니다.",
"source_id": "manual-linux-basic",
"difficulty": "medium"
},
{
"id": "linux-cmd-13",
"lesson_id": "linux-cron",
"question_type": "command",
"question": "현재 사용자의 crontab을 편집하는 명령을 입력하세요.",
"options": [],
"answer": "crontab -e",
"explanation": "`crontab -e`는 기본 편집기로 현재 사용자의 crontab을 엽니다. `-l`은 목록 확인, `-r`은 삭제입니다.",
"source_id": "manual-linux-basic",
"difficulty": "easy"
},
{
"id": "linux-cmd-14",
"lesson_id": "linux-df-du-mount",
"question_type": "command",
"question": "현재 마운트된 파일시스템의 디스크 사용량을 사람이 읽기 쉬운 단위(GB, MB)로 출력하는 명령을 입력하세요.",
"options": [],
"answer": "df -h",
"explanation": "`df -h`는 `-h`(human-readable) 옵션으로 GB, MB 단위로 용량을 표시합니다. `-T`를 추가하면 파일시스템 유형도 함께 출력됩니다.",
"source_id": "manual-linux-basic",
"difficulty": "easy"
},
{
"id": "linux-cmd-15",
"lesson_id": "linux-lvm",
"question_type": "command",
"question": "시스템의 모든 논리 볼륨(LV) 목록을 확인하는 명령을 입력하세요.",
"options": [],
"answer": "lvs",
"explanation": "`lvs`(LV summary)는 간결한 LV 목록을 출력합니다. `lvdisplay`는 더 자세한 정보를, `lvscan`은 모든 LV와 활성 상태를 보여줍니다.",
"source_id": "manual-linux-basic",
"difficulty": "medium"
},
{
"id": "linux-cmd-16",
"lesson_id": "linux-fstab",
"question_type": "command",
"question": "`/etc/fstab`에 등록된 모든 파일시스템을 마운트하는 명령을 입력하세요.",
"options": [],
"answer": "mount -a",
"explanation": "`mount -a`는 fstab의 noauto 옵션이 없는 모든 항목을 마운트합니다. fstab 수정 후 재부팅 없이 테스트할 때 사용합니다.",
"source_id": "manual-linux-basic",
"difficulty": "medium"
},
{
"id": "linux-cmd-17",
"lesson_id": "linux-ssh-key",
"question_type": "command",
"question": "ED25519 알고리즘으로 SSH 키 쌍을 생성하는 명령을 입력하세요.",
"options": [],
"answer": "ssh-keygen -t ed25519",
"explanation": "ED25519는 RSA 4096보다 짧고 강력한 알고리즘입니다. 생성된 공개 키(`~/.ssh/id_ed25519.pub`)를 서버의 `authorized_keys`에 등록합니다.",
"source_id": "manual-linux-basic",
"difficulty": "medium"
},
{
"id": "linux-cmd-18",
"lesson_id": "linux-sed",
"question_type": "command",
"question": "`/etc/hosts` 파일에서 `oldhost`를 `newhost`로 모두 바꿔 파일을 직접 수정하는 명령을 입력하세요.",
"options": [],
"answer": "sed -i 's/oldhost/newhost/g' /etc/hosts",
"explanation": "`-i`는 파일을 직접 수정(in-place), `s/패턴/교체/g`에서 `g`는 줄 내 모든 일치 항목을 교체합니다. `-i.bak`으로 백업도 만들 수 있습니다.",
"source_id": "manual-linux-basic",
"difficulty": "hard"
},
{
"id": "linux-cmd-19",
"lesson_id": "linux-text-pipeline",
"question_type": "command",
"question": "`/var/log/auth.log`에서 `Failed` 문자열이 포함된 줄만 뽑아 IP 주소 필드(첫 번째 공백 기준 필드 11)별 시도 횟수를 내림차순으로 출력하는 파이프라인을 입력하세요.",
"options": [],
"answer": "grep 'Failed' /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn",
"explanation": "grep→awk로 필드 추출→sort로 정렬→uniq -c로 중복 카운트→sort -rn으로 내림차순. 브루트포스 공격 IP를 파악하는 실전 패턴입니다.",
"source_id": "manual-linux-basic",
"difficulty": "hard"
},
{
"id": "linux-cmd-20",
"lesson_id": "linux-docker-basics",
"question_type": "command",
"question": "실행 중인 `webserver` 컨테이너 내부에서 `/bin/bash` 셸을 인터랙티브 터미널로 실행하는 명령을 입력하세요.",
"options": [],
"answer": "docker exec -it webserver /bin/bash",
"explanation": "`docker exec -it`는 실행 중인 컨테이너 내부에서 명령을 실행합니다. `-i`(stdin 유지), `-t`(터미널 할당). 컨테이너 안에서 디버깅할 때 필수 패턴입니다.",
"source_id": "manual-linux-docker",
"difficulty": "medium"
},
{
"id": "linux-cmd-21",
"lesson_id": "linux-mkfs-fsck",
"question_type": "command",
"question": "`/dev/sdb1` 파티션의 UUID를 확인하는 명령을 입력하세요.",
"options": [],
"answer": "blkid /dev/sdb1",
"explanation": "`blkid`는 블록 디바이스의 UUID, 파일시스템 유형(TYPE), 레이블을 출력합니다. fstab에 UUID 기반으로 등록할 때 이 명령으로 값을 확인합니다.",
"source_id": "manual-linux-storage",
"difficulty": "medium"
},
{
"id": "linux-cmd-22",
"lesson_id": "linux-at",
"question_type": "command",
"question": "1시간 후에 `/usr/local/bin/cleanup.sh`를 한 번 실행하도록 예약하는 명령을 입력하세요.",
"options": [],
"answer": "echo '/usr/local/bin/cleanup.sh' | at now + 1 hour",
"explanation": "`echo '명령' | at 시간` 형식으로 일회성 작업을 예약합니다. 예약 목록은 `atq`, 취소는 `atrm 번호`로 관리합니다.",
"source_id": "manual-linux-basic",
"difficulty": "hard"
}
]