Blog >> PHP >> Whitepapers.

PHP 원인을 알 수 없는 재시작·비정상 종료(segfault) 150 150 phobe

PHP 원인을 알 수 없는 재시작·비정상 종료(segfault)

PHP 애플리케이션의 원인 모를 재시작, Segfault(Segmentation fault), OOM(Out of Memory) 비정상 종료는 OS 커널 로그, 웹 서버/PHP-FPM 로그, 코어 덤프(Core Dump) 세 지점에서 추적

1. OS 커널 및 메모리(OOM) 킬러 로그 조회

# dmesg 버퍼에서 OOM 및 Segfault 이벤트 확인
dmesg -T | grep -Ei "oom|kill|segfault|php"

# systemd 저널에서 커널 메시지 필터링
journalctl -k --since "24 hours ago" | grep -Ei "oom|kill|segfault|php"

# /var/log/syslog 또는 /var/log/messages 직접 조회 (배포판에 따라 선택)
grep -Ei "oom-killer|out of memory|segfault" /var/log/messages
# CentOS/RHEL/Rocky 이외 계열:
# grep -Ei "oom-killer|out of memory|segfault" /var/log/syslog

2. PHP-FPM / 웹 서버 로그 조회
PHP 자체의 메모리 한도 초과(memory_limit)나 마스터 프로세스의 워커 비정상 종료 감지 로그를 확인

# PHP-FPM 메인 로그에서 비정상 종료 시그널(SIGSEGV, SIGKILL 등) 감지 내역 확인
# (경로는 버전에 따라 /var/log/php8.x-fpm.log 또는 /var/log/php-fpm/error.log)
grep -Ei "SIGSEGV|SIGKILL|exited on signal" /var/log/php*-fpm.log

# PHP fatal error (Allowed memory size exhausted) 확인
grep -i "allowed memory size" /var/log/php*-fpm.log /var/log/nginx/*error*.log /var/log/apache2/*error*.log 2>/dev/null

# 실시간 모니터링 (재현 시 유용)
tail -f /var/log/php*-fpm.log

# 실제 웹서버 502/504 에러 발생 여부 확인
grep -Ei "502 Bad Gateway|504 Gateway Time-out|connect\(\) failed" /var/log/nginx/*error*.log /var/log/httpd/*error*.log 2>/dev/null

# 실시간 PHP-FPM 워커 상태 모니터링 - 워커 프로세스들이 요청을 처리하며 부드럽게 PID가 바뀌는지 관찰
# 프로세스 PID 및 가동 시간(etime) 모니터링
watch -n 1 "ps -eo pid,ppid,user,%cpu,%mem,etime,command | grep -E 'php-fpm: pool' | grep -v grep"

# 실행 중인 풀(Pool) 목록 및 프로세스 수 확인
ps -eo user,pid,args | grep -E "php-fpm: pool" | grep -v grep | awk '{print $NF}' | sort | uniq -c

# 풀별 상세 프로세스(PID, 메모리 점유율, 가동 시간) 확인
ps -eo pid,ppid,user,%mem,rss,etime,command | grep -E "php-fpm: (master|pool)" | grep -v grep
# RSS: 실제 물리 메모리 사용량 (KB 단위)
# ELAPSED (etime): 프로세스가 생성된 후 지난 시간 (예: 04:12 = 4분 12초)
# pm.max_requests에 도달하여 새로 생성된 프로세스는 etime이 짧게 리셋

실행 중인 각 PHP-FPM 풀(Pool)별 워커 프로세스 수, 평균 메모리 점유량(MB), 총 메모리 합계(MB)

ps -eo rss,args | grep -E "php-fpm: pool" | grep -v grep | awk '{
    pool = $NF;
    rss = $1;
    mem[pool] += rss;
    count[pool] += 1;
}
END {
    printf "%-25s %-10s %-15s %-15s\n", "Pool Name", "Workers", "Avg Mem (MB)", "Total Mem (MB)";
    printf "----------------------------------------------------------------------\n";
    for (p in count) {
        printf "%-25s %-10d %-15.2f %-15.2f\n", p, count[p], (mem[p] / count[p]) / 1024, mem[p] / 1024;
    }
}'

3. Core Dump(코어 덤프) 파일 및 스택 트레이스 확인

# systemd-coredump 관리 환경인 경우
coredumpctl list | grep php

# 특정 coredump 분석 (GDB 자동 연동)
coredumpctl gdb php-fpm

# /var/crash 또는 현재 디렉터리의 core 파일 확인
ls -lh /var/crash/ /tmp/core* 2>/dev/null
  • Allowed memory size of … exhausted 발생 시:
    임시 조치: php.ini의 memory_limit = 512M 등으로 증설.
    근본 조치: 대용량 파일 스트리밍 처리(Generator, fopen 기반 청크 처리), 대량 DB 쿼리의 unbuffered query 또는 배치 커서 적용.
  • Out of memory: Killed process (php-fpm) 발생 시:
    PHP 개별 스크립트 한도가 아니라 서버 전체 RAM 부족이 원인이다.
    pm.max_children 값을 서버 가용 RAM 크기에 맞게 하향 조정 (가용 RAM ÷ 개별 PHP 프로세스 평균 사용량).
  • SIGSEGV (Signal 11) 발생 시:
    PHP 자체 버그보다 로드 된 확장 모듈(Imagick, OPcache, Xdebug, gRPC, Redis 등) 충돌 가능성이 90% 이상이다. 의심되는 모듈을 하나 씩 비활성화(php -m 확인)하거나 최신 안정 버전으로 컴파일/업데이트해야 한다.
# 1. 시스템 코어 덤프 제한(ulimit) 확인
ulimit -c
# '0'으로 출력되면 Segfault가 나도 덤프 파일을 디스크에 쓰지 않습니다.

# 2. PHP-FPM 마스터 설정에서 rlimit_core 점검
grep -rn "rlimit_core" /etc/php* /etc/php-fpm* 2>/dev/null
# 주석 해제 후 'rlimit_core = unlimited'로 두면 비정상 크래시 발생 시 즉시 덤프를 남깁니다.