Showing posts with label ubuntu. Show all posts
Showing posts with label ubuntu. Show all posts

Thursday, August 21, 2025

Ubuntu rsyslog 로그 필터링, DB 저장을 위한 실전 활용법

서버를 운영하다 보면 수많은 로그가 쏟아집니다. 이 로그들은 시스템의 상태를 파악하고, 문제 발생 시 원인을 추적하며, 보안 위협을 감지하는 데 필수적인 정보 자산입니다. 하지만 기본 설정으로는 로그가 텍스트 파일 형태로 /var/log 디렉터리에 흩어져 저장되기 때문에, 특정 정보를 찾거나 통계를 내는 등 의미 있는 데이터로 활용하기가 어렵습니다. 이 문제를 해결하기 위해 등장한 것이 바로 '중앙화된 로그 관리 시스템'입니다.

오늘 우리는 Ubuntu에 기본적으로 설치되어 있는 강력한 로그 처리 시스템인 rsyslog를 활용하여, 단순히 로그를 파일에 저장하는 것을 넘어 원하는 로그만 선별(필터링)하고, 이를 관계형 데이터베이스(MySQL/MariaDB)에 체계적으로 저장하는 방법을 자세히 알아보겠습니다. 이 과정을 통해 여러분은 흩어져 있던 로그를 강력한 데이터 자산으로 바꾸는 첫걸음을 떼게 될 것입니다.

이 글을 끝까지 따라오시면, 여러분은 다음을 할 수 있게 됩니다:

  • rsyslog의 모듈 시스템을 이해하고 DB 연동 모듈을 설치합니다.
  • 로그 저장을 위한 데이터베이스와 사용자 계정을 설정합니다.
  • rsyslog의 기본 및 고급 필터링 규칙(RainerScript)을 사용하여 원하는 로그만 정확히 골라냅니다.
  • 필터링된 로그를 실시간으로 데이터베이스에 삽입하도록 rsyslog를 설정합니다.
  • 설정이 올바르게 동작하는지 확인하고 기본적인 문제를 해결합니다.

이 과정은 단순히 로그를 DB에 넣는 기술적인 방법을 넘어, 대규모 시스템의 로그를 어떻게 효율적으로 관리하고 분석의 기반을 마련할 수 있는지에 대한 통찰을 제공할 것입니다. 이제, 텍스트 파일에 잠자고 있던 로그에 새로운 생명을 불어넣어 보겠습니다.


준비 단계: 필요한 것들 확인하기

본격적인 설정에 앞서, 원활한 진행을 위해 몇 가지 준비가 필요합니다. 아래 항목들이 준비되었는지 확인해주세요.

  1. Ubuntu 서버: Ubuntu 18.04 LTS, 20.04 LTS, 22.04 LTS 또는 그 이상의 버전이 설치된 서버가 필요합니다. 이 가이드는 대부분의 Debian 계열 리눅스에서도 유사하게 적용될 수 있습니다.
  2. Sudo 권한: 패키지를 설치하고 시스템 설정 파일을 수정해야 하므로, sudo 명령을 실행할 수 있는 관리자 권한을 가진 계정이 필요합니다.
  3. 데이터베이스 선택: 이 가이드에서는 가장 널리 사용되는 오픈소스 데이터베이스인 MariaDB를 기준으로 설명합니다. MySQL을 사용하셔도 과정은 거의 동일합니다. PostgreSQL을 사용하고 싶다면 관련 패키지 이름(rsyslog-pgsql)만 바꾸면 됩니다.
  4. 기본적인 리눅스 명령어 지식: apt, systemctl, nano 또는 vim과 같은 텍스트 편집기 사용법 등 기본적인 리눅스 명령어에 익숙하다고 가정합니다.

모든 준비가 되셨다면, 이제 첫 번째 단계인 데이터베이스와 rsyslog 모듈 설치부터 시작하겠습니다.


1단계: 데이터베이스 및 rsyslog 모듈 설치

rsyslog가 로그를 데이터베이스에 보내려면, rsyslog가 데이터베이스와 '대화'할 수 있도록 해주는 '통역사' 역할의 모듈이 필요합니다. MariaDB/MySQL의 경우 rsyslog-mysql이라는 패키지가 이 역할을 합니다. 또한, 로그를 저장할 데이터베이스 서버 자체도 설치해야 합니다.

1.1. MariaDB 서버 설치

이미 데이터베이스 서버가 운영 중이라면 이 단계를 건너뛰셔도 좋습니다. 새로 설치하는 경우, 다음 명령어를 터미널에 입력하여 MariaDB 서버를 설치합니다.

sudo apt update
sudo apt install mariadb-server -y

설치가 완료되면 MariaDB 서비스가 자동으로 시작됩니다. 다음 명령어로 서비스 상태를 확인하여 정상적으로 실행 중인지 확인합니다.

sudo systemctl status mariadb

출력 결과에 active (running)이라는 문구가 보인다면 성공적으로 설치 및 실행된 것입니다.

1.2. rsyslog MySQL 모듈 설치

이제 rsyslog가 MariaDB와 통신할 수 있도록 rsyslog-mysql 패키지를 설치합니다. 이 패키지는 rsyslog의 출력 모듈(Output Module) 중 하나인 ommysql을 제공합니다.

sudo apt install rsyslog-mysql -y

설치가 매우 간단하게 끝납니다. 이 작은 패키지 하나가 rsyslog의 능력을 파일 시스템 너머로 확장시켜주는 핵심 열쇠입니다.


2단계: 로그 저장을 위한 데이터베이스 설정

이제 로그를 저장할 '창고'를 만들어야 합니다. 보안을 위해 rsyslog 전용 데이터베이스와 사용자 계정을 생성하는 것이 좋습니다. 이렇게 하면 rsyslog 계정이 다른 데이터베이스에 영향을 미치는 것을 방지할 수 있습니다.

2.1. MariaDB 접속 및 보안 설정

먼저, root 사용자로 MariaDB에 접속합니다.

sudo mysql -u root

만약 처음 설치했다면, 초기 보안 설정을 진행하는 것이 좋습니다. mysql_secure_installation 스크립트를 실행하여 root 비밀번호 설정, 익명 사용자 제거 등을 수행할 수 있습니다.

sudo mysql_secure_installation

2.2. 데이터베이스 및 사용자 생성

MariaDB 프롬프트(MariaDB [(none)]>)에서 다음 SQL 쿼리를 차례대로 실행하여 rsyslog를 위한 데이터베이스와 사용자를 생성합니다.

1. 데이터베이스 생성: 로그를 저장할 `Syslog`라는 이름의 데이터베이스를 만듭니다.

CREATE DATABASE Syslog CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

2. 사용자 생성 및 권한 부여: `rsyslog_user`라는 사용자를 만들고, 이 사용자가 `Syslog` 데이터베이스에만 접근하여 모든 작업을 할 수 있도록 권한을 부여합니다. `'your-strong-password'` 부분은 반드시 강력한 비밀번호로 변경해주세요.

CREATE USER 'rsyslog_user'@'localhost' IDENTIFIED BY 'your-strong-password';
GRANT ALL PRIVILEGES ON Syslog.* TO 'rsyslog_user'@'localhost';

3. 변경사항 적용: 변경된 권한을 시스템에 즉시 적용합니다.

FLUSH PRIVILEGES;

4. 종료: MariaDB 프롬프트를 빠져나옵니다.

EXIT;

2.3. 로그 테이블 스키마(Schema) 생성

rsyslog는 어떤 구조의 테이블에 로그를 저장해야 할지 미리 약속된 스키마를 가지고 있습니다. 다행히도 rsyslog-mysql 패키지를 설치할 때 이 스키마를 생성해주는 SQL 스크립트 파일이 함께 제공됩니다. 우리는 이 스크립트를 방금 만든 `Syslog` 데이터베이스에 실행하기만 하면 됩니다.

스크립트 파일은 보통 /usr/share/doc/rsyslog-mysql/ 디렉터리에 있습니다. 다음 명령어로 해당 스크립트를 `Syslog` 데이터베이스에 적용합니다.

sudo mysql -u rsyslog_user -p Syslog < /usr/share/doc/rsyslog-mysql/createDB.sql

명령을 실행하면 위에서 설정한 rsyslog_user의 비밀번호를 입력하라는 메시지가 나옵니다. 비밀번호를 정확히 입력하면, 아무런 메시지 없이 명령이 종료됩니다. 이것이 정상입니다.

확인을 위해, `Syslog` 데이터베이스에 어떤 테이블이 생성되었는지 살펴볼 수 있습니다.

sudo mysql -u rsyslog_user -p -e "USE Syslog; SHOW TABLES;"

