평소 10분 내외로 끝나던 배치 가운데 일부가 며칠째 종료되지 않는다. 프로세스는 살아 있고 CPU 는 거의 쓰지 않는다. 배치 로그는 특정 지점에서 멈춘 뒤 더 이상 찍히지 않는다.
이것은 성능 저하가 아니라 종료 신호를 주고받지 못하는 상태다. "느려졌다" 는 가정으로 튜닝을 보면 시간만 쓴다.
compute 서버(compsrv) 로그에서 잡 생성과 상태 조회 흐름을 본다.
POST /compute/sessions/.../jobs 201 Created
GET /compute/.../jobs/<id>/state?wait=30 304 Not Modified
GET /compute/.../jobs/<id>/state?wait=30 304 Not Modified
...
세션과 잡 생성은 정상인데 304 Not Modified 가 계속 반복된다면, 상위 계층은 잡 상태가 바뀌기를 기다리는 중이다. 상태를 바꿔 줄 아래쪽에서 무언가 멈췄거나 죽었다는 뜻이다. compsrv 자체의 문제가 아니다.
ps -eo pid,ppid,user,stat,etime,%cpu,%mem,cmd | egrep 'sas|compute|batch'
cat /proc/<PID>/wchan; echo
top -Hp <PID>
STAT 가 D 면 중단 불가능한 I/O 대기다. 스토리지 쪽을 먼저 본다. S 인 채 오래 있고 CPU 를 안 쓰면 응답을 기다리는 중이다.
lsof -p <PID> | head -100
strace -tt -p <PID>
strace 는 운영 중이라도 몇 초만 붙여 보면 성격이 드러난다.
| 반복되는 호출 | 해석 |
|---|---|
futex(...) |
락 · 스레드 대기 |
read · poll · recvfrom |
네트워크나 DB 응답 대기 |
open · stat 반복 |
경로 · 스토리지 문제 |
| 아무 변화 없음 | hung I/O 가능성 |
dmesg -T | egrep -i 'nfs|i/o error|blocked|hung|stuck|timeout'
며칠 동안 멈춘 수준의 I/O hang 이라면 커널 로그에 반드시 흔적이 남는다. 최근 기간에 아무것도 없으면 디스크 · NFS 가설은 거의 탈락이다. 이 한 번의 확인으로 조사 범위가 크게 줄어든다.
iostat -x 1 5
vmstat 1 5
df -h; mount | grep -E 'nfs|cifs'
time dd if=/dev/zero of=<대상경로>/iotest bs=1M count=1024 oflag=direct
%util 이 100 에 붙어 있고 await 가 크면 디스크 병목이다. 값이 한가하면 스토리지는 아니다.
스케줄로 도는 배치라면 반드시 본다.
grep -R "Error during managed flush\|unexpected row count\|ERROR" \
/opt/sas/viya/config/var/log/launcher/default
Error during managed flush, Batch update returned unexpected row count 가 보이면 개별 배치보다 Launcher · 스케줄러 쪽 문제로 무게가 실린다. 해당 증상에 대한 SAS 핫픽스가 있으니 Problem Note 를 확인한다 (확인 필요 — 문서 번호는 SAS 지원 포털에서 직접 조회한다).
며칠 도는 배치는 SAS 로그 마지막 20~50줄이 가장 중요하다. 어느 단계 직후에 끊겼는지가 원인 갈래를 정한다.
proc sql; connect to ... 직후 — DB 응답 대기proc casutil 직후 — CAS 저장 · promote 단계NOTE: 만 찍히고 다음 단계가 없음 — 그 자리에서 멈춤실제로 자주 걸리는 지점이다. promote 는 이름만 바꾸는 작업이 아니라 세션 범위(session scope) 테이블을 전역 범위(global scope)로 등록하는 작업이다.
proc casutil;
promote casdata="<table>" incaslib="casuser" outcaslib="public";
run;
멈추거나 꼬이는 조건은 대개 이렇다.
replace · drop 정리가 안 된 상태에서 충돌한다.There is no session-scope table ... 이 찍힌다.확인은 목록부터 본다.
proc casutil;
list tables incaslib="public";
list tables incaslib="casuser";
run;
promote 대상 이름이 매번 같은 고정 이름이면 배치가 겹칠 때 반드시 부딪친다. 실행 식별자를 이름에 넣거나, promote 전에 기존 전역 테이블을 명시적으로 drop 한다. 배치 자체에 중복 실행 방지(락 파일 · 스케줄러 동시성 제한)를 거는 편이 더 확실하다.
로그에 다음이 보이면 정상적인 오류가 아니라 프로세스가 터진 것이다.
ERROR MAIN NoUser MAIN [httpjsgi.c:....] - Exception occurred during TKScript execution
ERROR MAIN NoUser MAIN [httpjsgi.c:....] - Access violation
tkhttp.so, tkdictionary.so, caspkg.so 같은 내부 라이브러리에서 메모리 접근 오류가 났다는 뜻이다. 프로세스가 죽으면 상위 compsrv 는 완료 신호를 받지 못하고, 잡 상태는 running 인 채로 남아 앞서 본 304 폴링이 끝없이 반복된다. 증상과 원인이 이렇게 이어진다.
엔진 크래시 -> 종료 신호 없음 -> job state 변화 없음 -> compsrv 폴링 무한 반복
이 단계에서는 SAS 지원에 넘기는 것이 맞다. 넘길 때 함께 보내는 자료는 다음과 같다.
/opt/sas/viya/config/var/log/ 아래 compsrv · CAS · launcher 로그의 해당 시각 구간ulimit -c 설정kill <PID> # 먼저 정상 종료 신호
kill -9 <PID> # 반응이 없을 때만
cas <session> terminate;
kill -9 는 세션 정리 없이 죽이므로 CAS 쪽에 고아 테이블이 남을 수 있다. 정리 후 list tables 로 남은 것을 확인한다.