카테고리 보관물:  IT

Syslog Server 설정

개요

Syslog Server 설정은 분산된 리눅스/윈도우 서버의 이벤트 로그를 중앙에서 수집·관리하기 위한 필수 인프라 구성입니다. rsyslog 기반의 Server Side에서 수신 설정을 하고, 각 Client 서버에서 원격 Syslog 서버 IP를 지정하면 로그가 자동으로 중앙 서버로 전송됩니다. 이 글에서는 CentOS 6/7 환경의 rsyslog 설정과 Windows의 eventlog-to-syslog 연동 방법을 정리합니다.

Server Side

  • CentOS(RHEL)의 경우 기본 경로는 /var/log/* 이며 필요시 아래와 같이 /logs/* 로 변경이 가능 합니다.
  • CentOS 7 설치
# vi /etc/rsyslog.conf
// 커널 로그 모듈 활성화
$ModLoad imklog
// 로그 저장 경로 변경 또는 추가
*.info;mail.none;authpriv.none;cron.none    /logs/messages
authpriv.*                                  /logs/secure
cron.*                                      /logs/cron
uucp,news.crit                              /logs/spooler
local7.*                                    /logs/boot.log

// Service 재시작
# systemctl restart rsyslog
  • CentOS 6 설치
# vi /etc/rsyslog.conf
// 커널 로그 모듈 활성화
$ModLoad imklog
// 로그 저장 경로 변경 또는 추가
*.info;mail.none;authpriv.none;cron.none    /logs/messages
authpriv.*                                  /logs/secure
cron.*                                      /logs/cron
uucp,news.crit                              /logs/spooler
local7.*                                    /logs/boot.log

// Service 재시작
# service rsyslog restart

Client Side

  • 리눅스의 경우 rsyslog.conf 또는 syslog.conf에 아래 행을 추가 하여 Syslog 서버로 로그를 전송할 수 있습니다.
  • CentOS 7 설치
# vi /etc/rsyslog.conf
// 커널 로그 모듈 활성화
$ModLoad imklog
// 로그 서버 IP(ex> x.x.x.x) 또는 Hostname 추가
*.* @x.x.x.x

// Service 재시작
# systemctl restart rsyslog
  • CentOS 6 설치
# vi /etc/rsyslog.conf
// 커널 로그 모듈 활성화
$ModLoad imklog
// 로그 서버 IP(ex> x.x.x.x) 또는 Hostname 추가
*.* @x.x.x.x

// Service 재시작
# service rsyslog restart
  • Windows 설치(eventlog-to-syslog)
  1. 윈도우 계열의 이벤트로그(eventlog)를 Syslog 서버로 전송
  2. App 다운 및 압축 해제(http://code.google.com/p/eventlog-to-syslog)
  3. 해당 파일을 C:\Windows\System32\ 로 복사
  4. evtsys 서비스 설치(아래 Prompt 또는 Powershell 실행)
  5. services.msc 실행 서비스 등록 확인 후 속성에서 시작 유형 ‘자동’ / 변경 후 서비스 시작
// x.x.x.x의 Syslog 서버의 514 포트로 이벤트로그를 전송하는 서비스 설치
C:\Windows\System32> evtsys -i -h x.x.x.x -p 514
Usage: evtsys -i|-u|-d [-h host[;host2;…]] [-f facility] [-p port]
       [-t tag] [-s minutes] [-q bool] [-l level] [-n] [-a]
  -i           Install service
  -u           Uninstall service
  -d           Debug: run as console program
  -a           Use our IP address (or fqdn) in the syslog message
  -h hosts     Name of log host(s), separated by a ‘;’
  -f facility  Facility level of syslog message
  -l level     Minimum level to send to syslog
               0=All/Verbose, 1=Critical, 2=Error, 3=Warning, 4=Info
  -n           (**Win9x/Server 2003 Only**) Include only those events specified
               in the config file
  -p port      Port number of syslogd
  -q bool      Query the Dhcp server to obtain the syslog/port to log to
               (0/1 = disable/enable)
  -t tag       Include tag as program field in syslog message
  -s minutes   Optional interval between status messages. 0 = Disabled

Default port: 514
Default facility: daemon
Default status interval: 0
Host (-h) required if installing.
Command did not complete due to a failure

Evtsys Options

참고

참고 문서: rsyslog 공식 설정 문서 · rsyslog.conf(5) man page

소스코드 플러그인 비교

개요

기술 블로그에서 코드를 게시글에 넣을 때 단순히 일반 텍스트로 삽입하면 가독성이 크게 떨어집니다. 들여쓰기가 무너지고, 문법 요소가 구분되지 않으며, 긴 줄은 줄 번호 없이 보기 어렵습니다. WordPress에서 소스코드를 게시글에 삽입하고 구문 강조(Syntax Highlight) 처리하기 위해 사용하는 소스코드 플러그인들을 비교합니다. Code Syntax Block, Enlighter, SyntaxHighlighter Evolved 등 주요 플러그인의 기능, 지원 언어, 편의성을 비교하여 환경에 맞는 플러그인 선택에 도움을 드립니다.

이 글에서는 Code Syntax Block, Enlighter, SyntaxHighlighter Evolved 세 플러그인을 비교하고, Enlighter의 다양한 테마를 같은 Python 코드로 시각적으로 비교합니다.

플러그인 비교 — 특징 및 추천

세 플러그인은 각각 다른 방향성을 가집니다. Code Syntax Block은 WordPress 5.0 이후의 블록 에디터(Gutenberg)와 완벽하게 통합되며 별도 설정 없이 바로 사용할 수 있습니다. 지원 언어는 제한적이지만 최신 WordPress 블록 기반 편집 경험에 가장 잘 맞습니다. 가볍고 추가 JavaScript 의존성이 없다는 것이 장점입니다.

Enlighter는 이 블로그에서 사용 중인 플러그인으로, 가장 많은 테마(Enlighter, Godzilla, Beyond, Classic, Mowtwo, Eclipse, Dracula, Monokai 등)를 제공합니다. 텍스트 에디터 환경에서도 잘 동작하며, EnlighterJSRAW 클래스를 가진 <pre> 블록만 있으면 JavaScript가 자동으로 렌더링합니다. 터미널/쉘 출력을 포함한 generic 언어 지원이 특히 인프라 관련 블로그에 유용합니다.

SyntaxHighlighter Evolved는 Alex Gorbatchev의 SyntaxHighlighter 라이브러리 기반으로 오랜 역사를 가집니다. 단축코드(shortcode) 방식([code lang="java"])으로 작성하며, 클래식 에디터와의 호환성이 좋습니다.

  • Code Syntax Block ( Python, Default )
def get_prime_nums(s, e):
    prime_nums = []

    for i in range(s, e + 1):
        flag = 1
        for j in range(2, i // 2 + 1):
            if i % j == 0:
                flag = 0
                break

        if flag == 1:
            prime_nums.append(i)

    return prime_nums

if __name__ == '__main__':
    s = int(input("Insert Start Number : "))
    e = int(input("Insert Finish Number : "))
#    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
// 소수를 출력합니다.

  • Enlighter Sourcecode ( Python, Default )
def get_prime_nums(s, e):
    prime_nums = []

    for i in range(s, e + 1):
        flag = 1
        for j in range(2, i // 2 + 1):
            if i % j == 0:
                flag = 0
                break

        if flag == 1:
            prime_nums.append(i)

    return prime_nums

if __name__ == '__main__':
    s = int(input("Insert Start Number : "))
    e = int(input("Insert Finish Number : "))
#    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
// 소수를 출력합니다.

  • Enlighter Sourcecode ( Python, Enlighter )
def get_prime_nums(s, e):
    prime_nums = []

    for i in range(s, e + 1):
        flag = 1
        for j in range(2, i // 2 + 1):
            if i % j == 0:
                flag = 0
                break

        if flag == 1:
            prime_nums.append(i)

    return prime_nums

if __name__ == '__main__':
    s = int(input("Insert Start Number : "))
    e = int(input("Insert Finish Number : "))
#    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
// 소수를 출력합니다.

  • Enlighter Sourcecode ( Python, Godzilla )
def get_prime_nums(s, e):
    prime_nums = []

    for i in range(s, e + 1):
        flag = 1
        for j in range(2, i // 2 + 1):
            if i % j == 0:
                flag = 0
                break

        if flag == 1:
            prime_nums.append(i)

    return prime_nums

if __name__ == '__main__':
    s = int(input("Insert Start Number : "))
    e = int(input("Insert Finish Number : "))
#    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
// 소수를 출력합니다.

  • Enlighter Sourcecode ( Python, Beyond )
def get_prime_nums(s, e):
    prime_nums = []

    for i in range(s, e + 1):
        flag = 1
        for j in range(2, i // 2 + 1):
            if i % j == 0:
                flag = 0
                break

        if flag == 1:
            prime_nums.append(i)

    return prime_nums

if __name__ == '__main__':
    s = int(input("Insert Start Number : "))
    e = int(input("Insert Finish Number : "))
#    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
// 소수를 출력합니다.

  • Enlighter Sourcecode ( Python, Classic )
def get_prime_nums(s, e):
    prime_nums = []

    for i in range(s, e + 1):
        flag = 1
        for j in range(2, i // 2 + 1):
            if i % j == 0:
                flag = 0
                break

        if flag == 1:
            prime_nums.append(i)

    return prime_nums

if __name__ == '__main__':
    s = int(input("Insert Start Number : "))
    e = int(input("Insert Finish Number : "))
#    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
// 소수를 출력합니다.

  • Enlighter Sourcecode ( Python, Mowtwo )
def get_prime_nums(s, e):
    prime_nums = []

    for i in range(s, e + 1):
        flag = 1
        for j in range(2, i // 2 + 1):
            if i % j == 0:
                flag = 0
                break

        if flag == 1:
            prime_nums.append(i)

    return prime_nums

if __name__ == '__main__':
    s = int(input("Insert Start Number : "))
    e = int(input("Insert Finish Number : "))
#    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
// 소수를 출력합니다.

  • Enlighter Sourcecode ( Python, Eclipse )
def get_prime_nums(s, e):
    prime_nums = []

    for i in range(s, e + 1):
        flag = 1
        for j in range(2, i // 2 + 1):
            if i % j == 0:
                flag = 0
                break

        if flag == 1:
            prime_nums.append(i)

    return prime_nums

if __name__ == '__main__':
    s = int(input("Insert Start Number : "))
    e = int(input("Insert Finish Number : "))
#    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
// 소수를 출력합니다.

  • Enlighter Sourcecode ( Python, Droide )
def get_prime_nums(s, e):
    prime_nums = []

    for i in range(s, e + 1):
        flag = 1
        for j in range(2, i // 2 + 1):
            if i % j == 0:
                flag = 0
                break

        if flag == 1:
            prime_nums.append(i)

    return prime_nums

if __name__ == '__main__':
    s = int(input("Insert Start Number : "))
    e = int(input("Insert Finish Number : "))
#    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
// 소수를 출력합니다.

  • Enlighter Sourcecode ( Python, Minimal )
def get_prime_nums(s, e):
    prime_nums = []

    for i in range(s, e + 1):
        flag = 1
        for j in range(2, i // 2 + 1):
            if i % j == 0:
                flag = 0
                break

        if flag == 1:
            prime_nums.append(i)

    return prime_nums

if __name__ == '__main__':
    s = int(input("Insert Start Number : "))
    e = int(input("Insert Finish Number : "))
#    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
// 소수를 출력합니다.

  • Enlighter Sourcecode ( Python, Atomic )
def get_prime_nums(s, e):
    prime_nums = []

    for i in range(s, e + 1):
        flag = 1
        for j in range(2, i // 2 + 1):
            if i % j == 0:
                flag = 0
                break

        if flag == 1:
            prime_nums.append(i)

    return prime_nums

if __name__ == '__main__':
    s = int(input("Insert Start Number : "))
    e = int(input("Insert Finish Number : "))
#    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
// 소수를 출력합니다.

  • Enlighter Sourcecode ( Python, Rowhammer )
def get_prime_nums(s, e):
    prime_nums = []

    for i in range(s, e + 1):
        flag = 1
        for j in range(2, i // 2 + 1):
            if i % j == 0:
                flag = 0
                break

        if flag == 1:
            prime_nums.append(i)

    return prime_nums

if __name__ == '__main__':
    s = int(input("Insert Start Number : "))
    e = int(input("Insert Finish Number : "))
#    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
// 소수를 출력합니다.

  • Enlighter Sourcecode ( Python, Bootstrap4 )
def get_prime_nums(s, e):
    prime_nums = []

    for i in range(s, e + 1):
        flag = 1
        for j in range(2, i // 2 + 1):
            if i % j == 0:
                flag = 0
                break

        if flag == 1:
            prime_nums.append(i)

    return prime_nums

if __name__ == '__main__':
    s = int(input("Insert Start Number : "))
    e = int(input("Insert Finish Number : "))
#    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
// 소수를 출력합니다.

  • Enlighter Sourcecode ( Python, Dracula )
def get_prime_nums(s, e):
    prime_nums = []

    for i in range(s, e + 1):
        flag = 1
        for j in range(2, i // 2 + 1):
            if i % j == 0:
                flag = 0
                break

        if flag == 1:
            prime_nums.append(i)

    return prime_nums

if __name__ == '__main__':
    s = int(input("Insert Start Number : "))
    e = int(input("Insert Finish Number : "))
#    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
// 소수를 출력합니다.

  • Enlighter Sourcecode ( Python, Monokai )
def get_prime_nums(s, e):
    prime_nums = []

    for i in range(s, e + 1):
        flag = 1
        for j in range(2, i // 2 + 1):
            if i % j == 0:
                flag = 0
                break

        if flag == 1:
            prime_nums.append(i)

    return prime_nums

if __name__ == '__main__':
    s = int(input("Insert Start Number : "))
    e = int(input("Insert Finish Number : "))
#    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
"""
    print(get_prime_nums(s, e))
// 소수를 출력합니다.

Enlighter 테마 선택 기준

Enlighter는 사이트 전체 기본 테마를 WordPress 관리자 화면의 Enlighter 설정(Settings > Enlighter)에서 지정할 수 있습니다. 개별 코드 블록에서 data-enlighter-theme 속성으로 테마를 덮어쓸 수도 있습니다. 위에서 비교한 결과 개인적으로는 다크 계열의 Dracula 또는 Monokai 테마가 터미널 명령어와 함께 쓸 때 가독성이 높습니다. 라이트 테마를 선호한다면 Enlighter(기본)Classic이 깔끔합니다. 어두운 배경과 높은 대비를 원하면 GodzillaEclipse가 좋습니다.

참고

참고 문서: SyntaxHighlighter Evolved 플러그인 · Code Syntax Block 플러그인

Zabbix Server 설치

개요

Zabbix Server 설치는 리눅스 서버 및 네트워크 장비의 성능과 가용성을 모니터링하는 오픈소스 모니터링 플랫폼 구축의 첫 단계입니다. Zabbix는 에이전트 기반 모니터링, SNMP, IPMI 등 다양한 수집 방식을 지원하며 웹 기반 대시보드를 제공합니다. 이 글에서는 CentOS 7 환경에서 Zabbix Server를 설치하는 절차를 정리합니다.

※ 설치 시기가 오래된 관계로 최근 버전과 설치 방식이 상이할 수 있습니다.

Zabbix 아키텍처 개요

Zabbix는 크게 Zabbix Server, Zabbix Agent, Zabbix Web UI로 구성됩니다. Server는 수집된 데이터를 MariaDB에 저장하고 트리거를 평가하여 알림을 발송하는 핵심 컴포넌트입니다. Agent는 모니터링 대상 서버에 설치되어 CPU, 메모리, 디스크, 프로세스 등의 메트릭을 수집해 Server에 전달합니다. Web UI는 Apache + PHP 기반으로 대시보드, 트리거 설정, 알림 설정 등을 관리합니다.

Zabbix는 에이전트 방식 외에도 SNMP(네트워크 장비), IPMI(서버 BMC), JMX(Java 애플리케이션), ICMP(ping 기반) 수집 방식을 지원합니다. 수백 대 이상의 서버를 모니터링하는 대규모 환경에서는 Zabbix Proxy를 배치하여 Server의 부하를 분산합니다. 이 가이드는 Zabbix 2.4 버전 기준이며, 현재 최신 버전(7.x)은 패키지 설치 방식이 다를 수 있습니다.

사전 설치 환경 구성(Pre Configuration)

  • OS Version : CentOS(RHEL) 7 64bit
  • Web Service : Apache (httpd)
  • Language : PHP (Version 5.4)
# /etc/php.ini 수정
max_execution_time=300      #스크립트의 최대 실행 시간
post_max_size=16M           #POST 방식으로 넘겨질 최대 데이터 크기
max_input_time=300          #스크립트 페이지로 넘어가기 전 php엔진이 데이터를 업로드 받는 최대 시간
date.timezone="Asia/Seoul"  #지역 시간 지정
  • DBMS : MariaDB or MySQL(Version 5.5)
# yum install MariaDB-shared MariaDB-devel MariaDB-common MariaDB-server MariaDB-client
// MariaDB 서비스 시작

# mysql_secure_installation
// 보안 설정 진행 ('enter' / 'password' / 'password' / y / n / y / y)

# mysql -uroot -p'password'
MariaDB [(none)]> CREATE DATABASE zabbix CHARACTER SET UTF8;
Query OK, 1 row affected (0.00 sec)

create user 'zabbix'@'localhost' identified by 'password'; #사용자 생성
create user 'zabbix'@'%' identified by 'password'; #원격 접근 사용자 생성

MariaDB [(none)]> GRANT ALL PRIVILEGES on zabbix.* to 'zabbix'@'localhost' IDENTIFIED BY 'SECRET_PASSWORD';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
  • 관련 패키지 설치
# yum install net-snmp-devel curl-devel fping 2fsprogs-devel zlib-devel libgssapi-devel krd5-devel openssl-devel libidn-devel iksemel-devel libXpm openssh-clients php-xml php-xmlrpc sharutils net-snmp OpenIPMI-devel libssh2-devel php-bcmath php-gd php-mbstring -y
// 설치 실패 항목 존재시 Zabbix Pre Install Error 발생

Zabbix 설치(Version 2.4)

  • Zabbix 패키지 설치 및 설정
// Zabbix Repo 설치
# rpm -Uvh http://repo.zabbix.com/zabbix/2.4/rhel/7/x86_64/zabbix-release-2.4-1.el7.noarch.rpm

// Zabbix Server 설치
# yum install zabbix zabbix-server zabbix-web zabbix-server-mysqlzabbix-web-mysql zabbix-agent -y

// 환경설정 수정
# /etc/zabbix/zabbix_server.conf
DBName=zabbix
DBUser=zabbix
DBPassword='Database 접근 계정 비밀번호'
StartSNMPTrapper=1
ListenIP='NIC IP Address',127.0.0.1
CacheSize=128M
HistoryCacheSize=128M
TrendCacheSize=64M
HistoryTextCacheSize=128M
Timeout=30
  • DB Schema Insert
// 스키마 생성(DB Table 생성 및 Data 입력)
# mysql -u zabbix -p zabbix < /usr/share/doc/zabbix-server-mysql-2.4.6/create/schema.sql

// 이미지 생성(3.0  버전 이후 zcat create.sql.gz | mysql -u root zabbix)
# mysql -u zabbix -p zabbix < /usr/share/doc/zabbix-server-mysql-2.4.6/create/images.sql

// 데이터 생성
# mysql -u zabbix -p zabbix < /usr/share/doc/zabbix-server-mysql-2.4.6/create/data.sql

Zabbix WEB 설치

  • WEB Document root 변경 : /usr/share/zabbix 디렉토리를 아파치의 기본 경로로 변경 하거나 Document root로 복사
  • 아파치 재시작 후 웹브라우저로 해당 웨서버 접속
  • 설치 과정 진행(캡쳐 화면은 2.2 버전을 활용한 것으로 실제와 차이가 다소 있습니다.)
정상 접속 상태 Next 이동
Required를 모두 충족 하면 OK상태 Fail이 하나라도 있으면 진행안됨
Required를 참고 하여 모두 적용 후 Next 이동
Database 정보 입력 모두 입력 후(MySQL 또는 MariaDB 선택, 기본 포트 미변경시 0 유지)
Test connection에 성공 하면 Next 이동
Host의 localhost 또는 IP 및 Port Num 확인 후 Next 이동
설정 확인 후 Next 이동
Fail 발생시 /usr/share/zabbix/conf/zabbix.conf.php.example 파일을 Document root 의 conf/zabbix.conf.php로 복사
Retry 재시도
OK 상태 확인 후 Finish 이동
// zabbix-server 등록
# systemctl enable zabbix-server

// zabbix-server 시작
# systemctl start zabbix-server
※시작 오류 발생시 yum update trousers
Zabbix WEB 로그인 후 정상 페이징 상태 확인(admin/zabbix)

Zabbix 운영 및 트러블슈팅

Zabbix Server 기동 후 로그(/var/log/zabbix/zabbix_server.log)에서 오류를 확인합니다. 가장 흔한 기동 오류는 DB 접속 실패(DBHost/DBUser/DBPassword 불일치)와 필수 패키지 미설치로 인한 라이브러리 오류입니다. trousers 패키지 오류가 발생하면 yum update trousers로 해결할 수 있습니다. Agent 연결이 안 될 경우 방화벽에서 10050/10051 포트(agent/server 기본 포트)가 열려 있는지 확인합니다.

Zabbix-agent 환경 설정

  • 설정 및 서비스 재시작
# /etc/zabbix/zabbix_agentd.conf 수정
Server=127.0.0.1          # 로컬호스트가 아닌 경우 실제 IP 입력
Hostname=hostname         # 호스트네임 적용
# ServerActive=127.0.0.1  # 주석처리

// zabbix-agent 등록
# systemctl enable zabbix-agent

// zabbix-agent 시작
# systemctl start zabbix-agent
  • Zabbix 관리 페이지에서 Hosts에 agent를 추가하여 모니터링 시작

참고

참고 문서: Zabbix 공식 설치 문서 · Zabbix 다운로드 페이지