실행 결과로 SystemEventsSystemEventsProperties 두 개의 테이블이 보인다면, 데이터베이스 준비는 완벽하게 끝난 것입니다. SystemEvents 테이블이 바로 우리의 로그가 차곡차곡 쌓일 곳입니다.


3단계: rsyslog 설정 - 필터링과 DB 연동

이제 가장 핵심적인 단계입니다. rsyslog의 설정 파일을 수정하여, 특정 조건에 맞는 로그만 골라내어 MariaDB로 보내도록 설정할 것입니다. rsyslog의 설정은 /etc/rsyslog.conf 파일과 /etc/rsyslog.d/ 디렉터리에 있는 .conf 파일들로 이루어집니다. 시스템의 기본 설정을 건드리지 않고 유지보수를 용이하게 하기 위해, 우리는 /etc/rsyslog.d/ 디렉터리 안에 새로운 설정 파일을 만드는 방식을 사용할 것입니다.

60-mysql.conf라는 이름으로 새 설정 파일을 생성합니다.

sudo nano /etc/rsyslog.d/60-mysql.conf

이 파일 안에 rsyslog에게 무엇을, 어떻게, 어디로 보낼지 지시하는 내용을 작성할 것입니다.

3.1. 기본 개념: RainerScript

최신 rsyslog는 RainerScript라는 진보된 스크립트 기반의 설정 구문을 사용합니다. 예전의 facility.priority 방식보다 훨씬 더 유연하고 강력한 필터링과 제어가 가능합니다. 우리는 RainerScript를 사용하여 필터링 규칙을 만들 것입니다.

RainerScript의 필터링은 기본적으로 if ... then ... 구조를 따릅니다.

if <조건문> then {
    <수행할 동작>
}

여기서 '조건문'은 로그 메시지의 다양한 속성(프로그램 이름, 호스트 이름, 메시지 내용 등)을 기반으로 만들어지며, '수행할 동작'은 해당 로그를 특정 파일에 저장하거나, 다른 서버로 보내거나, 우리가 하려는 것처럼 데이터베이스에 삽입하는 등의 작업을 정의합니다.

3.2. 설정 파일 작성: 모든 로그를 DB로 보내기 (기본)

먼저 필터링 없이 모든 로그를 DB로 보내는 가장 간단한 설정부터 시작해보겠습니다. 이를 통해 DB 연결이 제대로 작동하는지 확인할 수 있습니다. 60-mysql.conf 파일에 아래 내용을 입력하세요.

# #####################################################################
# ## MySQL/MariaDB 로 로그를 보내기 위한 설정 ##
# #####################################################################

# 1. ommysql 모듈을 로드합니다.
# 이 줄은 rsyslog에게 MySQL 데이터베이스와 통신하는 방법을 알려줍니다.
module(load="ommysql")

# 2. 모든 로그(*)를 대상으로 데이터베이스에 보내는 동작(action)을 정의합니다.
# 형식: *.* action(type="ommysql" server="서버주소" db="데이터베이스이름"
#                  uid="사용자이름" pwd="비밀번호")
#
# 아래 'your-strong-password' 부분은 2단계에서 설정한 DB 비밀번호로 반드시 변경해야 합니다.
action(
    type="ommysql"
    server="127.0.0.1"
    db="Syslog"
    uid="rsyslog_user"
    pwd="your-strong-password"
)

위 설정은 매우 직관적입니다.

  • module(load="ommysql"): MySQL 모듈을 활성화합니다.
  • action(...): 모든 로그(*.*에 해당, 여기서는 필터가 없으므로 모든 로그)에 대해 지정된 동작을 수행하라고 지시합니다.
    • type="ommysql": 동작의 종류가 MySQL DB에 쓰는 것임을 명시합니다.
    • server, db, uid, pwd: 2단계에서 설정한 데이터베이스 연결 정보를 정확하게 입력합니다.

3.3. 설정 파일 작성: 필터링 적용하기 (핵심)

이제 이 가이드의 핵심 주제인 '필터링'을 적용해 보겠습니다. 모든 로그를 DB에 저장하는 것은 엄청난 양의 데이터를 생성하여 저장 공간을 낭비하고, 정작 중요한 정보를 찾기 어렵게 만듭니다. 우리는 특정 조건에 맞는 로그만 DB에 저장하도록 규칙을 추가할 것입니다.

예를 들어, "SSH(sshd) 관련 로그와 커널(kernel) 메시지 중에서 심각도(severity)가 'warning' 이상인 로그만 DB에 저장하고 싶다"는 요구사항이 있다고 가정해 봅시다.

기존 60-mysql.conf 파일의 내용을 아래와 같이 수정하거나 새로 작성합니다.

# #####################################################################
# ## 특정 로그를 필터링하여 MySQL/MariaDB 로 보내기 위한 설정 ##
# #####################################################################

# 1. ommysql 모듈 로드
module(load="ommysql")

# 2. 필터링 규칙 및 DB 저장 액션 정의
# RainerScript의 if-then 구문을 사용합니다.
if ( \
    # 조건 1: 프로그램 이름(programname)이 'sshd' 이거나
    $programname == 'sshd' \
    or \
    # 조건 2: 프로그램 이름(programname)이 'kernel' 이고
    #          로그 심각도(syslogseverity)가 4('warning') 이하인 경우
    #          (심각도는 숫자가 작을수록 높음: 0=emerg, 1=alert, 2=crit, 3=err, 4=warning)
    ($programname == 'kernel' and $syslogseverity <= 4) \
) then {
    # 위의 조건에 맞는 로그에 대해서만 아래의 action을 수행합니다.
    action(
        type="ommysql"
        server="127.0.0.1"
        db="Syslog"
        uid="rsyslog_user"
        pwd="your-strong-password"
    )
    # stop: 이 규칙에 매칭된 로그는 이후의 다른 규칙에서 처리되지 않도록 합니다.
    #       DB 저장 후 /var/log/syslog 등에도 중복 저장되는 것을 막고 싶을 때 유용하지만,
    #       여기서는 기본 로그 파일에도 남겨두기 위해 주석 처리합니다.
    # stop
}

이 설정의 핵심은 if (...) then { ... } 블록입니다.

  • $programname: 로그를 생성한 프로세스/프로그램의 이름을 담고 있는 rsyslog의 내장 변수(속성)입니다.
  • $syslogseverity: 로그의 심각도를 숫자로 나타내는 변수입니다. (0: Emergency, 1: Alert, ..., 6: Informational, 7: Debug)
  • ==, or, and, <=: 일반적인 프로그래밍 언어와 유사한 비교 및 논리 연산자를 사용하여 복잡한 조건을 만들 수 있습니다.
  • action(...): 이제 이 actionif 조건문을 통과한 로그에만 적용됩니다.

더 많은 필터링 예시:

  • 특정 메시지가 포함된 로그만 저장하기 (예: 'Failed password'):
    if $msg contains 'Failed password' then { ... }
  • 특정 호스트에서 온 로그만 저장하기:
    if $hostname == 'web-server-01' then { ... }
  • CRON 작업 로그는 제외하고 저장하기:
    if not ($programname == 'CRON') then { ... }

이처럼 RainerScript를 활용하면 거의 모든 종류의 로그 필터링 시나리오를 구현할 수 있습니다. 여러분의 시스템 환경과 모니터링 목적에 맞게 필터링 조건을 자유롭게 수정하고 조합해보세요.


4단계: 설정 적용 및 검증

설정 파일 작성을 마쳤다면, 이제 rsyslog가 이 새로운 설정을 읽어 들이고 제대로 동작하는지 확인할 차례입니다.

4.1. 설정 파일 문법 검사

설정을 다시 시작하기 전에, 작성한 설정 파일에 문법적인 오류가 없는지 확인하는 것이 좋습니다. 오류가 있는 상태로 서비스를 재시작하면 rsyslog가 비정상적으로 종료될 수 있습니다. 다음 명령어로 문법 검사를 수행합니다.

sudo rsyslogd -N1

만약 "rsyslogd: version ..., config validation run (level 1), master config /etc/rsyslog.conf OK." 와 유사한 메시지가 출력되고 오류가 보이지 않는다면 문법적으로 이상이 없는 것입니다. 오류가 있다면, 오류 메시지가 가리키는 줄 번호와 파일을 확인하여 수정해주세요.

4.2. rsyslog 서비스 재시작

문법 검사를 통과했다면, 변경된 설정을 적용하기 위해 rsyslog 서비스를 재시작합니다.

sudo systemctl restart rsyslog

재시작 후 서비스가 정상적으로 실행 중인지 상태를 확인합니다.

sudo systemctl status rsyslog

active (running) 상태를 확인하고, 혹시라도 에러 로그가 출력되지 않았는지 주의 깊게 살펴봅니다.

4.3. 데이터베이스 확인

