리눅스 부팅 시간 가속화: Systemd 유닛 의존성 분석 및 최적화
systemd-analyze, critical-chain, 유닛 의존성 정리를 사용하여 느린 리눅스 부팅 경로를 찾고 수정하는 방법
리눅스 부팅 시간 가속화: Systemd 유닛 의존성 분석 및 최적화
리눅스 부팅 시간 최적화는 한 가지 질문에서 시작됩니다: 무엇이 실제로 시스템이 사용 가능해지는 것을 막고 있는가? 대부분의 최신 배포판에서 systemd는 서비스를 병렬로 시작하지만, 느린 유닛이나 불필요한 순서 규칙이 여전히 부팅 경로를 지연시킬 수 있습니다.
어떤 유닛이 시간을 소비하고 어떤 유닛이 중요 체인(critical chain)에 있는지 확인함으로써, 해당 유닛을 조정, 지연 또는 비활성화할지 결정할 수 있습니다. 아래 예제는 systemd-analyze와 시스템 예측 가능성을 유지하는 작은 의존성 변경에 초점을 맞춥니다.
Systemd 부팅 프로세스 이해하기
Systemd는 가능한 한 서비스를 병렬로 실행하여 시작 프로세스를 관리합니다. 그러나 서비스는 명시적 및 암시적 의존성이 모두 충족될 때만 시작할 수 있습니다. 유닛 A가 진행되기 전에 유닛 B가 완전히 활성화되어야 한다면, 유닛 A는 유닛 B에 의해 차단됩니다. 이러한 차단 의존성을 식별하는 것이 가속화를 위한 첫 번째 단계입니다.
주요 Systemd 분석 도구
Systemd는 부팅 성능을 진단하기 위한 몇 가지 강력한 명령줄 유틸리티를 제공합니다. 다음 도구는 병목 지점을 정확히 찾는 데 필수적입니다.
1. systemd-analyze (전체 보기)
이 명령은 커널, 사용자 공간 초기화 및 사용 가능한 대상 로드에 소요된 총 시간에 대한 개괄적인 개요를 제공합니다.
systemd-analyze
예제 출력 해석:
| 구성 요소 | 소요 시간 |
|---|---|
| 커널 | 1.234초 |
| Initrd | 0.500초 |
| 사용자 공간 | 5.789초 |
| 합계 | 7.523초 |
이를 통해 병목 현상이 커널 단계(펌웨어/드라이버 로딩)인지 사용자 공간 단계(서비스 시작)인지 빠르게 확인할 수 있습니다.
2. systemd-analyze blame (느린 유닛 식별)
이 명령은 활성화에 소요된 시간 순으로 정렬된 유닛 목록을 표시하며, 가장 오래 걸린 항목이 상단에 위치합니다.
systemd-analyze blame
초점: 상위 10개 항목을 살펴보십시오. 이는 시작 중에 적극적으로 시간을 소비하는 서비스입니다. 초기화 시간이 길다는 것은 단순히 서비스가 많은 작업을 수행한다는 의미일 수 있습니다. 목표는 이 작업이 부팅 중에 필요한지 확인하는 것입니다.
3. systemd-analyze critical-chain (의존성 분석)
이 명령은 부팅 대상(일반적으로 graphical.target 또는 multi-user.target)으로 이어지는 의존성 체인을 보여줍니다. 시스템이 완전히 부팅된 것으로 간주되기 전에 반드시 완료되어야 하는 유닛의 순서를 강조합니다.
systemd-analyze critical-chain
중요 체인에 나열된 유닛은 최적화의 주요 대상입니다. 이들을 지연시키면 전체 시스템 부팅이 지연되기 때문입니다.
4. systemd-analyze plot (부팅 순서 시각화)
병렬 처리 및 차단을 그래픽으로 표현하려면 SVG 파일을 생성하는 플롯 명령을 사용하십시오:
systemd-analyze plot > boot_analysis.svg
# 웹 브라우저에서 boot_analysis.svg 열기
이 그래프는 어떤 서비스가 병렬로 실행되고 어떤 서비스가 다른 서비스를 기다리고 있는지 시각적으로 보여주므로 의존성 문제를 즉시 파악할 수 있습니다.
최적화 기술: 유닛 파일 수정
위 도구를 사용하여 느리거나 차단하는 유닛을 식별한 후, 최적화는 유닛 자체를 빠르게 하거나 실행 시점을 변경하는 것을 포함합니다.
1. blame으로 식별된 느린 유닛 처리
blame 출력 상위에 있는 서비스(예: slow-database.service가 10초 소요)가 기본 시스템 작동(예: 로그인 또는 기본 네트워킹)에 즉시 필요하지 않은 경우, 지연시키는 것을 고려하십시오.
조치: 시작 의존성 수준을 변경합니다.
- 현재
multi-user.target에서 시작하는 경우, 타이머, 소켓, 경로 유닛 또는 수동 명령에서 시작할 수 있는지 확인하십시오. - 서비스가 선택 사항인 경우, 핵심 의존성 동작을 변경하는 것보다 비활성화하는 것이 일반적으로 더 안전합니다. 해당 유닛 유형에 대해 systemd가 일반적으로 추가하는 기본 순서를 이해하는 경우에만
DefaultDependencies=no를 사용하십시오.
2. Wants, Requires 및 After를 사용한 의존성 최적화
유닛 파일은 의존성 지시문을 사용하여 실행 순서를 제어합니다. 여기서의 잘못된 구성은 불필요한 순차적 실행의 일반적인 원인입니다.
의존성 유형:
Requires=: 강력한 의존성. 필수 유닛이 실패하면 이 유닛도 실패합니다.Wants=: 약한 의존성. 원하는 유닛을 사용할 수 있으면 이 유닛이 시작되지만, 원하는 유닛이 실패해도 시작을 시도합니다.After=: 순서 지정 지시문. 이 유닛은 지정된 유닛이 시작을 완료한 후에만 시작됩니다(성공 여부와 관계없음).Before=: 순서 지정 지시문. 이 유닛은 지정된 유닛 전에 시작되어야 합니다.
모범 사례 팁: 선택적 관계에는 Requires보다 Wants를 선호하십시오. Wants=는 실패 동작을 변경하며, 자체적으로 순서를 지정하지는 않습니다. After=와 같은 순서 규칙을 추가하지 않는 한, 원하는 유닛은 여전히 병렬로 시작될 수 있습니다.
불필요한 After= 제약 조건 제거
부팅 시간을 단축하는 가장 효과적인 방법은 불필요한 순서 제약 조건을 제거하는 것입니다. 유닛 A가 기능적으로 유닛 B가 시작될 때까지 기다릴 필요가 없다면, 유닛 A의 정의에서 After=unit-b.service 줄을 제거하십시오.
예제 수정 (개념적):
사용자 정의 애플리케이션 유닛 app.service가 불필요하게 네트워크 구성 서비스를 기다린다고 가정해 보십시오:
# /etc/systemd/system/app.service
[Unit]
Description=My Application
Requires=network.target
After=network.target <-- 잠재적으로 불필요한 대기!
[Service]
ExecStart=/usr/bin/myapp
애플리케이션이 로컬 루프백 인터페이스만 필요하거나 로컬 파일 잠금만 설정하면 되는 경우, 전체 네트워크 스택(network.target)을 기다리는 것은 몇 초를 낭비할 수 있습니다. 애플리케이션이 실제로 외부 네트워크가 필요하지 않음을 확인하면 After=network.target 줄을 제거하십시오. 그러면 systemd는 네트워크 설정과 병렬로 가능한 한 빨리 app.service를 시작하려고 시도합니다.
3. 불필요한 서비스 마스킹
systemd-analyze blame이 전혀 필요하지 않은 서비스(예: 서버에서 불필요한 블루투스 지원, 특정 하드웨어 모니터)가 실행 중임을 보여주는 경우, 비활성화하거나 마스킹하면 시작 자체를 중단할 수 있습니다.
- 비활성화:
systemctl disable <unit>(향후 부팅 시 시작되지 않도록 함). - 마스킹 (더 강력함):
systemctl mask <unit>(유닛을/dev/null에 연결하여 수동 시작 시도도 방지).
# 예: 셀룰러 모뎀이 없는 경우 ModemManager 마스킹
sudo systemctl mask ModemManager.service
변경 사항 다시 로드 및 확인
유닛 파일(특히 /etc/systemd/system/에 배치된 파일)을 수정한 후에는 재부팅하여 테스트하기 전에 systemd에 구성 데몬을 다시 로드하도록 지시해야 합니다:
sudo systemctl daemon-reload
# 그런 다음 재부팅 전에 의존성 또는 상태 확인
systemctl list-dependencies myapp.service
마지막으로, 항상 시스템을 재부팅하여 부팅 순서에 대한 실제 영향을 측정하십시오.
sudo reboot
재부팅 후 즉시 systemd-analyze를 다시 실행하여 최적화를 통해 달성한 시간 절감 효과를 정량화하십시오.
핵심 요점
부팅 튜닝을 작은 변경 루프로 취급하십시오: systemd-analyze로 측정하고, 중요 경로에 있는 유닛을 찾고, 정당화할 수 있는 순서 규칙만 제거한 다음, 재부팅하고 다시 측정하십시오. 가장 안전한 이점은 일반적으로 불필요한 서비스 비활성화, 작업을 타이머 또는 소켓 활성화로 전환, 그리고 자체 유닛에서 불필요한 After= 줄을 제거하는 데서 옵니다.