13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] journalctl

  • [리눅스] fstab 마운트 실패 시 부팅 복구 가이드

    [리눅스] fstab 마운트 실패 시 부팅 복구 가이드

    [리눅스] fstab 마운트 실패 시 부팅 복구 가이드

    리눅스 서버를 만지다 보면 한 번쯤은 fstab 마운트 복구가 필요한 순간을 만나게 됩니다. 재부팅했는데 로그인 화면 대신 검은 화면, 혹은 emergency mode(응급 모드)로 떨어지는 그 상황이요. 저도 홈랩에서 디스크를 정리하다가 <code>/etc/fstab에 UUID를 잘못 넣어서 서버가 부팅 중간에 멈춘 적이 있었는데, 처음엔 이게 뭔가 싶었고 한참 삽질했었습니다. 그래도 원리만 잡아두면 리눅스 부팅 오류는 생각보다 침착하게 복구할 수 있거든요.

    이번 글에서는 fstab 설정 때문에 생기는 파일 시스템 마운트 실패를 어떻게 진단하고, 어떤 순서로 복구하면 되는지 경험 기준으로 정리해보겠습니다. 운영 서버든 홈랩이든 공통으로 통하는 기본기라서, 한 번 익혀두면 진짜 든든합니다.

    fstab 마운트 복구 흐름과 리눅스 부팅 오류 지점을 보여주는 개요 이미지

    부팅 흐름에서 커널, systemd(시스템 및 서비스 관리자), fstab 처리, emergency mode로 이어지는 위치를 한눈에 보여주는 개요 이미지입니다.

    1. 왜 fstab 마운트 실패가 부팅 전체를 막을까요?

    /etc/fstab는 부팅할 때 어떤 파일 시스템을 어디에 붙일지 적어두는 약속장 같은 파일입니다. 시스템은 이 내용을 보고 루트 외의 파티션, 데이터 디스크, NFS(네트워크 파일 시스템), 스왑(가상 메모리) 등을 순서대로 준비하거든요.

    문제는 여기서 오타 하나, 없는 UUID 하나, 잘못된 파일 시스템 타입 하나가 들어가면 systemd가 마운트 유닛을 만들다가 바로 실패한다는 점입니다. 특히 필수 마운트처럼 취급되는 항목이 실패하면 정상 부팅 대신 응급 셸로 떨어져요. 저도 예전에 디스크를 교체하고 UUID가 바뀐 걸 놓쳐서 한참 헤맸는데, 로그를 보니 답은 이미 거기 다 있더라고요.

    • 자주 터지는 원인: UUID 오타, 장치명 변경, 마운트 포인트 미존재, 파일 시스템 타입 오류
    • 헷갈리는 원인: 외장 디스크 분리 상태, 네트워크 스토리지 지연, 권한 문제
    • 부팅을 더 꼬이게 하는 요소: 테스트 없이 바로 재부팅

    2. fstab 설정 핵심 개념 정리

    먼저 /etc/fstab 형식부터 짚고 가겠습니다. 처음엔 필드가 너무 많아 보여서 겁먹었는데, 실제로는 의미가 반복적이라 몇 번 보면 금방 익숙해집니다.

    UUID=xxxx-xxxx  /data  ext4  defaults,nofail  0  2

    각 필드의 역할을 정리하면 이렇습니다.

    필드 의미 실무 포인트
    장치 UUID 또는 장치 경로 가능하면 UUID 사용이 안정적입니다
    마운트 지점 예: /data 디렉터리가 실제로 있어야 합니다
    파일 시스템 ext4, xfs, nfs 등 실제 포맷과 맞아야 합니다
    옵션 defaults, nofail 등 부팅 영향도를 여기서 많이 조절합니다
    dump 보통 0 대부분 기본값으로 둡니다
    fsck 순서 루트는 1, 나머지는 2 또는 0 검사 순서가 꼬이지 않게 봐야 합니다

    여기서 중요한 포인트! UUID는 디스크 이름인 /dev/sdb1보다 보통 더 안정적입니다. 재부팅 후 디스크 순서가 바뀌어도 UUID는 그대로인 경우가 많거든요. 반대로 외장 디스크나 간헐적으로 붙는 저장소라면 nofail 같은 옵션이 정말 유용합니다.

    자주 쓰는 옵션 비교

    옵션 역할 언제 쓰면 좋은가
    defaults 기본 마운트 옵션 묶음 일반적인 로컬 디스크
    nofail 마운트 실패 시 부팅 지속 외장 디스크, 보조 데이터 볼륨
    noauto 부팅 시 자동 마운트 안 함 수동으로만 붙일 볼륨
    ro 읽기 전용 마운트 보호가 필요한 장치

    3. 부팅이 안 될 때 가장 먼저 확인할 것

    혹시 이런 경험 있으신가요? 재부팅 후에 Give root password for maintenance 비슷한 메시지가 보이거나, emergency shell로 떨어지고, 프롬프트는 뜨는데 뭐부터 해야 할지 막막한 상황이요. 이럴 때 가장 중요한 건 조급하게 재부팅을 반복하지 않는 겁니다.

    1. 화면에 표시된 실패 메시지를 먼저 읽습니다.
    2. /etc/fstab를 최근에 수정했는지 떠올립니다.
    3. 문제 디스크가 실제로 연결돼 있는지 확인합니다.
    4. 가능하면 읽기/쓰기 가능한 셸로 들어가서 설정을 고칩니다.

    대부분의 배포판에서 emergency mode에 들어가면 최소한의 셸은 열립니다. 여기서 /etc/fstab를 수정해 부팅을 살리는 흐름이 가장 기본입니다.

    4. 실전 fstab 마운트 복구 절차

    이제 실제 복구 순서로 가보겠습니다. 제가 직접 해보니 핵심은 세 가지였습니다. 문제 항목 찾기, fstab 임시 수정, 재검증 후 정상 부팅. 순서만 잘 지키면 생각보다 깔끔하게 끝나요.

    4-1. 현재 블록 장치와 UUID 확인

    lsblk -f
    blkid

    lsblk -f는 파일 시스템 타입과 마운트 상태를 같이 보여줘서 정말 자주 씁니다. blkid는 UUID를 정확히 확인할 때 좋고요. /etc/fstab에 적힌 UUID와 실제 장치 UUID가 같은지 꼭 대조해보세요.

    4-2. fstab 파일 열어서 문제 항목 주석 처리

    mount -o remount,rw /
    vi /etc/fstab

    루트 파일 시스템이 읽기 전용으로 잡혀 있으면 먼저 mount -o remount,rw /로 다시 읽기/쓰기로 바꿔야 수정이 됩니다. 그다음 의심되는 줄을 임시로 주석 처리해요.

    # UUID=1111-2222  /data  ext4  defaults  0  2

    처음엔 이걸 지워도 되나 싶었는데, 실무에서는 삭제보다 주석 처리가 훨씬 안전합니다. 원래 값이 남아 있어서 나중에 비교하기 좋거든요.

    fstab 마운트 복구를 위해 emergency mode에서 설정을 수정하는 이미지

    응급 셸에서 디스크 상태를 확인하고 /etc/fstab를 주석 처리하며 복구하는 실전 흐름을 보여주는 이미지입니다.

    4-3. 마운트 테스트로 즉시 검증

    mount -a

    이 명령이 정말 중요합니다. 재부팅 전에 mount -a로 fstab 설정을 미리 검증할 수 있거든요. 여기서 에러가 없으면 한 고비 넘은 거예요. 반대로 에러가 나오면 재부팅하지 말고 메시지를 기준으로 다시 수정해야 합니다.

    추가로 systemd 기반 환경에서는 아래 점검도 꽤 유용합니다.

    findmnt --verify
    journalctl -xb

    findmnt --verify는 fstab 구문과 마운트 정보를 검증할 때 도움이 되고, journalctl -xb는 현재 부팅 세션 로그를 확인할 때 좋습니다. 실제로 써보니까 journalctl에서 어느 마운트 유닛이 실패했는지 바로 보여줘서 시간을 정말 많이 줄여주더라고요.

    4-4. 마운트 포인트와 파일 시스템 자체 점검

    mkdir -p /data
    fsck /dev/sdb1

    주의할 점이 있습니다. 문제 원인이 꼭 fstab 문법만은 아닙니다. 마운트할 디렉터리 자체가 없을 수도 있고, 파일 시스템 손상으로 마운트가 거부될 수도 있어요. 다만 fsck는 대상 파일 시스템이 마운트되지 않은 상태에서 신중히 써야 합니다. 운영 중인 루트 볼륨에 무작정 적용하는 건 위험할 수 있으니 여기선 상황 판단이 필요합니다.

    5. 자주 만나는 장애 패턴과 해결법

    여기서부터는 제가 실제로 자주 봤던 패턴들입니다. 하나씩 보면 별거 아닌데, 부팅이 막히면 사람 마음이 급해져서 놓치기 쉽더라고요.

    5-1. UUID가 바뀌었는데 fstab은 예전 값인 경우

    디스크 교체, 파티션 재생성, 포맷 변경 후 흔히 발생합니다.

    blkid
    vi /etc/fstab

    실제 UUID로 다시 맞춰주면 대부분 해결되는 경우가 많습니다.

    5-2. 외장 디스크나 보조 스토리지 분리

    홈랩에서 특히 자주 봅니다. 평소엔 붙어 있던 USB 디스크나 보조 SSD가 빠진 상태인데, fstab에는 필수처럼 등록돼 있는 거죠. 이런 경우는 nofail 옵션이 정말 유용합니다.

    UUID=xxxx-xxxx  /backup  ext4  defaults,nofail  0  2

    이렇게 하면 해당 디스크가 없어도 부팅 자체는 계속 진행됩니다. 이거 진짜 편하더라고요.

    5-3. 네트워크 파일 시스템 지연

    NFS(네트워크 파일 시스템)나 원격 스토리지는 네트워크가 늦게 올라오면 마운트 실패가 날 수 있습니다. 이 경우에는 부팅 의존성을 잘 설계해야 합니다. 네트워크 스토리지는 로컬 디스크보다 변수도 많고 복구 포인트도 다르거든요.

    5-4. 마운트 지점 오타

    정말 사소한데 자주 나옵니다. /data로 써야 하는데 /date라고 적어버리는 식이죠. 저도 처음엔 UUID만 의심했었는데, 나중에 보니 디렉터리명이 틀린 적도 있었습니다. 이런 건 로그 보면 허무할 정도로 금방 드러나요.

    fstab 마운트 복구가 필요한 대표 장애 패턴 비교 이미지

    fstab 관련 장애 원인을 유형별로 비교해 보여주는 이미지입니다. 어떤 상황에서 어떤 대응이 필요한지 감을 잡기 좋습니다.

    6. 복구 후 검증: 정상 부팅까지 확인하는 방법

    문제 줄을 고쳤다고 끝이 아닙니다. 드디어 됐다! 하고 넘어가면 다음 재부팅 때 다시 같은 문제가 터질 수 있어요. 그래서 저는 복구 후 꼭 아래 순서로 검증합니다.

    1. mount -a 실행 후 에러가 없는지 확인
    2. findmnt --verify로 설정 검토
    3. lsblk -f로 원하는 마운트가 붙었는지 확인
    4. 재부팅 후 정상 로그인 여부 확인
    5. journalctl -b로 부팅 로그 재확인
    reboot

    재부팅이 끝난 뒤에는 아래처럼 확인하면 됩니다.

    mount | grep /data
    df -h
    journalctl -b | grep -i mount

    여기서 원하는 파일 시스템이 정상적으로 잡히고, 부팅 로그에 치명적인 mount 실패가 없다면 복구는 사실상 완료입니다. ✅

    fstab 마운트 복구 후 정상 부팅과 파일 시스템 마운트 검증 이미지

    정상 부팅 후 마운트 상태, 용량 확인, 부팅 로그 검증이 끝난 결과 화면을 표현한 이미지입니다.

    7. 다시 안 터지게 만드는 운영 팁

    복구보다 더 중요한 건 재발 방지입니다. 제가 홈랩과 테스트 서버를 굴리면서 느낀 건, fstab은 작은 파일이지만 운영 안정성에 미치는 영향이 꽤 크다는 점이었어요.

    • 수정 전 백업: cp /etc/fstab /etc/fstab.bak
    • UUID 우선 사용: 장치명보다 재부팅 변화에 강합니다
    • 테스트 후 재부팅: 반드시 mount -a 먼저
    • 보조 스토리지는 nofail 고려: 부팅 장애 범위를 줄입니다
    • 마운트 포인트 사전 생성: 디렉터리 누락 방지

    백업 예시는 아주 단순하지만 효과적입니다.

    cp /etc/fstab /etc/fstab.bak
    cp /etc/fstab /etc/fstab.$(date +%F)

    그리고 변경 이력을 메모해두면 나중에 복구 속도가 훨씬 빨라집니다. 특히 여러 디스크를 붙여 쓰는 NAS 스타일 홈랩 환경에서는 더 그렇습니다.

    8. 정리와 FAQ

    fstab 마운트 복구는 겉보기엔 무섭지만, 사실 흐름은 비교적 단순합니다. 장치 확인하고, fstab 설정에서 문제 줄 찾고, mount -a로 검증한 뒤, 다시 부팅해서 로그를 확인하면 되니까요. 저도 처음엔 emergency mode만 보면 식은땀이 났었는데, 몇 번 복구해보니 결국 로그와 기본 명령어가 답이더라고요.

    특히 리눅스 부팅 오류가 fstab에서 시작됐는지 빠르게 의심하는 습관이 중요합니다. 서버가 부팅 중 멈췄을 때 최근에 스토리지 작업을 했다면 거의 우선순위 1순위로 봐도 됩니다. 다음 글에서는 systemd mount unit과 자동 마운트 설계를 조금 더 깊게 다뤄볼 예정입니다. 이전 글에서 디스크 UUID 확인 방법을 정리했었다면 같이 보셔도 흐름이 잘 이어질 겁니다.

    자주 묻는 질문

    • Q. fstab 수정 후 바로 재부팅해도 될까요?
      가능하면 안 하시는 걸 권합니다. 먼저 mount -a로 검증해보는 게 안전합니다.
    • Q. /dev/sdb1 대신 UUID를 꼭 써야 하나요?
      꼭은 아니지만 실무에서는 UUID가 보통 더 안정적입니다.
    • Q. 모든 항목에 nofail을 넣으면 되나요?
      아닙니다. 필수 마운트까지 무조건 느슨하게 만들면 다른 문제를 놓칠 수 있습니다. 보조 디스크 위주로 판단하시는 게 좋습니다.

    문제 인지, 응급 복구, 검증, 재발 방지까지 한 번에 정리한 요약 인포그래픽 이미지입니다.

  • [Linux] journald 로그 관리: systemd 실전 트러블슈팅 5가지

    [Linux] journald 로그 관리: systemd 실전 트러블슈팅 5가지

    [Linux] journald 로그 관리: systemd 실전 트러블슈팅 5가지

    서버 장애는 꼭 바쁜 시간에 터지더라고요. 특히 journald 로그 관리가 제대로 안 되어 있으면, 분명 에러는 났는데 로그가 어디 갔는지부터 찾게 됩니다. 저도 홈랩에서 Rocky Linux, Ubuntu 계열 서버를 굴리면서 처음엔 /var/log만 뒤지다가 시간을 꽤 날렸습니다. 근데 systemd 기반 배포판에서는 journalctl 하나만 제대로 익혀도 장애 대응 속도가 확 달라지거든요. 이번 글에서는 제가 실제로 자주 쓰는 Linux 트러블슈팅 방식 기준으로, 운영 중 바로 써먹을 수 있는 로그 분석 팁 5가지를 정리해보겠습니다.

    journald 로그 관리 개요와 systemd 로그 수집 구조 이미지

    systemd와 journald가 서비스 로그를 수집하고 조회하는 전체 흐름을 보여주는 개요 이미지입니다.

    1. journald가 중요한 이유: 파일 로그만 보던 습관에서 벗어나야 합니다

    쉽게 말해 journald는 systemd 환경에서 로그를 모아두는 중앙 저장소 역할을 합니다. 전통적인 텍스트 로그 파일처럼 보이는 방식과는 조금 다르죠. 서비스별 로그, 부팅 세션별 로그, 우선순위(priority), 커널 메시지까지 한 번에 엮어서 볼 수 있다는 게 핵심입니다.

    처음엔 이게 뭔가 싶었는데, 실제로 써보니까 특정 서비스가 언제 죽었는지, 재시작되기 직전에 어떤 에러가 있었는지 추적하기가 훨씬 편했습니다. 특히 컨테이너 호스트나 작은 홈서버처럼 서비스 수가 늘어나는 환경에서는 로그가 여기저기 흩어져 있으면 진짜 피곤하거든요.

    • journalctl: journald 로그 조회 도구
    • persistent logging(영구 저장): 재부팅 후에도 로그 유지
    • priority(우선순위): error, warning 같은 중요도 기준 필터링
    • boot scope(부팅 범위): 특정 부팅 시점 로그만 추적

    2. 기본 개념 먼저: journalctl은 어떻게 봐야 덜 헷갈릴까

    저도 처음엔 journalctl 치고 로그가 너무 많이 나와서 바로 닫았습니다. 그래서 저는 아래 순서로 익히는 걸 추천합니다.

    1. 전체 로그보다 서비스 단위로 보기
    2. 시간 범위를 자르기
    3. 우선순위를 걸어서 에러만 보기
    4. 부팅 단위로 사고 시점을 좁히기

    가장 먼저 익혀둘 명령은 이 정도입니다.

    # 전체 로그 최근 부분 보기
    journalctl -e
    
    # 특정 서비스 로그 보기
    journalctl -u nginx.service
    
    # 최근 부팅 기준 로그 보기
    journalctl -b
    
    # 에러 레벨만 보기
    journalctl -p err
    
    # 실시간 추적
    journalctl -f

    여기서 중요한 포인트! -u, -b, -p, --since만 익혀도 현장에서 체감이 큽니다. 쓸데없이 로그 바다에 빠지지 않게 해주거든요.

    3. 실전 트러블슈팅 1: 로그가 너무 많아서 원인을 못 찾을 때

    이건 정말 흔합니다. 로그는 있는데 너무 많아요. 특히 장시간 운영한 서버에서 전체 로그를 그냥 열면 필요한 줄 찾다가 집중력이 먼저 떨어집니다. 제가 직접 해보니 이럴 땐 시간 범위 + 서비스명 + 우선순위를 같이 거는 게 제일 효율적이었습니다.

    3-1. 시간 범위로 자르기

    journalctl --since "2026-07-15 09:00:00" --until "2026-07-15 10:00:00"
    
    journalctl --since "30 min ago"
    
    journalctl --since today

    장애가 9시 20분쯤 났다는 제보가 있으면, 굳이 하루치 전체를 볼 필요가 없죠. 이 범위를 먼저 줄이는 것만으로도 노이즈가 꽤 사라집니다.

    3-2. 서비스 단위로 좁히기

    journalctl -u docker.service --since "30 min ago"
    journalctl -u ssh.service -e
    journalctl -u NetworkManager.service -b

    예를 들어 SSH 접속 장애면 ssh.service, 컨테이너 이슈면 docker.service부터 보시면 됩니다. 서비스 이름이 헷갈릴 때는 아래처럼 확인해두면 편합니다.

    systemctl list-units --type=service
    systemctl status nginx.service

    3-3. 에러 우선순위만 보기

    journalctl -p warning
    journalctl -p err
    journalctl -p crit..alert

    저는 급할 때 journalctl -p err -b부터 봅니다. 큰 줄기부터 잡고, 그다음 상세 로그로 내려가는 방식이 훨씬 빠르더라고요.

    journald 로그 관리에서 시간 범위와 서비스 필터를 적용하는 로그 분석 이미지

    시간 범위, 서비스, 우선순위 필터를 조합해 로그를 줄여나가는 과정을 보여주는 이미지입니다.

    4. 실전 트러블슈팅 2: 재부팅 후 로그가 사라지는 문제

    처음 홈랩을 꾸렸을 때 이걸로 꽤 삽질했습니다. 분명 어젯밤에 장애가 있었는데, 아침에 다시 보니 로그가 안 남아 있는 거예요. 이유는 간단했습니다. persistent logging(영구 저장)이 꺼져 있었던 겁니다.

    4-1. 현재 저장소 상태 확인

    journalctl --disk-usage
    ls -ld /var/log/journal

    /var/log/journal 디렉터리가 없으면 메모리 기반 저장만 되는 경우가 있습니다. 배포판 설정에 따라 동작이 다를 수 있어서, 실제 상태를 먼저 확인하는 게 안전합니다.

    4-2. 영구 저장 활성화

    sudo mkdir -p /var/log/journal
    sudo systemd-tmpfiles --create --prefix /var/log/journal
    sudo systemctl restart systemd-journald

    환경에 따라 /etc/systemd/journald.conf에서 저장 정책을 명시하는 게 더 깔끔할 때도 있습니다.

    sudo editor /etc/systemd/journald.conf
    [Journal]
    Storage=persistent
    SystemMaxUse=1G
    RuntimeMaxUse=200M
    MaxRetentionSec=1month

    설정 후에는 데몬을 다시 읽혀줍니다.

    sudo systemctl restart systemd-journald
    journalctl -b -1

    -b -1이 보이면 이전 부팅 로그까지 남고 있다는 뜻입니다. 드디어 됐다! 싶은 순간이 여기서 나오죠.

    5. 실전 트러블슈팅 3: 디스크가 차오르는 원인이 journald일 때

    로그는 남겨야 하지만, 무한정 쌓아두면 결국 디스크를 압박합니다. 특히 작은 SSD나 VM 디스크에서는 이게 꽤 치명적이거든요. journald 로그 관리에서 운영자가 가장 먼저 챙겨야 할 부분 중 하나가 용량 정책입니다.

    5-1. 현재 사용량 확인

    journalctl --disk-usage

    5-2. 즉시 정리하기

    # 7일보다 오래된 로그 삭제
    sudo journalctl --vacuum-time=7d
    
    # 총 사용량을 500M 이하로 줄이기
    sudo journalctl --vacuum-size=500M
    
    # 파일 개수 기준 정리
    sudo journalctl --vacuum-files=10

    운영 중 급하게 용량을 비워야 할 때 정말 유용합니다. 다만 무작정 지우기 전에 꼭 필요한 장애 분석이 끝났는지는 확인하셔야 합니다.

    5-3. 아예 정책으로 제한하기

    [Journal]
    SystemMaxUse=1G
    SystemKeepFree=500M
    SystemMaxFileSize=100M
    MaxRetentionSec=1month

    저는 홈랩에서는 과하게 크게 잡지 않습니다. 분석 가능한 기간은 유지하되, 디스크 여유 공간도 남겨야 하니까요. 여기서 중요한 건 숫자 자체보다 정책을 명시해두는 습관입니다.

    옵션 의미 언제 유용한가
    SystemMaxUse journal 전체 최대 사용량 디스크 점유 상한을 명확히 두고 싶을 때
    SystemKeepFree 남겨둘 최소 여유 공간 서비스 디스크 고갈을 예방할 때
    MaxRetentionSec 로그 보관 기간 기간 기준으로 운영 정책을 맞출 때
    –vacuum-size 즉시 용량 기준 정리 긴급 대응 시
    journald 로그 관리의 디스크 사용량 점검과 정리 전후 비교 이미지

    journald 로그 용량을 확인하고 정리하기 전후 차이를 보여주는 시각 자료입니다.

    6. 실전 트러블슈팅 4: 서비스는 죽었는데 원인이 안 보일 때

    이럴 때는 서비스 상태만 보지 말고, 이전 부팅 기록과 실시간 추적을 같이 봐야 합니다. 특히 재시작이 반복되는 서비스는 순간적으로 죽었다 살아나서 놓치기 쉽습니다.

    6-1. 특정 부팅 세션 기준으로 보기

    journalctl --list-boots
    journalctl -b -1
    journalctl -b -2 -u nginx.service

    배포 후 재부팅이 있었는지, 장애가 이전 부팅부터 이어진 건지 확인할 때 굉장히 유용합니다. 저도 커널 업데이트 이후 네트워크 서비스가 꼬인 적이 있었는데, 부팅별로 나눠보니 원인이 바로 보이더라고요.

    6-2. 서비스 실시간 추적

    journalctl -u myapp.service -f

    애플리케이션 재시작 테스트를 하면서 한쪽 터미널에서는 이 명령을 띄워두면 편합니다. 장애 재현과 동시에 로그를 보게 되니까, 놓치는 줄이 확 줄어듭니다.

    6-3. 상세 상태 확인과 묶어서 보기

    systemctl status myapp.service
    journalctl -u myapp.service -n 100 -o short-iso

    systemctl status는 현재 상태 요약, journalctl은 상세 로그 본문이라고 생각하시면 이해가 쉽습니다.

    7. 실전 트러블슈팅 5: 로그 형식이 불편하거나 파이프라인 연동이 필요할 때

    운영하다 보면 사람 눈으로만 보는 로그보다, 다른 도구로 넘기기 좋은 형식이 필요할 때가 있습니다. 예를 들어 자동화 스크립트, 간단한 grep 처리, 또는 JSON 수집 파이프라인 같은 경우죠.

    7-1. 출력 형식 바꾸기

    journalctl -u nginx.service -o short-iso
    journalctl -u nginx.service -o json
    journalctl -u nginx.service -o cat

    개인적으로 사람 눈으로 볼 땐 short-iso를 자주 씁니다. 타임스탬프가 읽기 편해서요. 반면 후처리나 수집 연계가 필요하면 json 출력이 꽤 쓸만합니다.

    7-2. 최근 로그 일부만 빠르게 확인

    journalctl -u nginx.service -n 50
    journalctl -k -n 100

    -k는 커널 로그를 보는 옵션입니다. 디스크 I/O나 네트워크 드라이버 문제처럼 시스템 하단 이슈를 의심할 때 먼저 보는 편입니다.

    7-3. grep과 함께 써서 빠르게 패턴 찾기

    journalctl -u docker.service --since "1 hour ago" | grep -i error
    journalctl -b | grep -Ei "timeout|failed|denied"

    엄밀히 말하면 structured log(구조화 로그)의 장점을 다 살리는 방식은 아니지만, 현장에선 이렇게 빠르게 감 잡는 경우도 많습니다. 급할 때는 일단 보이는 게 중요하거든요.

    journald 로그 관리에서 서비스 로그 실시간 추적과 구조화 출력 예시 이미지

    서비스 로그를 실시간으로 추적하고 다양한 출력 형식으로 확인하는 예시 이미지입니다.

    8. 운영 중 자주 겪는 주의사항: 제가 삽질했던 포인트들

    여기부터는 진짜 실무형 메모입니다. 문서만 보면 안 보이는데, 실제로는 아래 포인트에서 많이 막히더라고요.

    • ⚠️ 권한 문제: 일반 사용자로는 일부 시스템 로그가 제한될 수 있습니다. 안 보이면 sudo로 다시 확인해보세요.
    • ⚠️ 로그가 없다고 장애가 없는 건 아닙니다: 애플리케이션이 stdout/stderr로 안 남기면 journald에도 부족하게 남을 수 있습니다.
    • ⚠️ 영구 저장 설정 후 재시작 필요: 설정 파일만 바꾸고 journald 재시작을 안 해서 헷갈리는 경우가 많습니다.
    • ⚠️ 너무 aggressive한 vacuum: 로그를 급하게 지웠다가, 나중에 RCA(Root Cause Analysis, 근본 원인 분석) 못 하는 상황이 생깁니다.
    • ⚠️ 시간 동기화 확인: NTP가 어긋나면 로그 해석이 꼬입니다. 사건 순서가 뒤집혀 보이기도 하거든요.

    여기서 중요한 포인트! journald 로그 관리는 단순히 용량 정리만 의미하지 않습니다. 남겨야 할 로그를 남기고, 필요한 순간에 바로 찾을 수 있게 만드는 운영 습관에 가깝습니다.

    FAQ: 많이 받는 질문

    Q. rsyslog가 있으면 journald는 안 써도 되나요?
    아닙니다. 둘은 배타적이라기보다 함께 쓰는 경우가 많습니다. journald로 빠르게 조회하고, 필요하면 다른 로그 시스템으로 전달하는 식이죠.

    Q. journalctl이 너무 느릴 때는요?
    시간 범위, 서비스명, 부팅 범위를 먼저 줄여보세요. 전체 검색부터 하면 당연히 체감이 무겁습니다.

    Q. Linux 트러블슈팅에서 가장 먼저 볼 명령 하나만 고르라면?
    저는 journalctl -p err -b를 자주 씁니다. 현재 부팅의 에러를 먼저 보고 큰 줄기를 잡기 좋거든요.

    9. 검증과 마무리: 제대로 설정됐는지 이렇게 확인하면 됩니다

    설정은 했는데 정말 잘 적용됐는지 확인하는 단계가 중요합니다. 아래 순서대로 보면 웬만한 건 검증됩니다.

    1. journalctl --disk-usage로 저장량 확인
    2. journalctl --list-boots로 이전 부팅 로그 유지 여부 확인
    3. journalctl -u 서비스명 -f로 실시간 수집 확인
    4. journalctl -p err -b로 에러 필터 확인
    5. systemctl restart systemd-journald 이후 동작 재확인
    journalctl --disk-usage
    journalctl --list-boots
    journalctl -b -1
    journalctl -u ssh.service -n 20 -o short-iso
    journalctl -p err -b

    이 다섯 줄만 점검해도 현재 서버의 journald 상태를 꽤 명확하게 파악할 수 있습니다. 저도 처음엔 파일 로그만 찾다가 돌아왔는데, 이제는 장애가 나면 거의 반사적으로 journalctl부터 엽니다. 이거 진짜 편하더라고요.

    정리하자면, 이번 글의 핵심은 이겁니다. journald 로그 관리는 로그를 보는 기술이 아니라, 장애 순간에 증거를 잃지 않는 운영 방식입니다. persistent 설정으로 로그를 남기고, 시간/서비스/우선순위 필터로 빨리 좁히고, vacuum 정책으로 디스크를 보호하면 기본기는 꽤 단단해집니다.

    다음 글에서는 systemd 서비스 유닛 파일 튜닝이나, rsyslog와의 연계, 중앙 로그 수집 구조도 이어서 다뤄볼 예정입니다. 이전 글에서 다뤘던 리눅스 서비스 장애 대응 흐름과 연결해서 보시면 더 이해가 잘 되실 거예요. 혹시 지금 운영 중인 서버에서 로그가 자꾸 증발하거나, 디스크가 로그 때문에 차는 경험 있으신가요? 그럴 때 오늘 소개한 5가지를 하나씩 적용해보시면 방향이 꽤 빨리 잡히실 겁니다.

    journald 설정과 검증 포인트를 한눈에 정리한 요약 인포그래픽 이미지입니다.

  • [Linux] systemd 서비스 오류 진단 및 해결: journalctl 활용법

    [Linux] systemd 서비스 오류 진단 및 해결: journalctl 활용법

    [Linux] systemd 서비스 오류 진단 및 해결: journalctl 활용법

    리눅스 서버를 운영하다 보면 갑자기 서비스가 죽어버리거나, 재부팅 이후 특정 데몬(daemon, 백그라운드 서비스)이 올라오지 않는 상황을 꼭 한 번쯤 겪게 됩니다. 저도 홈랩에서 웹 서버, 백업 에이전트, VPN 서비스까지 이것저것 올려두고 쓰다 보니, systemd 서비스 오류 해결이 생각보다 자주 필요한 작업이더라고요. 처음엔 서비스가 실패했다는 메시지만 보고 멍해졌었는데, 실제로는 journalctl(저널 로그 조회 도구)만 제대로 써도 원인 파악 속도가 확 달라집니다. 혹시 서비스는 안 뜨는데 왜 죽는지 감이 안 잡히는 경험 있으신가요? 오늘은 제가 직접 삽질하면서 정리한 방식으로, journalctl 사용법부터 리눅스 서비스 디버깅, systemd 유닛 실패, 그리고 부팅 문제 추적까지 한 번에 정리해보겠습니다.

    systemd 서비스 오류 해결과 journalctl 로그 흐름을 설명하는 개요 다이어그램

    systemd가 서비스 상태를 관리하고 journalctl이 로그를 추적하는 전체 흐름을 한눈에 보여주는 개요 이미지입니다.

    1. 왜 systemd 서비스 오류 진단이 중요한가

    예전에는 SysV init(전통적인 리눅스 초기화 방식) 스크립트를 직접 뒤져보던 시절도 있었지만, 요즘 주요 배포판은 대부분 systemd(시스템 및 서비스 관리자)를 씁니다. 서비스 시작, 중지, 재시작은 물론이고 부팅 시 의존성(dependency, 선후관계)까지 systemd가 관리하죠. 문제는 여기서 서비스 하나만 꼬여도 연쇄적으로 장애가 퍼질 수 있다는 점입니다.

    예를 들어 이런 상황이 있습니다.

    • 웹 서비스는 죽었는데 포트 충돌인지, 권한 문제인지 모르겠을 때
    • 부팅은 됐는데 특정 유닛(unit, 서비스 정의 파일)이 실패해서 후속 작업이 멈췄을 때
    • 재시작 루프에 빠져 CPU를 계속 잡아먹을 때
    • 로그 파일이 흩어져 있어서 어디부터 봐야 할지 막막할 때

    이럴 때 무작정 <code>systemctl restart만 반복하면 해결이 안 됩니다. 저도 처음엔 그러다가 로그 힌트를 놓쳐서 시간을 두 배로 쓴 적이 많았거든요. 여기서 중요한 포인트! systemd 서비스 오류 해결의 핵심은 상태 확인과 로그 확인을 분리해서 보는 것입니다.

    2. systemd와 journalctl, 쉽게 말해 뭐가 다른가

    쉽게 말해 systemctl은 “서비스를 관리하는 도구”이고, journalctl은 “무슨 일이 있었는지 기록을 읽는 도구”입니다. 둘을 같이 써야 제대로 보입니다.

    도구 역할 주요 용도
    systemctl 서비스 제어 및 상태 조회 start, stop, restart, status
    journalctl 저널 로그 조회 에러 원인 분석, 시간대별 추적
    systemd unit 서비스 정의 파일 ExecStart, Restart, After 등 설정

    보통 장애 분석은 이런 흐름으로 갑니다.

    1. systemctl status로 현재 실패 상태를 확인합니다.
    2. journalctl -u 서비스명으로 해당 서비스 로그를 좁혀봅니다.
    3. 필요하면 부팅 단위 로그, 이전 부팅 로그까지 확장해서 봅니다.
    4. 원인이 설정 파일인지, 권한인지, 실행 파일 경로인지 확인합니다.

    이 패턴만 익혀도 대부분의 리눅스 서비스 디버깅은 훨씬 수월해집니다.

    3. 가장 먼저 보는 기본 명령어

    실전에서는 저는 거의 항상 아래 순서로 확인합니다. 눈에 익혀두시면 정말 편합니다.

    3-1. 서비스 상태 확인

    sudo systemctl status nginx.service

    여기서 봐야 할 포인트는 세 가지예요.

    • Loaded: 유닛 파일이 정상적으로 읽혔는지
    • Active: active, failed, activating 상태가 어떤지
    • Main PID / Exit code: 프로세스가 왜 종료됐는지

    출력 하단에 최근 로그 일부가 붙는 경우도 있는데, 그걸로 끝내면 안 됩니다. 진짜 원인은 뒤에 더 있을 때가 많거든요.

    3-2. 특정 서비스 로그 보기

    sudo journalctl -u nginx.service

    이 명령은 해당 유닛에 연결된 로그만 쏙 빼서 보여줍니다. 로그가 많으면 아래처럼 최근 것만 보는 식으로 줄여서 봐도 좋습니다.

    sudo journalctl -u nginx.service -n 50

    실시간으로 따라가려면 tail(로그 끝 추적) 같이 -f 옵션을 쓰면 편합니다.

    sudo journalctl -u nginx.service -f

    제가 직접 해보니 재시작 테스트할 때 이 조합이 제일 편하더라고요. 한쪽 터미널에서는 로그를 보고, 다른 쪽에서는 서비스를 재시작합니다.

    sudo systemctl restart nginx.service

    3-3. 에러 우선으로 좁혀보기

    sudo journalctl -p err..alert

    이건 시스템 전체에서 error 이상의 심각한 로그만 골라서 봅니다. 서비스명이 명확하지 않거나, 어디서 문제가 시작됐는지 감이 안 올 때 꽤 유용해요.

    4. 실전으로 보는 journalctl 활용법

    이제 실제 장애 분석 흐름으로 가보겠습니다. 예시로 사용자 정의 앱 서비스가 실행 실패하는 상황을 가정해볼게요.

    4-1. 실패한 유닛만 먼저 확인

    sudo systemctl --failed

    부팅 직후 이상이 있을 때는 이 명령이 정말 좋습니다. 실패한 유닛을 한 번에 보여주니까요. 특히 systemd 유닛 실패가 여러 개 겹쳐 있을 때 시작점 찾기에 좋아요.

    4-2. 해당 유닛 상세 상태 확인

    sudo systemctl status myapp.service

    예를 들어 여기서 code=exited, status=203/EXEC 같은 메시지가 보이면 실행 파일 경로나 권한을 먼저 의심해봅니다. 저도 처음엔 애플리케이션 문제인 줄 알고 코드부터 뒤졌는데, 알고 보니 ExecStart 경로 오타였던 적이 있습니다. 이런 거 은근 자주 나옵니다 ㅎㅎ

    4-3. 시간 범위로 로그 좁히기

    sudo journalctl -u myapp.service --since "2026-07-11 09:00:00" --until "2026-07-11 09:10:00"

    재배포 직후나 재부팅 직후처럼 문제 발생 시점이 뚜렷하면 시간 범위를 넣는 게 좋습니다. 로그가 긴 서버일수록 이게 체감상 엄청 크다니까요.

    systemd 서비스 오류 해결을 위해 상태와 로그를 함께 보는 터미널 화면

    서비스 상태와 저널 로그를 나란히 확인하면서 실행 경로, 권한, 포트 충돌 같은 원인을 추적하는 장면을 표현한 이미지입니다.

    4-4. 현재 부팅 기준 로그 보기

    sudo journalctl -b

    -b는 현재 부팅(boot, 시스템 시작 세션) 기준 로그를 보여줍니다. 부팅 직후 서비스가 안 뜨는 경우엔 정말 자주 씁니다. 시스템 전체를 보고 싶을 때는 좋지만, 특정 서비스 분석이라면 유닛 옵션과 같이 쓰는 편이 나아요.

    sudo journalctl -b -u myapp.service

    4-5. 이전 부팅 로그 확인

    sudo journalctl -b -1

    이건 부팅 문제 잡을 때 핵심입니다. 오늘은 정상인데 어제 재부팅에서는 실패했다면, 이전 부팅 로그를 보는 게 맞습니다. 실제로 써보니 “지금은 재현 안 되는데 아까는 왜 안 됐지?” 같은 상황에서 아주 큰 도움이 되더라고요.

    sudo journalctl -b -1 -u myapp.service

    5. 자주 만나는 장애 유형과 해결 패턴

    여기부터는 제가 실무와 홈랩에서 자주 본 패턴 위주로 정리해보겠습니다. 모든 에러를 외울 필요는 없고, 로그에서 어떤 방향으로 해석할지만 익혀도 충분합니다.

    5-1. 실행 파일 경로 오류

    ExecStart에 지정한 바이너리(binary, 실행 파일) 경로가 틀리면 서비스는 시작도 못 합니다.

    sudo systemctl cat myapp.service

    유닛 내용을 확인해서 ExecStart=/opt/myapp/bin/start.sh 같은 경로가 실제 존재하는지 봅니다.

    ls -l /opt/myapp/bin/start.sh

    없거나 실행 권한이 없으면 아래처럼 수정합니다.

    sudo chmod +x /opt/myapp/bin/start.sh
    sudo systemctl daemon-reload
    sudo systemctl restart myapp.service

    5-2. 포트 충돌

    웹 서버나 에이전트 서비스는 포트 충돌 때문에 죽는 경우가 많습니다. 로그에 address already in use 같은 문구가 보이면 거의 이쪽입니다.

    sudo ss -lntp

    어떤 프로세스가 포트를 잡고 있는지 확인하고, 중복 서비스가 있으면 정리합니다.

    5-3. 권한 문제

    systemd 서비스는 보통 root 또는 특정 사용자 계정으로 실행됩니다. 파일 접근 권한이 안 맞으면 시작 직후 종료됩니다.

    sudo journalctl -u myapp.service -n 100 | grep -i "permission\|denied"

    여기서 중요한 건 서비스 실행 계정입니다.

    sudo systemctl show myapp.service -p User -p Group

    로그에 Permission denied가 보이면 파일 소유권(owner)과 권한부터 확인해봐요.

    5-4. 환경 변수 누락

    애플리케이션이 쉘에서는 잘 뜨는데 systemd에서는 실패하는 경우가 있습니다. 이건 환경 변수(environment variable) 차이인 경우가 많습니다. 저도 Docker가 아닌 순수 서비스로 앱 띄울 때 여기서 꽤 삽질했어요.

    sudo systemctl cat myapp.service

    필요하면 유닛에 다음처럼 넣습니다.

    [Service]
    Environment="APP_ENV=production"
    Environment="JAVA_HOME=/usr/lib/jvm/java-17-openjdk"

    수정 후엔 꼭 다시 읽혀야 합니다.

    sudo systemctl daemon-reload
    sudo systemctl restart myapp.service

    6. ⚠️ 제가 실제로 자주 겪은 트러블슈팅 포인트

    이 섹션은 정말 현장에서 체감 큰 부분입니다. 문법은 맞는데 계속 안 되는 상황, 그거 꽤 답답하거든요.

    • daemon-reload를 빼먹는 실수: 유닛 파일 수정 후 sudo systemctl daemon-reload를 안 하면 이전 설정이 계속 적용됩니다.
    • 로그 보존 정책 차이: 환경에 따라 journal이 메모리 기반으로만 남아 재부팅 후 예전 로그가 제한적일 수 있습니다.
    • 서비스 이름 착각: 패키지명과 유닛명이 다를 수 있습니다. 예를 들어 실제 유닛명이 예상과 다를 수 있으니 systemctl list-units --type=service로 확인하세요.
    • Restart 정책 오해: Restart=always 때문에 서비스가 계속 재기동되면 원인 로그가 빨리 지나갑니다. 이럴 땐 실시간 로그 추적이 필수예요.

    특히 재시작 루프는 초보 때 진짜 헷갈립니다. 서비스는 살아있는 것처럼 보이는데, 사실은 죽고 다시 뜨고를 반복하고 있거든요.

    sudo systemctl show myapp.service -p Restart -p RestartSec -p ExecMainStatus

    이렇게 정책과 종료 상태를 함께 보면 흐름이 좀 더 명확해집니다.

    7. 검증과 결과 확인은 이렇게 합니다

    문제를 수정한 뒤에는 단순히 서비스가 올라왔는지만 보지 말고, 실제로 안정적으로 동작하는지 확인해야 합니다. 저도 예전엔 active (running)만 보고 끝냈다가 30초 후 다시 죽는 걸 놓친 적이 있었습니다.

    1. 서비스 상태를 다시 확인합니다.
    2. 최근 로그에 에러가 사라졌는지 봅니다.
    3. 필요하면 포트, 프로세스, 응답까지 점검합니다.
    4. 재부팅 후에도 자동 시작이 되는지 확인합니다.
    sudo systemctl status myapp.service
    sudo journalctl -u myapp.service -n 30
    sudo systemctl is-enabled myapp.service
    sudo systemctl is-active myapp.service

    웹 서비스라면 간단히 응답 체크도 해보면 좋습니다.

    curl -I http://127.0.0.1:8080

    이 단계까지 통과하면 드디어 됐다! 싶은 순간이 옵니다. 이런 맛에 로그 보는 거죠.

    systemd 서비스 오류 해결 후 정상 동작을 검증하는 장면

    수정 이후 서비스가 정상 실행되고 최근 로그에 치명적인 오류가 사라진 상태를 확인하는 검증 이미지를 위한 위치입니다.

    8. 빠르게 보는 명령어 치트시트

    정리 차원에서 많이 쓰는 명령을 표로 묶어보겠습니다. 장애 대응 중엔 이런 요약이 꽤 도움이 됩니다.

    상황 명령어 설명
    서비스 상태 확인 systemctl status 서비스명 현재 상태와 최근 로그 확인
    특정 서비스 로그 journalctl -u 서비스명 해당 유닛 관련 로그만 조회
    최근 로그 50줄 journalctl -u 서비스명 -n 50 최근 에러 빠르게 확인
    실시간 추적 journalctl -u 서비스명 -f 재시작 테스트와 함께 보기 좋음
    현재 부팅 로그 journalctl -b 이번 부팅 기준 전체 로그
    이전 부팅 로그 journalctl -b -1 재부팅 전 문제 추적
    실패 유닛 확인 systemctl --failed 실패한 서비스 일괄 조회

    이 정도만 손에 익으면 대부분의 systemd 서비스 오류 해결 작업은 훨씬 빨라집니다. 그리고 다음 글에서는 systemd unit 파일 작성법과 Restart 정책 설계도 따로 다뤄볼 예정입니다. 이전 글에서 로그 로테이션(log rotation, 로그 보관 정책) 관련 내용을 보셨다면 함께 연결해서 보셔도 좋습니다.

    journalctl 사용법과 systemd 서비스 오류 해결 순서를 요약한 인포그래픽

    자주 쓰는 journalctl 옵션과 장애 대응 순서를 요약한 인포그래픽용 이미지 위치입니다.

    9. 마무리: 로그를 보면 서비스가 왜 죽는지 보입니다

    systemd 서비스 오류 해결은 막연히 어려워 보이지만, 사실 흐름은 꽤 단순합니다. 상태 확인은 systemctl, 원인 추적은 journalctl. 이 두 축만 잘 잡으면 됩니다. 저도 처음엔 서비스가 failed로 뜨면 겁부터 났는데, 하나씩 로그를 따라가다 보니 오히려 장애 대응의 기준점이 생기더라고요.

    오늘 정리한 내용을 다시 압축하면 이렇습니다.

    • 서비스가 죽었으면 먼저 status로 현재 상태를 봅니다.
    • 원인은 journalctl로 시간대와 유닛 기준으로 좁혀봅니다.
    • 부팅 문제는 -b와 -b -1 조합으로 추적합니다.
    • 실행 경로, 권한, 포트, 환경 변수를 우선 의심하면 해결이 빠릅니다.

    혹시 지금도 특정 서비스가 이유 없이 죽고 있다면, 무작정 재시작부터 하지 마시고 저널부터 한 번 열어보세요. 생각보다 답이 로그 안에 그대로 들어있습니다. 이거 진짜 편하더라고요. 다음 글에서는 서비스 자동 재시작 정책과 의존성 설정을 조금 더 깊게 다뤄보겠습니다.