가장 확실한 검증 방법은 데이터베이스에 로그가 실제로 쌓이고 있는지 직접 확인하는 것입니다.

필터링 규칙에 맞는 로그를 인위적으로 발생시켜 봅시다. 예를 들어, SSH 접속을 시도하거나(성공 또는 실패) 시스템을 재부팅하여 커널 메시지를 생성할 수 있습니다. 잠시 기다린 후, MariaDB에 접속하여 SystemEvents 테이블의 내용을 조회합니다.

sudo mysql -u rsyslog_user -p

DB에 접속한 후, 다음 쿼리를 실행합니다.

USE Syslog;
SELECT ID, ReceivedAt, FromHost, SysLogTag, Message FROM SystemEvents ORDER BY ID DESC LIMIT 10;

이 쿼리는 가장 최근에 저장된 로그 10개를 보여줍니다. 만약 SSH(sshd)나 커널(kernel) 관련 로그들이 테이블에 나타난다면, 여러분의 설정이 성공적으로 작동하고 있는 것입니다! 만약 데이터가 보이지 않는다면, 다음 문제 해결 단계를 참고하세요.


문제 해결 (Troubleshooting)

설정 후 로그가 DB에 들어오지 않는 경우, 다음 사항들을 점검해보세요.

  1. rsyslog 상태 및 로그 확인: sudo systemctl status rsyslog 또는 sudo journalctl -u rsyslog 명령을 실행하여 rsyslog 자체의 에러 메시지를 확인합니다. "cannot connect to mysql server"와 같은 DB 연결 오류 메시지가 있는지 확인하세요.
  2. DB 접속 정보 확인: 60-mysql.conf 파일에 입력한 데이터베이스 이름, 사용자 이름, 비밀번호, 서버 주소가 정확한지 다시 한 번 확인합니다. 특히 비밀번호 오타가 흔한 실수입니다.
  3. 방화벽 확인: 만약 rsyslog와 데이터베이스가 다른 서버에 있다면, 방화벽(ufw, iptables 등)이 데이터베이스 포트(기본 3306)로의 연결을 허용하고 있는지 확인해야 합니다.
  4. 필터링 조건 확인: 설정한 필터링 조건이 너무 엄격하여 현재 시스템에서 발생하는 로그가 없는 것은 아닌지 확인합니다. 테스트를 위해 잠시 필터링 조건을 제거하고 모든 로그(*.*)를 보내는 설정으로 변경하여 DB 연결 자체에 문제가 없는지 먼저 확인하는 것이 좋은 방법입니다.
  5. SELinux/AppArmor: 드물지만, SELinux나 AppArmor 같은 보안 모듈이 rsyslog의 네트워크 연결을 차단할 수도 있습니다. 관련 로그(/var/log/audit/audit.log 또는 /var/log/syslog)를 확인하여 권한 거부(permission denied) 메시지가 있는지 찾아보세요.

결론 및 다음 단계

축하합니다! 여러분은 이제 Ubuntu 서버에서 발생하는 로그를 실시간으로 필터링하여 데이터베이스에 저장하는 시스템을 성공적으로 구축했습니다. 이로써 여러분은 단순히 텍스트 파일의 나열이었던 로그를, SQL 쿼리를 통해 검색, 정렬, 집계할 수 있는 구조화된 데이터로 변환했습니다. 이는 시스템 모니터링, 보안 분석, 장애 대응 능력을 한 차원 높은 수준으로 끌어올리는 중요한 기반이 됩니다.

여기서 멈추지 마세요. 다음 단계로 나아갈 수 있습니다:

  • 로그 시각화: Grafana, Metabase와 같은 대시보드 도구를 데이터베이스에 연결하여 시간에 따른 에러 발생 추이, 로그인 시도 IP 분포 등 로그 데이터를 시각적으로 분석할 수 있습니다.
  • 고급 템플릿 사용: rsyslog의 템플릿 기능을 사용하면 데이터베이스에 저장되는 로그의 형식을 완전히 커스터마이징할 수 있습니다. 특정 정보만 추출하여 별도의 컬럼에 저장하는 등 고급 활용이 가능합니다.
  • 로그 중앙화 확장: 여러 대의 서버에서 발생하는 로그를 하나의 중앙 rsyslog 서버로 전송하고, 이 중앙 서버가 필터링 후 데이터베이스에 저장하도록 구성하여 전사적인 로그 관리 시스템을 구축할 수 있습니다.

오늘 배운 rsyslog의 필터링과 DB 연동 기능은 시작에 불과합니다. rsyslog는 매우 유연하고 강력한 도구이므로, 공식 문서를 참고하여 여러분의 환경에 맞는 더욱 정교한 로그 관리 파이프라인을 만들어 보시길 바랍니다.

Streamline Ubuntu Logging: Filtering rsyslog to a Database

When you operate a server, you're faced with a deluge of logs. These logs are essential assets for understanding system health, tracing the cause of problems, and detecting security threats. However, in a default setup, logs are scattered as text files in the /var/log directory, making it difficult to search for specific information, generate statistics, or derive meaningful insights. To solve this, the concept of a "centralized logging system" was born.

Today, we will delve into how to use rsyslog, the powerful log processing system that comes pre-installed on Ubuntu, to go beyond simple file storage. We will learn how to selectively filter logs and systematically store them in a relational database (MySQL/MariaDB). Through this process, you will take the first step in transforming your scattered logs into a powerful data asset.

By the time you finish this article, you will be able to:

  • Understand rsyslog's modular system and install the database integration module.
  • Set up a dedicated database and user account for log storage.
  • Use rsyslog's basic and advanced filtering rules (RainerScript) to precisely select the logs you need.
  • Configure rsyslog to insert filtered logs into a database in real-time.
  • Verify that your configuration is working correctly and troubleshoot common issues.

This guide isn't just about the technical steps of putting logs into a DB; it's about providing insight into how you can efficiently manage logs from large-scale systems and build a foundation for analysis. Now, let's breathe new life into the logs sleeping in your text files.


Prerequisites: What You'll Need

Before we dive in, let's ensure you have everything you need for a smooth process.

  1. An Ubuntu Server: You'll need a server running Ubuntu 18.04 LTS, 20.04 LTS, 22.04 LTS, or a newer version. This guide can also be adapted for most Debian-based Linux distributions.
  2. Sudo Privileges: You will need an account with sudo access to install packages and modify system configuration files.
  3. A Database of Choice: This guide will use MariaDB as the example, as it's a widely used open-source database. The process is nearly identical for MySQL. If you prefer PostgreSQL, you'll just need to change the relevant package name (e.g., to rsyslog-pgsql).
  4. Basic Linux Command-Line Knowledge: We'll assume you're comfortable with basic commands like apt, systemctl, and using a text editor such as nano or vim.

If you're all set, let's begin with our first step: installing the database and the rsyslog module.


Step 1: Install the Database and rsyslog Module

For rsyslog to send logs to a database, it needs a "translator" module that allows it to "speak" with the database. For MariaDB/MySQL, a package named rsyslog-mysql fills this role. We also need to install the database server itself to store the logs.

1.1. Install MariaDB Server

If you already have a database server running, you can skip this step. If you're starting fresh, install the MariaDB server by entering the following commands in your terminal:

sudo apt update
sudo apt install mariadb-server -y

Once the installation is complete, the MariaDB service will start automatically. You can confirm it's running correctly with this command:

sudo systemctl status mariadb

If the output includes a line like active (running), the installation and startup were successful.

1.2. Install the rsyslog MySQL Module

Now, let's install the rsyslog-mysql package so rsyslog can communicate with MariaDB. This package provides the ommysql output module.

sudo apt install rsyslog-mysql -y

The installation is quick and straightforward. This single small package is the key that extends rsyslog's capabilities beyond the filesystem.


Step 2: Set Up the Database for Log Storage

Next, we need to create a "warehouse" for our logs. For security purposes, it's a best practice to create a dedicated database and user for rsyslog. This prevents the rsyslog user from affecting other databases on the server.

2.1. Connect to MariaDB and Secure It

First, log in to MariaDB as the root user.

sudo mysql -u root

If this is a new installation, it's highly recommended to run the security script. The mysql_secure_installation script will guide you through setting a root password, removing anonymous users, and more.

sudo mysql_secure_installation

2.2. Create the Database and User

From the MariaDB prompt (MariaDB [(none)]>), execute the following SQL queries to create a database and a user for rsyslog.

1. Create the database: We'll create a database named `Syslog` to store the logs.

CREATE DATABASE Syslog CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

2. Create a user and grant privileges: We'll create a user named `rsyslog_user` and give it full permissions on the `Syslog` database only. Be sure to replace `'your-strong-password'` with a real, strong password.

