journalctl 명령어: 사용법과 서비스별 로그, 저널 용량 정리

서비스와 커널이 남긴 로그를 systemd 저널에서 골라 읽는 도구가 journalctl 명령어입니다. systemd를 쓰는 리눅스에서는 systemd-journald가 이 로그를 저널에 모아 둡니다. AlmaLinux 9 서버와 Debian 12 서버에서 서비스와 시간, 중요도별로 로그를 골라 읽은 결과, 일반 계정에는 자기 로그만 보였고 저널을 메모리에 두는 서버는 이전 부팅을 고를 수 없었습니다.
아래 출력은 두 서버에서 실행한 결과입니다. 호스트 이름, 계정, 부팅 ID, AlmaLinux 서버의 프로세스 번호와 systemd 패키지 릴리스는 예시 값으로 바꿨고, 시각은 두 서버 모두 UTC로 출력했습니다.
1️⃣ journalctl 명령어 사용법과 최근 로그
옵션 없이 journalctl을 실행하면 저널의 가장 오래된 줄부터 less 화면으로 열리므로, 최근 로그를 볼 때는 -n으로 줄 수를 정합니다. -n 뒤에 숫자를 생략하면 10줄이 나옵니다.
journalctl -n 3Oct 28 07:14:06 server1 systemd[1]: session-3017.scope: Deactivated successfully.
Oct 28 07:14:06 server1 systemd[1]: session-3017.scope: Consumed 3.934s CPU time.
Oct 28 07:14:07 server1 sudo[851987]: pam_unix(sudo:session): session closed for user user한 줄은 시각, 호스트 이름, 로그를 남긴 프로그램과 프로세스 번호, 메시지 순서로 이루어집니다. -r을 붙이면 순서가 뒤집혀 가장 최근 줄이 맨 위로 올라옵니다. AlmaLinux 서버의 crond 로그에서는 가장 늦게 남은 CMDEND 줄이 맨 위였습니다.
journalctl -r -u crond -n 3Oct 28 07:01:01 server1 CROND[841384]: (root) CMDEND (run-parts /etc/cron.hourly)
Oct 28 07:01:01 server1 run-parts[841394]: (/etc/cron.hourly) starting 0anacron
Oct 28 07:01:01 server1 CROND[841388]: (root) CMD (run-parts /etc/cron.hourly)-f는 마지막 줄을 출력한 뒤 끝나지 않고 새로 들어오는 줄을 계속 이어서 출력합니다. Debian 12 서버에서 -q와 -t myapp을 붙여 logger 줄의 마지막 한 줄을 띄워 두고, logger로 두 줄을 더 남겼습니다. 남긴 두 줄이 그 아래에 바로 이어졌습니다.
journalctl -q -f -n 1 -t myappOct 28 07:12:46 server2 myapp[347704]: journalctl error test
Oct 28 07:14:35 server2 myapp[347881]: follow line 1
Oct 28 07:14:36 server2 myapp[347877]: follow line 2-f는 Ctrl+C를 누를 때까지 멈추지 않으므로, 서비스를 다시 시작하는 동안 로그를 지켜볼 때 사용합니다.
less 화면에서는 화면 폭보다 긴 줄이 오른쪽에서 잘리고, 방향키로 잘린 부분을 확인합니다. 출력을 파이프나 파일로 넘기면 less를 거치지 않습니다. less 없이 터미널에 바로 띄우려면 --no-pager를 붙입니다.
2️⃣ journalctl 서비스별 로그
최근 줄만 보면 여러 서비스의 로그가 섞여 나오므로, 서비스 하나의 로그를 볼 때는 -u로 유닛 이름을 지정합니다. 유닛 이름 끝의 .service는 생략할 수 있습니다.
journalctl -u crond -n 4Oct 28 06:01:01 server1 CROND[802926]: (root) CMDEND (run-parts /etc/cron.hourly)
Oct 28 07:01:01 server1 CROND[841388]: (root) CMD (run-parts /etc/cron.hourly)
Oct 28 07:01:01 server1 run-parts[841394]: (/etc/cron.hourly) starting 0anacron
Oct 28 07:01:01 server1 CROND[841384]: (root) CMDEND (run-parts /etc/cron.hourly)-u를 두 번 적으면 두 서비스의 로그가 시각 순서대로 섞여 나옵니다. AlmaLinux 서버에서 10월 18일 08:00부터 08:15까지의 crond와 nginx를 함께 고른 결과, 08:01의 crond 줄 넷 뒤에 08:12의 nginx reload 줄 둘이 이어졌습니다.
journalctl -u nginx -u crond --since '2026-10-18 08:00' --until '2026-10-18 08:15'Oct 18 08:01:01 server1 CROND[381522]: (root) CMD (run-parts /etc/cron.hourly)
Oct 18 08:01:01 server1 run-parts[381528]: (/etc/cron.hourly) starting 0anacron
Oct 18 08:01:01 server1 run-parts[381534]: (/etc/cron.hourly) finished 0anacron
Oct 18 08:01:01 server1 CROND[381518]: (root) CMDEND (run-parts /etc/cron.hourly)
Oct 18 08:12:30 server1 systemd[1]: Reloading nginx - high performance web server...
Oct 18 08:12:30 server1 systemd[1]: Reloaded nginx - high performance web server.systemctl status는 서비스 상태 아래에 최근 로그 10줄만 붙여 출력하므로, 그보다 앞선 로그는 journalctl -u로 확인합니다. 서비스를 다시 시작했다면 systemctl restart 바로 다음에 journalctl -u를 실행해 시작 로그를 확인합니다.
스크립트나 크론 작업이 logger로 남긴 로그는 유닛이 아니라 이름표(식별자)로 찾습니다. -t 뒤에는 logger의 -t에 적은 이름을 그대로 적습니다.
logger -t myapp 'journalctl test message'Debian 12 서버에서 logger는 화면에 아무것도 출력하지 않았고, 남긴 줄은 -t myapp으로 찾아 확인했습니다.
journalctl -q -t myappOct 28 07:12:44 server2 myapp[347693]: journalctl test message-g는 메시지에 특정 글자가 들어 있는 줄만 남깁니다. 찾는 글자를 모두 소문자로 적으면 대소문자를 가리지 않습니다.
journalctl -u crond -g anacron -n 2Oct 28 07:01:01 server1 run-parts[841394]: (/etc/cron.hourly) starting 0anacron-n은 -g로 고르기 전의 줄 수를 세므로, crond의 마지막 두 줄 가운데 anacron이 든 한 줄만 남았습니다.
3️⃣ 시간 범위와 부팅별 로그
--since와 --until은 출력할 시간의 시작과 끝을 정합니다. 날짜와 시각 사이에 공백이 있으면 작은따옴표로 감쌉니다.
| --since 값 | 뜻과 쓰는 때 |
|---|---|
| '2026-10-28 06:00' | 그날 06:00:00부터(초를 적지 않으면 00초), 문제가 생긴 시각을 알 때 |
| today | 오늘 00:00:00부터, 오늘 생긴 로그만 볼 때 |
| yesterday | 어제 00:00:00부터 지금까지, 어제 하루만 보려면 --until today를 함께 |
| '-2h' | 2시간 전부터, 방금 생긴 일을 볼 때(아래 실측) |
| '1 hour ago' | 1시간 전부터, -1h와 같은 뜻 |
AlmaLinux 서버에서 최근 2시간은 06:01에 남은 crond 줄부터 시작했고, 아래는 그 가운데 앞 네 줄입니다.
journalctl -u crond --since '-2h' | head -4Oct 28 06:01:01 server1 CROND[802930]: (root) CMD (run-parts /etc/cron.hourly)
Oct 28 06:01:01 server1 run-parts[802936]: (/etc/cron.hourly) starting 0anacron
Oct 28 06:01:01 server1 CROND[802926]: (root) CMDEND (run-parts /etc/cron.hourly)
Oct 28 07:01:01 server1 CROND[841388]: (root) CMD (run-parts /etc/cron.hourly)-b는 현재 부팅 이후의 로그만 남깁니다. 서버가 다시 시작된 원인을 찾을 때는 이전 부팅의 로그가 남아 있는지 부팅 목록부터 확인합니다.
journalctl -b -u crond -n 2Oct 28 07:01:01 server1 run-parts[841394]: (/etc/cron.hourly) starting 0anacron
Oct 28 07:01:01 server1 CROND[841384]: (root) CMDEND (run-parts /etc/cron.hourly)--list-boots는 저널에 남아 있는 부팅마다 번호와 부팅 ID, 첫 줄과 마지막 줄의 시각을 출력합니다.
journalctl --list-bootsIDX BOOT ID FIRST ENTRY LAST ENTRY
0 4f1c2a9be0d34c7a8e6b5d20c1f3a7e9 Sat 2026-10-17 08:29:26 UTC Wed 2026-10-28 07:16:10 UTCAlmaLinux 서버는 저널을 디스크에 두지 않아 부팅 기록이 하나뿐이었습니다. 그래서 이전 부팅을 지정한 -b -1은 안내 문구만 남기고 끝났습니다.
journalctl -b -1Specifying boot ID or boot offset has no effect, no persistent journal was found.이전 부팅의 로그는 저널을 디스크(/var/log/journal)에 저장하는 서버에서만 -b -1로 읽을 수 있습니다.
4️⃣ journalctl 오류 로그와 커널 로그
-p는 로그의 중요도 단계로 줄을 고릅니다. 단계 하나를 적으면 그 단계와 그보다 중요한 단계가 모두 나오고, 단계는 이름과 숫자 어느 쪽으로 적어도 됩니다.
| 단계 | 숫자 | 뜻 |
|---|---|---|
| emerg | 0 | 시스템을 쓸 수 없는 상태 |
| alert | 1 | 바로 조치가 필요한 상태 |
| crit | 2 | 치명적인 오류 |
| err | 3 | 오류 |
| warning | 4 | 경고 |
| notice | 5 | 정상이지만 눈여겨볼 일, -p 없이 logger로 남긴 줄의 단계 |
| info | 6 | 정보 |
| debug | 7 | 디버그 메시지 |
logger로 err 단계 줄을 하나 남긴 뒤 -p err로 고르자, 같은 이름표의 notice 단계 줄(journalctl test message)은 빠지고 err 줄만 남았습니다.
logger -t myapp -p user.err 'journalctl error test'; journalctl -q -t myapp -p errOct 28 07:12:46 server2 myapp[347704]: journalctl error test두 단계를 점 두 개로 이으면 그 범위만 출력합니다. warning..err로 고르면 경고와 오류 단계만 남습니다.
journalctl -q -t myapp -p warning..errOct 28 07:12:46 server2 myapp[347704]: journalctl error test-k는 커널 메시지만 남기고, 현재 부팅 이후의 줄만 출력합니다.
journalctl -k -n 3Oct 26 10:14:25 server1 systemd-rc-local-generator[96245]: /etc/rc.d/rc.local is not marked executable, skipping.
Oct 27 10:47:57 server1 systemd-rc-local-generator[512078]: /etc/rc.d/rc.local is not marked executable, skipping.
Oct 27 11:01:10 server1 systemd-rc-local-generator[520023]: /etc/rc.d/rc.local is not marked executable, skipping.AlmaLinux 서버의 -k 마지막 세 줄은 모두 systemd-rc-local-generator 줄이었습니다. 이 줄은 커널 로그 버퍼로 남긴 메시지라 _TRANSPORT 값이 kernel로 저장되어 -k에도 함께 나옵니다.
5️⃣ journalctl 출력 형식
-o는 한 줄의 형식을 바꿉니다. 기본값 short는 syslog 파일과 거의 같은 형식이고, short-iso는 시각을 ISO 8601 형식으로 바꿔 시간대까지 붙입니다. AlmaLinux 서버에서 short-iso로 바꾸자 시각 끝에 +0000이 붙었습니다.
journalctl -u crond -n 2 -o short-iso2026-10-28T07:01:01+0000 server1 run-parts[841394]: (/etc/cron.hourly) starting 0anacron
2026-10-28T07:01:01+0000 server1 CROND[841384]: (root) CMDEND (run-parts /etc/cron.hourly)cat은 시각과 호스트 이름을 모두 빼고 메시지만 출력하므로, 메시지를 grep이나 다른 프로그램으로 넘길 때 사용합니다.
journalctl -u crond -n 2 -o cat(/etc/cron.hourly) starting 0anacron
(root) CMDEND (run-parts /etc/cron.hourly)json과 json-pretty는 저널에 저장된 필드를 이름과 값으로 출력합니다. --output-fields로 필드를 고르면 커서와 시각, 부팅 ID 필드가 늘 함께 따라옵니다. Debian 12 서버에서 네 필드만 골랐을 때도 __CURSOR와 _BOOT_ID, 두 시각 필드가 함께 나왔습니다.
journalctl -q -t myapp -n 1 -o json-pretty --output-fields=MESSAGE,PRIORITY,SYSLOG_IDENTIFIER,_PID{
"__REALTIME_TIMESTAMP" : "1793171676664200",
"_PID" : "347877",
"SYSLOG_IDENTIFIER" : "myapp",
"MESSAGE" : "follow line 2",
"__CURSOR" : "s=2a6f0c1d9e8b47a3b5c4d3e2f1a0b9c8;i=1a2b3;b=b7e3d1a04c9f4e2a8d6c5b1f0e2a9c47;m=17cf8fe36f5;t=65ee150cf1188;x=1f2e3d4c5b6a7980",
"_BOOT_ID" : "b7e3d1a04c9f4e2a8d6c5b1f0e2a9c47",
"PRIORITY" : "5",
"__MONOTONIC_TIMESTAMP" : "1636264982261"
}6️⃣ 저널 저장 위치와 용량 정리
저널이 메모리에 있는지 디스크에 있는지는 journald.conf의 Storage= 값이 정합니다. 기본값 auto는 /var/log/journal 폴더가 있으면 디스크에, 없으면 메모리(/run/log/journal)에 저장합니다.
AlmaLinux 서버에는 /var/log/journal 폴더가 없어 저널이 /run/log/journal에만 있었습니다.
ls -ld /var/log/journal /run/log/journalls: cannot access '/var/log/journal': No such file or directory
drwxr-sr-x+ 4 root systemd-journal 80 Oct 17 08:30 /run/log/journalDebian 12 서버에는 두 폴더가 모두 있었고, 저널은 디스크에 쌓이고 있었습니다.
ls -ld /var/log/journal /run/log/journaldrwxr-sr-x+ 2 root systemd-journal 40 Oct 9 08:43 /run/log/journal
drwxr-sr-x+ 4 root systemd-journal 4096 Sep 24 12:52 /var/log/journal재부팅 뒤에도 로그를 남기려면 journald.conf의 Storage=를 persistent로 바꾸고 systemd-journald를 다시 시작합니다. 공식 매뉴얼 기준으로 /var/log/journal 폴더는 필요하면 자동으로 만들어집니다. 이 글에서는 설정을 바꾸지 않았습니다.
디스크에 남는 저널은 사고 뒤에 꺼내 읽는 비행기 블랙박스와 같습니다.
--disk-usage는 보관된 저널 파일과 지금 쓰고 있는 파일을 합한 크기를 출력합니다. -q로 맨 위의 [Hint] 안내를 숨긴 Debian 12 서버 일반 계정의 결과는 6.6M 한 줄이었습니다.
journalctl -q --disk-usageArchived and active journals take up 6.6M in the file system.디스크에 저장하는 저널의 최대 크기는 SystemMaxUse=로 정합니다. 값을 적지 않으면 파일 시스템 크기의 10%(최대 4G)가 상한이고, Debian 12 서버의 journald.conf에는 50M이 적혀 있었습니다.
grep -v '^#' /etc/systemd/journald.conf | grep -v '^$'[Journal]
SystemMaxUse=50M오래된 저널을 바로 줄일 때는 --vacuum-size로 남길 크기를, --vacuum-time으로 남길 기간을 정합니다. 두 명령은 저널 파일을 지우므로 이 글에서는 실행하지 않았습니다.
journalctl --vacuum-size=200M--vacuum-size=200M은 보관된 저널 파일을 오래된 것부터 지워 전체 크기를 200M 아래로 줄입니다.
journalctl --vacuum-time=2weeks--vacuum-time=2weeks는 2주보다 오래된 줄만 담은 보관 파일을 지웁니다.
vacuum은 보관된 파일만 지우고 지금 쓰고 있는 파일은 남기므로, 실행한 뒤에도 --disk-usage 숫자가 지정한 크기까지 줄지 않을 수 있습니다.
/var/log 아래 텍스트 로그를 쓰는 rsyslog는 journald와 따로 동작합니다. 그래서 두 로그는 읽는 방법도, 용량을 관리하는 방법도 다릅니다.
| 항목 | journald(journalctl) | rsyslog |
|---|---|---|
| 읽는 방법 | journalctl | cat, less, grep |
| 저장 위치 | /run/log/journal 또는 /var/log/journal | /var/log/messages(RHEL 계열) 또는 /var/log/syslog(Debian 계열) |
| 용량 관리 | journald.conf의 SystemMaxUse 등 | logrotate |
7️⃣ journalctl 명령어 읽기 권한과 옵션
🔲 읽기 권한
root가 아닌 계정으로 journalctl을 실행하면 맨 위에 [Hint] 문구가 뜨고, 그 계정이 남긴 로그만 보입니다. Debian 12 서버의 일반 계정으로 nginx 로그를 찾자 안내 문구 뒤에 [-- No entries --]만 나왔습니다.
journalctl -u nginx -n 5Hint: You are currently not seeing messages from other users and the system.
Users in groups 'adm', 'systemd-journal' can see all messages.
Pass -q to turn off this notice.
-- No entries --id -nG 결과 이 계정이 속한 그룹은 하나뿐이었고, 안내 문구가 말하는 adm이나 systemd-journal 그룹은 없었습니다.
id -nGuser공식 매뉴얼은 systemd-journal, adm, wheel 그룹의 계정이 모든 저널을 읽을 수 있다고 설명합니다. adm과 wheel에는 배포판이 정한 다른 권한이 함께 붙고 wheel은 관리 작업까지 할 수 있는 경우가 많아, 로그만 읽을 계정에는 systemd-journal 그룹이 맞습니다.
usermod -aG systemd-journal user그룹을 추가하는 usermod 명령은 이 글에서 실행하지 않았습니다. 그룹을 추가한 뒤에는 다시 로그인해 id -nG로 그룹을 확인합니다. 관리자 권한이 있는 계정이면 sudo journalctl로 실행해도 모든 로그가 보입니다.
[Hint] 문구는 -q로 숨깁니다. 다만 -q를 붙여도 보이는 로그는 그 계정이 남긴 줄뿐입니다. --user는 그 계정의 사용자 저널을 읽고, 저널을 디스크에 저장하는 서버에서만 동작합니다. 저널을 디스크에 두는 Debian 12 서버에서는 그 계정의 systemd 줄과 logger 줄이 나왔습니다.
journalctl --user -n 3Oct 28 07:12:35 server2 systemd[347665]: Reached target default.target - Main User Target.
Oct 28 07:12:35 server2 systemd[347665]: Startup finished in 181ms.
Oct 28 07:12:44 server2 myapp[347693]: journalctl test message🔲 journalctl 명령어 옵션
📌 주요 옵션: 이 글에서 실행한 결과
| 옵션 | 하는 일 | 이 글에서 본 결과 | |
|---|---|---|---|
| -n 줄 수 | 마지막 몇 줄만 출력, 숫자를 빼면 10줄 | -n 3에 마지막 세 줄이 나옴 | |
| -r | 순서를 뒤집어 최근 줄을 맨 위로 | crond 로그에서 가장 늦게 남은 CMDEND 줄이 맨 위 | |
| -f | 마지막 줄 뒤에 새로 들어오는 줄을 계속 출력 | logger로 남긴 두 줄이 바로 아래 이어짐 | |
| -q | [Hint] 같은 안내 문구를 숨김 | Debian 12 일반 계정의 --disk-usage 결과가 6.6M 한 줄만 남음 | |
| -u 유닛 | 그 서비스의 로그만 출력 | -u를 두 번 적자 crond 줄 넷 뒤에 nginx reload 줄 둘이 시각 순서로 이어짐 | |
| -t 이름표 | logger -t로 남긴 이름표의 로그만 출력 | -t myapp에 logger로 남긴 줄이 나옴 | |
| -g 글자 | 메시지에 그 글자가 든 줄만 출력 | crond 마지막 두 줄 가운데 anacron이 든 한 줄만 남음 | |
| --since, --until | 출력할 시간 범위의 시작과 끝 | --since '-2h'가 06:01에 남은 crond 줄부터 시작 | |
| -b | 현재 부팅 이후의 로그만, -b -1은 이전 부팅 | 저널을 디스크에 두지 않는 AlmaLinux 서버에서 -b -1은 [no persistent journal was found] 안내만 | |
| --list-boots | 저널에 남은 부팅 목록 | AlmaLinux 서버는 부팅 기록이 하나뿐 | |
| -p 단계 | 그 중요도와 그보다 중요한 단계만 출력 | -p err에 notice 줄은 빠지고 err 줄만, warning..err도 같은 한 줄 | |
| -k | 현재 부팅의 커널 메시지만 출력 | 마지막 세 줄이 모두 systemd-rc-local-generator 줄 | |
| -o 형식 | 한 줄의 출력 형식을 바꿈 | short-iso는 시각 끝에 +0000, cat은 메시지만 남음 | |
| --output-fields 필드 | json 출력에서 필드를 고름 | 네 필드만 골라도 __CURSOR와 _BOOT_ID, 두 시각 필드가 함께 나옴 | |
| --disk-usage | 저널 파일 전체가 차지하는 크기를 출력 | Debian 12 서버 일반 계정에서 6.6M | |
| --user | 그 계정의 사용자 저널을 읽음 | Debian 12 서버에서 그 계정의 systemd 줄과 logger 줄이 나옴 | |
| --utc | 시각을 UTC로 출력 | 시간대를 따로 정한 AlmaLinux 서버에서도 crond 로그 시각이 UTC 기준으로 바뀜 | |
| 필드=값 | 그 필드 값을 가진 줄만 출력 | _PID=347704에 logger가 남긴 err 줄 하나만 나옴 |
📎 그 밖의 옵션: 공식 매뉴얼 기준
| 옵션 | 하는 일 | |
|---|---|---|
| --no-pager | less를 거치지 않고 터미널에 바로 출력 | |
| -e, --pager-end | less 화면을 저널 끝에서 열고, -n을 따로 적지 않으면 1000줄 | |
| -x, --catalog | 메시지 카탈로그에 있는 설명 글을 로그 줄에 덧붙임 | |
| -a, --all | 출력할 수 없는 글자가 있거나 아주 긴 필드도 줄이지 않고 출력 | |
| -N, --fields | 저널에서 쓰이는 필드 이름을 모두 출력 | |
| -F, --field= 필드 | 그 필드가 가진 값을 모두 출력 | |
| -D 폴더 | 기본 저널 자리 대신 지정한 폴더의 저널을 읽음 | |
| --file= 파일 | 지정한 저널 파일을 읽음, 여러 번 적을 수 있음 | |
| --vacuum-size= 크기 | 보관된 저널 파일을 오래된 것부터 지워 지정한 크기 아래로 줄임 | |
| --vacuum-time= 기간 | 지정한 기간보다 오래된 줄만 담은 보관 파일을 지움 | |
| --vacuum-files= 개수 | 보관된 저널 파일을 지정한 개수만 남기고 지움 | |
| --rotate | 지금 쓰는 저널 파일을 보관 파일로 돌리고 새 파일을 시작 | |
| --flush | 메모리(/run/log/journal)의 저널을 디스크(/var/log/journal)로 옮김, persistent 저장일 때 |
🔲 journalctl 명령어 시뮬레이터
아래 시뮬레이터에서 최근 로그와 서비스별 로그, 시간 범위, 중요도, 출력 형식을 직접 입력해 확인할 수 있습니다.
🔢 FAQ & 추천 콘텐츠




ℹ️ 제휴 안내
본 사이트의 콘텐츠에는 제휴 링크가 포함되어 있습니다. 방문자가 이 링크를 통해 상품 또는 서비스를 구매하면 본 사이트는 판매처로부터 수수료를 지급받습니다. 이 과정에서 구매자가 지불하는 금액(이벤트 할인 시 금액이 내려갑니다↓)은 오르지 않습니다. 게시된 가격·할인·재고 정보는 작성 시점 기준이며 실제와 다를 수 있으므로, 구매 전 판매처에서 최종 확인하시기 바랍니다. 상품 선정과 평가는 자체 기준에 따라 작성되며, 수수료 지급 여부가 소개 순서나 평가 내용에 영향을 주지 않습니다.



