본문 바로가기
운영체제 (LNX,WIN)

윈도우 PC 프로세스 정보 수집을 통한 모니터링 및 분석

by 날으는물고기 2024. 2. 15.

윈도우 PC 프로세스 정보 수집을 통한 모니터링 및 분석

Process Explorer - Sysinternals - Microsoft Learn

윈도우 PC에서 실행 중인 프로세스의 정보를 수집하기 위해서는 Python의 psutil 라이브러리를 사용할 수 있습니다. 이 라이브러리를 사용하면 현재 실행 중인 프로세스에 대한 다양한 정보를 얻을 수 있으며, 이를 통해 프로세스의 이름, ID, 메모리 사용량 등을 확인할 수 있습니다.

 

먼저, psutil 라이브러리를 설치해야 합니다. 이는 pip 명령어를 사용하여 설치할 수 있습니다.

pip install psutil

설치가 완료된 후, 다음과 같은 Python 스크립트를 사용하여 실행 중인 모든 프로세스의 정보를 수집할 수 있습니다.

import psutil

# 모든 프로세스를 순회하며 정보를 출력
for proc in psutil.process_iter(['pid', 'name', 'memory_info']):
    # 프로세스 ID, 이름, 메모리 사용량을 출력
    print(f"PID: {proc.info['pid']}, Name: {proc.info['name']}, Memory Usage: {proc.info['memory_info']}")

이 스크립트는 현재 실행 중인 모든 프로세스의 PID(프로세스 ID), 이름, 그리고 메모리 사용 정보를 출력합니다. psutil.process_iter() 함수는 다양한 정보를 제공할 수 있으며, 필요한 정보를 선택적으로 조회할 수 있습니다.

 

이 방법은 기본적인 프로세스 정보를 수집하는 데 사용할 수 있으며, 추가적인 정보가 필요한 경우 psutil의 다른 기능들을 활용할 수 있습니다. 예를 들어, 네트워크 사용량, 파일 시스템 사용량, 프로세스의 상태 등 다양한 정보를 얻을 수 있습니다.

 

수집된 프로세스 정보를 JSON 파일로 저장하고, 이전 수행 결과와 비교하여 변경 사항을 슬랙으로 알리는 작업은 여러 단계로 나누어서 수행할 수 있습니다. 다음은 이 과정을 단계별로 설명하고, 필요한 Python 코드를 제공하는 방법입니다.

프로세스 정보 수집 및 JSON 파일로 저장

먼저, psutil을 사용하여 프로세스 정보를 수집하고, 이를 JSON 파일로 저장합니다.

import psutil
import json

def collect_process_info():
    processes = []
    for proc in psutil.process_iter(['pid', 'name', 'memory_info']):
        processes.append({
            "pid": proc.info['pid'],
            "name": proc.info['name'],
            "memory": proc.info['memory_info'].rss  # Resident Set Size 메모리 사용량
        })
    return processes

def save_to_json(data, filename='process_info.json'):
    with open(filename, 'w') as f:
        json.dump(data, f, indent=4)

processes = collect_process_info()
save_to_json(processes)

이전 실행 결과와 현재 결과 비교

이전에 저장된 JSON 파일과 현재 수집된 데이터를 비교하여 변경 사항을 파악합니다.

def load_from_json(filename='process_info.json'):
    try:
        with open(filename, 'r') as f:
            return json.load(f)
    except FileNotFoundError:
        return None

def compare_process_info(old_data, new_data):
    old_pids = {proc['pid'] for proc in old_data}
    new_pids = {proc['pid'] for proc in new_data}

    started_processes = [proc for proc in new_data if proc['pid'] not in old_pids]
    stopped_processes = [proc for proc in old_data if proc['pid'] not in new_pids]

    return started_processes, stopped_processes

# 이전 데이터 로드
old_processes = load_from_json()

# 현재 데이터와 비교
started, stopped = compare_process_info(old_processes, processes) if old_processes else ([], [])

슬랙으로 알림 보내기

변경 사항을 슬랙으로 알리기 위해 requests 라이브러리를 사용합니다. 먼저 슬랙에서 Incoming Webhook URL을 설정해야 합니다.

import requests

def send_slack_message(message, webhook_url):
    payload = {"text": message}
    response = requests.post(webhook_url, json=payload)
    return response.status_code

# 슬랙 웹훅 URL (여기에 실제 URL을 사용해야 함)
webhook_url = "YOUR_SLACK_WEBHOOK_URL"