CREATE USER 'rsyslog_user'@'localhost' IDENTIFIED BY 'your-strong-password';
GRANT ALL PRIVILEGES ON Syslog.* TO 'rsyslog_user'@'localhost';

3. Apply changes: Flush the privileges to apply the changes immediately.

FLUSH PRIVILEGES;

4. Exit: Leave the MariaDB prompt.

EXIT;

2.3. Create the Log Table Schema

rsyslog expects a specific table structure to store logs. Fortunately, the rsyslog-mysql package includes a SQL script to create this predefined schema. All we have to do is execute this script on the `Syslog` database we just created.

The script file is typically located in the /usr/share/doc/rsyslog-mysql/ directory. Use the following command to apply it to the `Syslog` database.

sudo mysql -u rsyslog_user -p Syslog < /usr/share/doc/rsyslog-mysql/createDB.sql

You will be prompted for the password for the `rsyslog_user` you set earlier. Enter it correctly. The command should complete without any output, which is normal.

To verify, you can check which tables were created in the `Syslog` database.

sudo mysql -u rsyslog_user -p -e "USE Syslog; SHOW TABLES;"

If the output shows two tables, SystemEvents and SystemEventsProperties, your database setup is complete. The SystemEvents table is where all your logs will be stored.


Step 3: Configure rsyslog - Filtering and DB Integration

This is the most critical step. We will modify rsyslog's configuration to filter logs based on specific criteria and send the matching ones to our MariaDB database. rsyslog's configuration is managed through /etc/rsyslog.conf and files ending in .conf within the /etc/rsyslog.d/ directory. To keep the main system configuration clean and make maintenance easier, we'll create a new configuration file in the /etc/rsyslog.d/ directory.

Let's create a new file named 60-mysql.conf.

sudo nano /etc/rsyslog.d/60-mysql.conf

Inside this file, we will write instructions telling rsyslog what to send, how to send it, and where to send it.

3.1. Core Concept: RainerScript

Modern versions of rsyslog use an advanced, script-based configuration syntax called RainerScript. It offers far more flexibility and power for filtering and control than the older facility.priority format. We will use RainerScript to create our filtering rules.

Filtering in RainerScript generally follows an if ... then ... structure.

if <condition> then {
    <action to perform>
}

The 'condition' is built based on various properties of a log message (e.g., program name, hostname, message content), and the 'action' defines what to do with that log, such as saving it to a file, forwarding it to another server, or, in our case, inserting it into a database.

3.2. Configuration: Sending All Logs to the DB (Basic)

First, let's start with the simplest configuration: sending all logs to the database without any filtering. This will help us confirm that the database connection is working correctly. Enter the following content into your 60-mysql.conf file.

# #####################################################################
# ## Configuration to send logs to MySQL/MariaDB ##
# #####################################################################

# 1. Load the ommysql module.
# This line tells rsyslog how to communicate with a MySQL database.
module(load="ommysql")

# 2. Define an action to send all logs (*) to the database.
# Format: *.* action(type="ommysql" server="server_address" db="database_name"
#                  uid="username" pwd="password")
#
# IMPORTANT: Replace 'your-strong-password' below with the actual DB password you set in Step 2.
action(
    type="ommysql"
    server="127.0.0.1"
    db="Syslog"
    uid="rsyslog_user"
    pwd="your-strong-password"
)

This configuration is quite intuitive:

  • module(load="ommysql"): Activates the MySQL module.
  • action(...): Instructs rsyslog to perform the specified action for all logs (implied since there's no filter).
    • type="ommysql": Specifies that the action is to write to a MySQL DB.
    • server, db, uid, pwd: You must enter the exact database connection details you configured in Step 2.

3.3. Configuration: Applying Filters (The Core Task)

Now, let's implement the core topic of this guide: filtering. Storing every single log in the database generates a massive amount of data, wastes storage, and makes it harder to find important information. We will add rules to store only the logs that meet specific criteria.

For example, let's say our requirement is: "I want to store only SSH (sshd) logs and kernel messages with a severity of 'warning' or higher in the database."

Modify or replace the content of your 60-mysql.conf file with the following:

# #####################################################################
# ## Configuration to filter logs and send them to MySQL/MariaDB ##
# #####################################################################

# 1. Load the ommysql module
module(load="ommysql")

# 2. Define filtering rules and the DB storage action
# We use the RainerScript if-then syntax.
if ( \
    # Condition 1: If the program name is 'sshd'
    $programname == 'sshd' \
    or \
    # Condition 2: If the program name is 'kernel' AND
    #              the log severity (syslogseverity) is 4 ('warning') or less
    #              (Severity is numeric, lower numbers are more severe: 0=emerg, 1=alert, 2=crit, 3=err, 4=warning)
    ($programname == 'kernel' and $syslogseverity <= 4) \
) then {
    # The action below will only be executed for logs that match the above conditions.
    action(
        type="ommysql"
        server="127.0.0.1"
        db="Syslog"
        uid="rsyslog_user"
        pwd="your-strong-password"
    )
    # The 'stop' command prevents this log from being processed by any subsequent rules.
    # This can be useful to prevent duplicate logging (e.g., to both DB and /var/log/syslog).
    # We'll keep it commented out to ensure logs are still written to default files.
    # stop
}

The core of this configuration is the if (...) then { ... } block:

  • $programname: An internal rsyslog variable (property) that holds the name of the process/program that generated the log.
  • $syslogseverity: A variable representing the log's severity as a number (0: Emergency, 1: Alert, ..., 6: Informational, 7: Debug).
  • ==, or, and, <=: You can use familiar comparison and logical operators, just like in a programming language, to build complex conditions.
  • action(...): This action is now conditional and will only apply to logs that pass the if statement.

More Filtering Examples:

  • Store only logs containing a specific message (e.g., 'Failed password'):
    if $msg contains 'Failed password' then { ... }
  • Store only logs from a specific host:
    if $hostname == 'web-server-01' then { ... }
  • Store everything except CRON job logs:
    if not ($programname == 'CRON') then { ... }

As you can see, RainerScript allows you to implement almost any log filtering scenario imaginable. Feel free to modify and combine conditions to fit your system's environment and monitoring goals.


Step 4: Apply and Verify the Configuration

Once you've finished writing the configuration file, it's time to make rsyslog read the new settings and verify that everything is working as expected.

4.1. Check Configuration Syntax

Before restarting the service, it's a good practice to check your configuration file for syntax errors. Restarting with a broken config could cause rsyslog to fail. Run the following command to perform a syntax check:

sudo rsyslogd -N1

If you see a message like "rsyslogd: version ..., config validation run (level 1), master config /etc/rsyslog.conf OK." and no errors, your syntax is correct. If there are errors, the message will point to the file and line number that needs fixing.

4.2. Restart the rsyslog Service

With the syntax check passed, restart the rsyslog service to apply the new configuration.

sudo systemctl restart rsyslog

After restarting, check the service's status to ensure it's running correctly.

sudo systemctl status rsyslog

Look for the active (running) state and carefully check for any error messages in the output.

4.3. Check the Database

The most definitive way to verify your setup is to check if logs are actually appearing in the database.

Try to generate some logs that match your filter rules. For instance, attempt an SSH login (either successful or failed) or reboot the system to generate kernel messages. After waiting a moment, connect to MariaDB and query the SystemEvents table.

sudo mysql -u rsyslog_user -p

Once connected to the DB, run the following query:

USE Syslog;
SELECT ID, ReceivedAt, FromHost, SysLogTag, Message FROM SystemEvents ORDER BY ID DESC LIMIT 10;

This query displays the 10 most recently stored logs. If you see logs related to SSH (sshd) or the kernel in the table, your configuration is working successfully! If you don't see any data, refer to the troubleshooting section below.


Troubleshooting

If logs aren't appearing in the database after configuration, check the following:

  1. Check rsyslog Status and Logs: Run sudo systemctl status rsyslog or sudo journalctl -u rsyslog to check for error messages from rsyslog itself. Look for messages about DB connection failures, like "cannot connect to mysql server."
  2. Verify DB Connection Info: Double-check that the database name, username, password, and server address in your 60-mysql.conf file are perfectly correct. A typo in the password is a very common mistake.
  3. Check Firewall: If rsyslog and the database are on different servers, ensure that the firewall (e.g., ufw, iptables) is allowing connections on the database port (default 3306).
  4. Check Filter Conditions: Make sure your filter conditions are not too strict, which might result in no logs currently matching them. For testing, you can temporarily remove the filter condition and use a simple all-logs (*.*) configuration to first confirm if the DB connection itself is the issue.
  5. SELinux/AppArmor: In rare cases, security modules like SELinux or AppArmor might be blocking rsyslog's network connections. Check the relevant logs (/var/log/audit/audit.log or /var/log/syslog) for permission denied messages.

Conclusion and Next Steps

Congratulations! You have successfully built a system to filter logs in real-time on your Ubuntu server and store them in a database. You've transformed what was once a mere list of text files into structured data that can be queried, sorted, and aggregated using SQL. This is a critical foundation for elevating your system monitoring, security analysis, and incident response capabilities to the next level.

But don't stop here. You can take this even further:

  • Log Visualization: Connect dashboard tools like Grafana or Metabase to your database to visually analyze your log data. You can create charts for error trends over time, maps of login attempt IPs, and more.
  • Use Advanced Templates: rsyslog's templating feature allows you to completely customize the format of logs stored in the database. This enables advanced use cases, like extracting specific information into separate columns.
  • Expand to Centralized Logging: Configure multiple servers to forward their logs to a central rsyslog server. This central server can then handle the filtering and database insertion, creating an enterprise-wide log management system.

The filtering and DB integration features of rsyslog you've learned today are just the beginning. rsyslog is an incredibly flexible and powerful tool. I encourage you to explore the official documentation and build even more sophisticated log management pipelines tailored to your specific environment.

Ubuntu rsyslog徹底活用:ログをフィルタリングしてデータベースに格納する

サーバーを運用していると、無数のログが絶え間なく生成されます。これらのログは、システムの健全性を把握し、問題発生時の原因を追跡し、セキュリティの脅威を検出するための不可欠な情報資産です。しかし、デフォルト設定のままでは、ログはテキストファイルとして/var/logディレクトリに散在して保存されるため、特定の情報を検索したり、統計を取ったりといった、意味のあるデータとして活用することは困難です。この問題を解決するために登場したのが、「集中ログ管理システム」という考え方です。

本記事では、Ubuntuに標準でインストールされている強力なログ処理システムであるrsyslogを活用し、単にログをファイルに保存するレベルを超え、必要なログだけを選別(フィルタリング)し、それをリレーショナルデータベース(MySQL/MariaDB)に体系的に保存する方法を詳しく解説します。このプロセスを通じて、あなたは散在していたログを強力なデータ資産に変える第一歩を踏み出すことになります。

この記事を最後まで読めば、以下のことができるようになります:

  • rsyslogのモジュールシステムを理解し、DB連携モジュールをインストールする。
  • ログ保存用のデータベースとユーザーアカウントを設定する。
  • rsyslogの基本および高度なフィルタリングルール(RainerScript)を使い、目的のログだけを正確に抽出する。
  • フィルタリングしたログをリアルタイムでデータベースに挿入するようrsyslogを設定する。
  • 設定が正しく動作しているかを確認し、基本的な問題をトラブルシューティングする。

このプロセスは、単にログをDBに入れる技術的な手順だけでなく、大規模システムのログをいかに効率的に管理し、分析のための基盤をどう構築するかという洞察を提供します。さあ、テキストファイルの中で眠っているログに、新たな命を吹き込みましょう。


準備:必要なものの確認

本格的な設定に入る前に、円滑な進行のためにいくつかの準備が必要です。以下の項目が揃っているか確認してください。

  1. Ubuntuサーバー:Ubuntu 18.04 LTS, 20.04 LTS, 22.04 LTSまたはそれ以降のバージョンがインストールされたサーバー。このガイドは、ほとんどのDebian系Linuxディストリビューションでも同様に適用可能です。
  2. Sudo権限:パッケージのインストールやシステム設定ファイルの編集が必要なため、sudoコマンドを実行できる管理者権限を持つアカウントが必要です。
  3. データベースの選択:このガイドでは、最も広く利用されているオープンソースデータベースであるMariaDBを基準に説明します。MySQLを使用する場合も、手順はほぼ同じです。PostgreSQLを使用したい場合は、関連パッケージ名(rsyslog-pgsql)を変更するだけで対応できます。
  4. 基本的なLinuxコマンドの知識apt, systemctl, テキストエディタ(nanovim)の使用法など、基本的なLinuxコマンドに慣れていることを前提とします。

すべての準備が整ったら、最初のステップであるデータベースとrsyslogモジュールのインストールから始めましょう。


ステップ1:データベースとrsyslogモジュールのインストール

rsyslogがログをデータベースに送信するには、rsyslogがデータベースと「対話」するための「通訳者」の役割を果たすモジュールが必要です。MariaDB/MySQLの場合、rsyslog-mysqlというパッケージがこの役割を担います。また、ログを保存するデータベースサーバー自体もインストールする必要があります。

1.1. MariaDBサーバーのインストール

すでにデータベースサーバーが稼働している場合は、このステップをスキップしてください。新規にインストールする場合は、次のコマンドをターミナルに入力してMariaDBサーバーをインストールします。

sudo apt update
sudo apt install mariadb-server -y

インストールが完了すると、MariaDBサービスは自動的に起動します。次のコマンドでサービスのステータスを確認し、正常に実行中であることを確認します。

sudo systemctl status mariadb

出力結果にactive (running)という文字列が表示されれば、インストールと起動は成功です。

1.2. rsyslog MySQLモジュールのインストール

次に、rsyslogがMariaDBと通信できるように、rsyslog-mysqlパッケージをインストールします。このパッケージは、rsyslogの出力モジュール(Output Module)の一つであるommysqlを提供します。

sudo apt install rsyslog-mysql -y

インストールは非常に簡単です。この小さなパッケージ一つが、rsyslogの能力をファイルシステムの枠を超えて拡張させる鍵となります。


ステップ2:ログ保存用データベースの設定

次に、ログを保存するための「倉庫」を作成します。セキュリティ上、rsyslog専用のデータベースとユーザーアカウントを作成することが推奨されます。これにより、rsyslogアカウントが他のデータベースに影響を与えるのを防ぐことができます。

2.1. MariaDBへの接続とセキュリティ設定

まず、rootユーザーとしてMariaDBに接続します。

sudo mysql -u root

初めてインストールした場合は、初期セキュリティ設定を行うことを強くお勧めします。mysql_secure_installationスクリプトを実行し、rootパスワードの設定や匿名ユーザーの削除などを行います。

sudo mysql_secure_installation

2.2. データベースとユーザーの作成

MariaDBプロンプト(MariaDB [(none)]>)で、以下のSQLクエリを順に実行し、rsyslog用のデータベースとユーザーを作成します。

1. データベースの作成: ログを保存するための`Syslog`という名前のデータベースを作成します。

CREATE DATABASE Syslog CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

2. ユーザーの作成と権限付与: `rsyslog_user`というユーザーを作成し、このユーザーが`Syslog`データベースに対してのみ全ての操作を行えるよう権限を付与します。`'your-strong-password'`の部分は、必ず強力なパスワードに変更してください。

CREATE USER 'rsyslog_user'@'localhost' IDENTIFIED BY 'your-strong-password';
GRANT ALL PRIVILEGES ON Syslog.* TO 'rsyslog_user'@'localhost';

3. 変更の適用: 変更した権限をシステムに即時反映させます。

FLUSH PRIVILEGES;

4. 終了: MariaDBプロンプトを終了します。

EXIT;

2.3. ログテーブルスキーマの作成

rsyslogは、どのような構造のテーブルにログを保存すべきか、あらかじめ定義されたスキーマを持っています。幸いなことに、rsyslog-mysqlパッケージをインストールすると、このスキーマを作成するためのSQLスクリプトファイルが一緒に提供されます。私たちは、このスクリプトを先ほど作成した`Syslog`データベースで実行するだけです。

スクリプトファイルは通常/usr/share/doc/rsyslog-mysql/ディレクトリにあります。次のコマンドで、このスクリプトを`Syslog`データベースに適用します。

sudo mysql -u rsyslog_user -p Syslog < /usr/share/doc/rsyslog-mysql/createDB.sql

コマンドを実行すると、上で設定した`rsyslog_user`のパスワードを尋ねられます。パスワードを正確に入力すると、何もメッセージが表示されずにコマンドが終了します。これが正常な状態です。

確認のために、`Syslog`データベースにどのようなテーブルが作成されたかを見てみましょう。

sudo mysql -u rsyslog_user -p -e "USE Syslog; SHOW TABLES;"

実行結果としてSystemEventsSystemEventsPropertiesという2つのテーブルが表示されれば、データベースの準備は完璧に完了です。SystemEventsテーブルが、私たちのログがこれから積み重ねられていく場所となります。


ステップ3:rsyslogの設定 - フィルタリングとDB連携

ここが最も重要なステップです。rsyslogの設定ファイルを編集し、特定の条件に合致するログだけをフィルタリングしてMariaDBに送信するように設定します。rsyslogの設定は/etc/rsyslog.confファイルと/etc/rsyslog.d/ディレクトリ内の.confファイル群で構成されています。システムの基本設定を汚さず、メンテナンスを容易にするため、私たちは/etc/rsyslog.d/ディレクトリ内に新しい設定ファイルを作成する方法を採用します。

60-mysql.confという名前で新しい設定ファイルを作成します。

sudo nano /etc/rsyslog.d/60-mysql.conf

このファイルの中に、rsyslogに対して何を、どのように、どこへ送るかを指示する内容を記述していきます。

3.1. 基本概念:RainerScript

最新のrsyslogは、RainerScriptという先進的なスクリプトベースの設定構文を使用します。これは旧来のfacility.priority形式よりもはるかに柔軟で強力なフィルタリングと制御を可能にします。私たちはこのRainerScriptを使ってフィルタリングルールを作成します。

RainerScriptのフィルタリングは、基本的にif ... then ...という構造に従います。

if <条件文> then {
    <実行するアクション>
}

ここで「条件文」はログメッセージの様々なプロパティ(プログラム名、ホスト名、メッセージ内容など)に基づいて作られ、「実行するアクション」は、該当するログを特定のファイルに保存したり、別のサーバーに転送したり、あるいは私たちがこれから行うようにデータベースに挿入したりする操作を定義します。

3.2. 設定ファイルの作成:全てのログをDBに送信(基本)

まず、フィルタリングなしで全てのログをDBに送信する最も簡単な設定から始めます。これにより、DB接続が正しく機能するかどうかを確認できます。60-mysql.confファイルに以下の内容を入力してください。

# #####################################################################
# ## MySQL/MariaDBへログを送信するための設定 ##
# #####################################################################

# 1. ommysqlモジュールをロードします。
# この行は、rsyslogにMySQLデータベースとの通信方法を教えます。
module(load="ommysql")

# 2. 全てのログ(*)を対象にデータベースへ送信するアクション(action)を定義します。
# 書式: *.* action(type="ommysql" server="サーバーアドレス" db="データベース名"
#                  uid="ユーザー名" pwd="パスワード")
#
# 下記の'your-strong-password'の部分は、ステップ2で設定したDBパスワードに必ず変更してください。
action(
    type="ommysql"
    server="127.0.0.1"
    db="Syslog"
    uid="rsyslog_user"
    pwd="your-strong-password"
)

上記の設定は非常に直感的です。

  • module(load="ommysql"): MySQLモジュールを有効化します。
  • action(...): 全てのログ(ここではフィルタがないため*.*に相当)に対して指定されたアクションを実行するよう指示します。
    • type="ommysql": アクションの種類がMySQL DBへの書き込みであることを明記します。
    • server, db, uid, pwd: ステップ2で設定したデータベース接続情報を正確に入力します。

3.3. 設定ファイルの作成:フィルタリングの適用(核心)

いよいよ、このガイドの核心テーマである「フィルタリング」を適用します。全てのログをDBに保存すると、膨大な量のデータを生成し、ストレージを浪費するだけでなく、本当に重要な情報を見つけにくくしてしまいます。特定の条件に合致するログだけをDBに保存するようにルールを追加しましょう。

例えば、「SSH(sshd)関連のログと、カーネル(kernel)メッセージのうち、重要度(severity)が'warning'以上のログだけをDBに保存したい」という要件があるとします。

既存の60-mysql.confファイルの内容を以下のように修正または新規作成します。

# #####################################################################
# ## 特定のログをフィルタリングしてMySQL/MariaDBへ送信するための設定 ##
# #####################################################################

# 1. ommysqlモジュールのロード
module(load="ommysql")

# 2. フィルタリングルールとDB保存アクションの定義
# RainerScriptのif-then構文を使用します。
if ( \
    # 条件1: プログラム名(programname)が'sshd'である、または
    $programname == 'sshd' \
    or \
    # 条件2: プログラム名(programname)が'kernel'であり、かつ
    #          ログの重要度(syslogseverity)が4('warning')以下の場合
    #          (重要度は数字が小さいほど高い: 0=emerg, 1=alert, 2=crit, 3=err, 4=warning)
    ($programname == 'kernel' and $syslogseverity <= 4) \
) then {
    # 上記の条件に合致したログに対してのみ、以下のアクションを実行します。
    action(
        type="ommysql"
        server="127.0.0.1"
        db="Syslog"
        uid="rsyslog_user"
        pwd="your-strong-password"
    )
    # stop: このルールにマッチしたログは、これ以降の他のルールでは処理されません。
    #       DB保存後に/var/log/syslogなどにも重複して保存されるのを防ぎたい場合に便利ですが、
    #       ここではデフォルトのログファイルにも残すため、コメントアウトしておきます。
    # stop
}

この設定の核心はif (...) then { ... }ブロックです。

  • $programname: ログを生成したプロセス/プログラムの名前を保持するrsyslogの組み込み変数(プロパティ)です。
  • $syslogseverity: ログの重要度を数値で表す変数です。(0: Emergency, 1: Alert, ..., 6: Informational, 7: Debug)
  • ==, or, and, <=: 一般的なプログラミング言語と同様の比較演算子や論理演算子を使い、複雑な条件式を作成できます。
  • action(...): このactionは、ifの条件文を通過したログにのみ適用されるようになります。

その他のフィルタリング例:

  • 特定のメッセージを含むログだけを保存する(例: 'Failed password'):
    if $msg contains 'Failed password' then { ... }
  • 特定のホストからのログだけを保存する:
    if $hostname == 'web-server-01' then { ... }
  • CRONジョブのログを除外して保存する:
    if not ($programname == 'CRON') then { ... }

このように、RainerScriptを活用すれば、ほとんどあらゆる種類のログフィルタリングシナリオを実装できます。あなたのシステム環境と監視目的に合わせて、フィルタリング条件を自由自在に修正・組み合わせてみてください。


ステップ4:設定の適用と検証

設定ファイルの作成が完了したら、次はこの新しい設定をrsyslogに読み込ませ、意図通りに動作するかを確認する番です。

4.1. 設定ファイルの構文チェック

サービスを再起動する前に、作成した設定ファイルに文法的な誤りがないか確認することをお勧めします。エラーがある状態でサービスを再起動すると、rsyslogが異常終了する可能性があります。次のコマンドで構文チェックを実行します。

sudo rsyslogd -N1

もし「rsyslogd: version ..., config validation run (level 1), master config /etc/rsyslog.conf OK.」のようなメッセージが表示され、エラーが見当たらなければ、構文は正常です。エラーが表示された場合は、エラーメッセージが指し示すファイルと行番号を確認して修正してください。

4.2. rsyslogサービスの再起動

構文チェックをパスしたら、変更した設定を適用するためにrsyslogサービスを再起動します。

sudo systemctl restart rsyslog

再起動後、サービスが正常に実行されているかステータスを確認します。

sudo systemctl status rsyslog

active (running)の状態であることを確認し、エラーログが出力されていないか注意深く確認してください。

4.3. データベースの確認

最も確実な検証方法は、データベースにログが実際に蓄積されているかを直接確認することです。

フィルタリングルールに合致するようなログを意図的に発生させてみましょう。例えば、SSH接続を試みたり(成功・失敗問わず)、システムを再起動してカーネルメッセージを生成させたりします。少し待ってから、MariaDBに接続し、SystemEventsテーブルの内容を照会します。

sudo mysql -u rsyslog_user -p

DBに接続後、次のクエリを実行します。

USE Syslog;
SELECT ID, ReceivedAt, FromHost, SysLogTag, Message FROM SystemEvents ORDER BY ID DESC LIMIT 10;

このクエリは、直近に保存されたログ10件を表示します。もしSSH(sshd)やカーネル(kernel)関連のログがテーブルに表示されれば、あなたの設定は成功です!データが表示されない場合は、次のトラブルシューティングのセクションを参考にしてください。


トラブルシューティング

設定後にログがDBに届かない場合、以下の点を確認してみてください。

  1. rsyslogのステータスとログの確認: sudo systemctl status rsyslogまたはsudo journalctl -u rsyslogコマンドを実行し、rsyslog自体のエラーメッセージを確認します。「cannot connect to mysql server」のようなDB接続エラーメッセージがないか探してください。
  2. DB接続情報の確認: 60-mysql.confファイルに入力したデータベース名、ユーザー名、パスワード、サーバーアドレスが正確か再度確認します。特にパスワードのタイプミスはよくある間違いです。
  3. ファイアウォールの確認: rsyslogとデータベースが別々のサーバーにある場合、ファイアウォール(ufw, iptablesなど)がデータベースのポート(デフォルトは3306)への接続を許可しているか確認する必要があります。
  4. フィルタリング条件の確認: 設定したフィルタリング条件が厳しすぎて、現在システムで発生しているログが一つもマッチしていない可能性はないか確認します。テストのため、一時的にフィルタリング条件を外し、全てのログ(*.*)を送信する設定に変更して、DB接続自体に問題がないかをまず確認するのが良い方法です。
  5. SELinux/AppArmor: 稀なケースですが、SELinuxやAppArmorのようなセキュリティモジュールがrsyslogのネットワーク接続をブロックしている可能性があります。関連ログ(/var/log/audit/audit.log/var/log/syslog)を確認し、権限拒否(permission denied)メッセージがないか探してみてください。

結論と次のステップ

おめでとうございます!これであなたは、Ubuntuサーバーで発生するログをリアルタイムでフィルタリングし、データベースに保存するシステムを構築することに成功しました。これにより、単なるテキストファイルの羅列だったログを、SQLクエリを通じて検索、ソート、集計が可能な構造化データへと変換しました。これは、システム監視、セキュリティ分析、障害対応能力を一段高いレベルへと引き上げる重要な基盤となります。

ここで立ち止まらないでください。次のステップに進むことができます:

  • ログの可視化: GrafanaやMetabaseのようなダッシュボードツールをデータベースに接続し、時間経過に伴うエラー発生の推移、ログイン試行IPの分布など、ログデータを視覚的に分析できます。
  • 高度なテンプレートの使用: rsyslogのテンプレート機能を使えば、データベースに保存されるログの形式を完全にカスタマイズできます。特定の情報だけを抽出して別のカラムに保存するなど、高度な活用が可能です。
  • ログ集中管理の拡張: 複数台のサーバーで発生するログを一台の集中rsyslogサーバーに転送し、この中央サーバーがフィルタリングとデータベースへの保存を行うように構成することで、全社的なログ管理システムを構築できます。

今日学んだrsyslogのフィルタリングとDB連携機能は、ほんの始まりに過ぎません。rsyslogは非常に柔軟で強力なツールです。公式ドキュメントを参考に、あなたの環境に合わせた、より洗練されたログ管理パイプラインを構築してみてください。

精通 Ubuntu rsyslog:日志过滤与数据库集成实战

在服务器运维工作中,我们每天都会面对海量的日志。这些日志是理解系统健康状况、追溯问题根源、检测安全威胁的宝贵信息资产。然而,在默认配置下,日志以纯文本文件的形式散落在/var/log目录中,这使得查找特定信息、进行统计分析或从中提取有价值的数据变得异常困难。为了解决这一难题,“集中式日志管理系统”应运而生。

今天,我们将深入探讨如何利用Ubuntu系统内置的强大日志处理工具rsyslog,实现超越传统文件存储的日志管理方式。我们将学习如何精确筛选(过滤)我们关心的日志,并将其系统性地存入关系型数据库(如MySQL/MariaDB)。通过这一过程,您将迈出将零散日志转变为强大数据资产的第一步。

读完本文,您将能够:

  • 理解 rsyslog 的模块化系统,并安装数据库集成模块。
  • 为日志存储建立专用的数据库和用户账户。
  • 使用 rsyslog 的基础及高级过滤规则(RainerScript),精准捕获所需日志。
  • 配置 rsyslog,将过滤后的日志实时插入数据库。
  • 验证配置是否生效,并掌握常见问题的排查方法。

本指南不仅是关于如何将日志存入数据库的技术教程,更旨在提供一种思路:如何高效管理大规模系统中的日志,并为未来的数据分析奠定坚实基础。现在,让我们一起唤醒那些沉睡在文本文件中的日志数据吧!


准备工作:确认必备环境

在开始配置之前,请确保您已具备以下条件,以保证过程顺利。

  1. 一台Ubuntu服务器:需要一台安装了Ubuntu 18.04 LTS、20.04 LTS、22.04 LTS或更新版本的服务器。本指南内容也基本适用于其他Debian系的Linux发行版。
  2. Sudo权限:您需要一个拥有sudo权限的账户,以便安装软件包和修改系统配置文件。
  3. 选定的数据库:本指南将以广泛使用的开源数据库MariaDB为例进行讲解。如果您使用MySQL,操作步骤几乎完全相同。若希望使用PostgreSQL,只需将相关软件包名称(如rsyslog-pgsql)做相应替换即可。
  4. 基础Linux命令行知识:我们假定您已熟悉aptsystemctl等基本命令,并会使用nanovim等文本编辑器。

一切就绪后,让我们从第一步开始:安装数据库及rsyslog相关模块。


第一步:安装数据库与rsyslog模块

为了让rsyslog能将日志发送到数据库,它需要一个“翻译官”——一个能让它与数据库“对话”的模块。对于MariaDB/MySQL,这个角色由名为rsyslog-mysql的软件包扮演。同时,我们也需要安装用于存储日志的数据库服务器本身。

1.1. 安装MariaDB服务器

如果您的服务器上已经运行着数据库,可以跳过此步骤。如果是全新安装,请在终端中输入以下命令来安装MariaDB服务器:

sudo apt update
sudo apt install mariadb-server -y

安装完成后,MariaDB服务会自动启动。您可以通过以下命令检查其运行状态:

sudo systemctl status mariadb

如果输出信息中包含active (running)字样,说明安装和启动都已成功。

1.2. 安装rsyslog的MySQL模块

现在,安装rsyslog-mysql软件包,使rsyslog具备与MariaDB通信的能力。该软件包提供了rsyslog的一个重要输出模块(Output Module)——ommysql

sudo apt install rsyslog-mysql -y

安装过程非常迅速。就是这个小小的软件包,为rsyslog赋予了超越文件系统的强大扩展能力。


第二步:为日志存储配置数据库

接下来,我们需要为日志创建一个“仓库”。出于安全考虑,最佳实践是为rsyslog创建一个专用的数据库和用户。这样可以有效隔离权限,防止rsyslog账户影响到服务器上的其他数据库。

2.1. 连接并加固MariaDB

首先,以root用户身份登录MariaDB。

sudo mysql -u root

如果是首次安装,强烈建议运行安全配置脚本。mysql_secure_installation脚本将引导您完成设置root密码、移除匿名用户等一系列安全强化操作。

sudo mysql_secure_installation

2.2. 创建数据库和用户

在MariaDB的命令行提示符(MariaDB [(none)]>)下,依次执行以下SQL查询语句,创建rsyslog专用的数据库和用户。

1. 创建数据库: 我们创建一个名为`Syslog`的数据库,用于存放日志。

CREATE DATABASE Syslog CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

2. 创建用户并授权: 创建一个名为`rsyslog_user`的用户,并授予其对`Syslog`数据库的全部权限。请务必将`'your-strong-password'`替换为一个真实的、高强度的密码。

CREATE USER 'rsyslog_user'@'localhost' IDENTIFIED BY 'your-strong-password';
GRANT ALL PRIVILEGES ON Syslog.* TO 'rsyslog_user'@'localhost';

3. 应用更改: 刷新权限,使更改立即生效。

FLUSH PRIVILEGES;

4. 退出: 离开MariaDB命令行。

EXIT;

2.3. 创建日志表结构(Schema)

rsyslog需要一个特定结构的表来存储日志。幸运的是,rsyslog-mysql软件包中已为我们准备好了创建此表结构的SQL脚本。我们只需在我们刚刚创建的`Syslog`数据库上执行它即可。

该脚本文件通常位于/usr/share/doc/rsyslog-mysql/目录下。使用以下命令将其导入到`Syslog`数据库中:

sudo mysql -u rsyslog_user -p Syslog < /usr/share/doc/rsyslog-mysql/createDB.sql

执行此命令后,系统会提示您输入`rsyslog_user`的密码。正确输入后,命令会安静地执行完毕,没有任何输出,这是正常现象。

为了验证,我们可以查看一下`Syslog`数据库中创建了哪些表。

sudo mysql -u rsyslog_user -p -e "USE Syslog; SHOW TABLES;"

如果执行结果显示了SystemEventsSystemEventsProperties这两个表,那么数据库的准备工作就圆满完成了。SystemEvents表就是我们即将存放日志的地方。


第三步:配置rsyslog - 过滤与数据库对接

这是最核心的环节。我们将修改rsyslog的配置文件,使其根据特定条件筛选日志,并将符合条件的日志发送到MariaDB。rsyslog的配置由主配置文件/etc/rsyslog.conf/etc/rsyslog.d/目录下的所有.conf文件共同决定。为了保持主配置的整洁和便于维护,我们将在/etc/rsyslog.d/目录下创建一个新的配置文件。

让我们创建一个名为60-mysql.conf的新文件。

sudo nano /etc/rsyslog.d/60-mysql.conf

在这个文件中,我们将告诉rsyslog要发送什么、如何发送以及发送到哪里。

3.1. 核心概念:RainerScript

现代rsyslog版本采用一种名为RainerScript的先进脚本化配置语法。相比传统的facility.priority格式,它提供了更强大、更灵活的过滤和控制能力。我们将使用RainerScript来构建我们的过滤规则。

RainerScript的过滤逻辑基本遵循if ... then ...结构:

if <条件表达式> then {
    <要执行的动作>
}

这里的“条件表达式”可以基于日志的各种属性(如程序名、主机名、消息内容等)来构建,而“要执行的动作”则定义了如何处理这条日志,例如存入文件、转发到另一台服务器,或是我们即将要做的——插入到数据库。

3.2. 编写配置:将所有日志发送到数据库(基础版)

我们先从最简单的配置开始:不加任何过滤,将所有日志都发送到数据库。这有助于我们首先验证数据库连接是否正常。请在60-mysql.conf文件中输入以下内容:

# #####################################################################
# ## 用于将日志发送到 MySQL/MariaDB 的配置 ##
# #####################################################################

# 1. 加载 ommysql 模块
# 这行代码告诉 rsyslog 如何与 MySQL 数据库通信
module(load="ommysql")

# 2. 定义一个动作(action),将所有日志(*)发送到数据库
# 格式: *.* action(type="ommysql" server="服务器地址" db="数据库名"
#                  uid="用户名" pwd="密码")
#
# 重要:请务必将下面的 'your-strong-password' 替换为您在第二步中设置的真实数据库密码
action(
    type="ommysql"
    server="127.0.0.1"
    db="Syslog"
    uid="rsyslog_user"
    pwd="your-strong-password"
)

这个配置非常直观:

  • module(load="ommysql"): 激活MySQL模块。
  • action(...): 指示rsyslog对所有日志(由于没有过滤器,默认为*.*)执行指定的动作。
    • type="ommysql": 明确指定动作为写入MySQL数据库。
    • server, db, uid, pwd: 必须准确填写您在第二步中配置的数据库连接信息。

3.3. 编写配置:应用过滤器(核心任务)

现在,我们来实践本指南的核心主题:“过滤”。将所有日志都存入数据库会产生海量数据,不仅浪费存储空间,也增加了查找关键信息的难度。我们将添加规则,只存储符合特定条件的日志。

假设我们的需求是:“我只想将SSH(sshd)相关的日志,以及级别为'warning'或更高的内核(kernel)消息存入数据库。

修改或替换60-mysql.conf文件的内容为:

# #####################################################################
# ## 用于过滤日志并将其发送到 MySQL/MariaDB 的配置 ##
# #####################################################################

# 1. 加载 ommysql 模块
module(load="ommysql")

# 2. 定义过滤规则和数据库存储动作
# 我们使用 RainerScript 的 if-then 语法
if ( \
    # 条件1:如果程序名(programname)是 'sshd'
    $programname == 'sshd' \
    or \
    # 条件2:如果程序名(programname)是 'kernel' 并且
    #          日志级别(syslogseverity) 小于等于 4 ('warning')
    #          (级别数值越小越严重: 0=emerg, 1=alert, 2=crit, 3=err, 4=warning)
    ($programname == 'kernel' and $syslogseverity <= 4) \
) then {
    # 只有匹配上述条件的日志才会执行下面的 action
    action(
        type="ommysql"
        server="127.0.0.1"
        db="Syslog"
        uid="rsyslog_user"
        pwd="your-strong-password"
    )
    # 'stop' 指令可以阻止这条日志被后续规则继续处理。
    # 如果不希望日志在存入DB后还写入 /var/log/syslog 等默认文件,这个指令很有用。
    # 这里我们将其注释掉,以保留默认的文件日志。
    # stop
}

此配置的核心在于if (...) then { ... }代码块:

  • $programname: rsyslog的一个内置变量(属性),它包含了生成日志的进程/程序的名称。
  • $syslogseverity: 一个代表日志严重级别的数字变量 (0: Emergency, 1: Alert, ..., 6: Informational, 7: Debug)。
  • ==, or, and, <=: 您可以像在编程语言中一样,使用这些常见的比较和逻辑运算符来构建复杂的条件。
  • action(...): 现在,这个动作变成了有条件的,只有通过了if语句检查的日志才会触发它。

更多过滤示例:

  • 只存储包含特定消息的日志 (例如 'Failed password'):
    if $msg contains 'Failed password' then { ... }
  • 只存储来自特定主机的日志:
    if $hostname == 'web-server-01' then { ... }
  • 存储除CRON任务之外的所有日志:
    if not ($programname == 'CRON') then { ... }

如您所见,RainerScript几乎可以实现您能想到的任何日志过滤场景。请根据您的系统环境和监控目标,自由地修改和组合过滤条件吧。


第四步:应用配置并验证

完成配置文件编写后,就该让rsyslog加载新设置,并验证一切是否按预期工作了。

4.1. 检查配置文件语法

在重启服务之前,检查一下配置文件是否存在语法错误是一个好习惯。带有错误的配置可能导致rsyslog服务启动失败。运行以下命令进行语法检查:

sudo rsyslogd -N1

如果您看到类似“rsyslogd: version ..., config validation run (level 1), master config /etc/rsyslog.conf OK.”且没有报错的输出,说明语法正确。如果存在错误,输出信息会指出错误所在的文件和行号,请据此进行修正。

4.2. 重启rsyslog服务

语法检查通过后,重启rsyslog服务以应用新配置。

sudo systemctl restart rsyslog

重启后,检查服务状态,确保其正常运行。

sudo systemctl status rsyslog

请留意状态是否为active (running),并仔细查看输出中是否有错误信息。

4.3. 检查数据库

最权威的验证方法就是直接检查数据库中是否已经有日志数据了。

我们可以手动触发一些符合过滤规则的日志。例如,尝试一次SSH登录(成功或失败均可),或者重启系统以产生内核消息。稍等片刻后,登录到MariaDB,查询SystemEvents表的内容。

sudo mysql -u rsyslog_user -p

登录数据库后,执行以下查询:

USE Syslog;
SELECT ID, ReceivedAt, FromHost, SysLogTag, Message FROM SystemEvents ORDER BY ID DESC LIMIT 10;

这条查询会显示最新存入的10条日志。如果您在查询结果中看到了与SSH(sshd)或内核(kernel)相关的日志,那么恭喜您,配置成功了!如果没有任何数据,请参考下面的问题排查部分。


问题排查 (Troubleshooting)

如果配置后数据库中没有日志进入,请检查以下几点:

  1. 检查rsyslog状态和日志: 运行sudo systemctl status rsyslogsudo journalctl -u rsyslog,查看rsyslog自身的错误日志。留意是否有“cannot connect to mysql server”之类的数据库连接失败信息。
  2. 核对数据库连接信息: 再次仔细检查60-mysql.conf文件中的数据库名、用户名、密码和服务器地址是否完全正确。密码拼写错误是常见原因。
  3. 检查防火墙: 如果rsyslog和数据库位于不同的服务器上,需要确保防火墙(如ufw, iptables)允许了对数据库端口(默认为3306)的访问。
  4. 检查过滤条件: 确认您的过滤条件是否过于严苛,导致当前系统根本没有产生匹配的日志。为了测试,可以暂时去掉过滤条件,改用捕获所有日志(*.*)的配置,先排除数据库连接本身的问题。
  5. SELinux/AppArmor: 极少数情况下,SELinux或AppArmor等安全模块可能会阻止rsyslog的网络连接。检查相关审计日志(/var/log/audit/audit.log/var/log/syslog)中是否有权限拒绝(permission denied)的记录。

总结与展望

恭喜!您已成功地在Ubuntu服务器上构建了一个能够实时过滤日志并将其存入数据库的系统。通过这一实践,您已将原本杂乱的文本文件,转化为了可以通过SQL进行查询、排序和聚合的结构化数据。这是将您的系统监控、安全分析和故障响应能力提升到新高度的关键一步。

但您的探索之旅并未结束,还可以更进一步:

  • 日志可视化: 将Grafana、Metabase等仪表盘工具连接到您的数据库,对日志数据进行可视化分析,例如绘制错误数量随时间变化的趋势图、登录尝试IP来源的地理分布图等。
  • 使用高级模板: rsyslog的模板功能允许您完全自定义存入数据库的日志格式。您可以实现更高级的用法,比如从日志消息中提取特定字段存入独立的列。
  • 扩展为日志中心: 配置多台服务器,将它们的日志统一转发到一个中央rsyslog服务器。由这台中央服务器负责所有日志的过滤和入库操作,从而构建一个企业级的集中式日志管理平台。

今天所学的rsyslog过滤与数据库集成功能仅仅是个开始。rsyslog是一个极其灵活和强大的工具。我们鼓励您进一步探索其官方文档,根据您的实际需求,构建出更精细、更强大的日志管理流水线。