# 변경 사항 메시지 생성
message_parts = []
if started:
    message_parts.append("Started Processes:\n" + "\n".join(f"PID: {proc['pid']}, Name: {proc['name']}" for proc in started))
if stopped:
    message_parts.append("Stopped Processes:\n" + "\n".join(f"PID: {proc['pid']}, Name: {proc['name']}" for proc in stopped))

if message_parts:
    message = "\n\n".join(message_parts)
    send_slack_message(message, webhook_url)

이 코드는 다음과 같은 순서로 작동합니다.

  1. 현재 실행 중인 프로세스의 정보를 수집하고 JSON 파일로 저장합니다.
  2. 이전에 저장된 JSON 파일을 로드하고 현재 데이터와 비교합니다.
  3. 변경된 프로세스 정보(시작되거나 종료된 프로세스)를 슬랙으로 전송합니다.

requests 라이브러리도 설치해야 합니다.

pip install requests

이 스크립트를 사용하기 전에, 슬랙에서 Incoming Webhook을 설정하고 해당 URL을 스크립트에 제공해야 합니다. Webhook URL은 슬랙 메시지를 보내는 데 사용됩니다.

 

SQLite 데이터베이스를 사용하여 프로세스 정보의 히스토리를 관리하고, 최근 수행된 결과와 비교하여 달라진 부분을 슬랙으로 알림을 보내는 기능을 구현할 수 있습니다. 이를 위해 Python 스크립트를 다음 단계로 나누어 구현합니다.

  1. SQLite 데이터베이스 초기화: 프로세스 정보를 저장할 테이블을 생성합니다.
  2. 프로세스 정보 수집 및 저장: 현재 실행 중인 프로세스 정보를 수집하여 SQLite 데이터베이스에 저장합니다.
  3. 이전 실행 결과와 비교: 데이터베이스의 최근 정보와 현재 수집된 정보를 비교합니다.
  4. 슬랙으로 알림 보내기: 변경 사항을 슬랙으로 전송합니다.

SQLite 데이터베이스 초기화

import sqlite3

def initialize_database(db_name='process_info.db'):
    conn = sqlite3.connect(db_name)
    cursor = conn.cursor()
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS processes (
            id INTEGER PRIMARY KEY,
            pid INTEGER,
            name TEXT,
            memory INTEGER,
            timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
        )
    ''')
    conn.commit()
    conn.close()

initialize_database()

프로세스 정보 수집 및 저장

import psutil

def collect_and_save_process_info(db_name='process_info.db'):
    conn = sqlite3.connect(db_name)
    cursor = conn.cursor()

    for proc in psutil.process_iter(['pid', 'name', 'memory_info']):
        cursor.execute('INSERT INTO processes (pid, name, memory) VALUES (?, ?, ?)',
                       (proc.info['pid'], proc.info['name'], proc.info['memory_info'].rss))

    conn.commit()
    conn.close()

collect_and_save_process_info()

이전 실행 결과와 비교

def get_last_process_info(db_name='process_info.db'):
    conn = sqlite3.connect(db_name)
    cursor = conn.cursor()
    cursor.execute('''
        SELECT pid, name, memory FROM processes 
        WHERE timestamp = (SELECT MAX(timestamp) FROM processes)
    ''')
    last_processes = cursor.fetchall()
    conn.close()
    return last_processes

def compare_process_info(db_name='process_info.db'):
    last_processes = get_last_process_info(db_name)
    last_pids = {proc[0] for proc in last_processes}
    current_processes = collect_process_info()
    current_pids = {proc['pid'] for proc in current_processes}

    started_processes = [proc for proc in current_processes if proc['pid'] not in last_pids]
    stopped_processes = [proc for proc in last_processes if proc[0] not in current_pids]

    return started_processes, stopped_processes

슬랙으로 알림 보내기

앞서 설명한 send_slack_message 함수를 사용하여 변경 사항을 슬랙으로 전송합니다.

# ... (send_slack_message 함수 코드)

started, stopped = compare_process_info()
if started or stopped:
    # 메시지 작성 및 슬랙으로 전송
    # ...

이 스크립트는 프로세스 정보를 수집하고, SQLite 데이터베이스에 저장한 후, 가장 최근의 정보와 비교하여 시작되거나 종료된 프로세스를 찾아 슬랙으로 알림을 보내는 작업을 수행합니다. 데이터베이스는 프로세스 정보의 히스토리를 관리하는 데 사용됩니다. 데이터베이스와 슬랙 웹훅 URL을 설정하기 전에, 해당 환경에 맞게 코드를 수정해야 합니다.

728x90

댓글