코드 208개 중 208개
작업에 필요한 특권이 프로세스에 없습니다. 파일 소유자 변경, 다른 사용자의 프로세스에 시그널 보내기, 변경 불가 파일(chattr +i) 수정 등이 해당합니다. EACCES와 달리 파일 권한을 바꿔도 해결되지 않으며, root나 해당 capability가 필요합니다.
파일이나 디렉터리가 존재하지 않습니다. 경로 중간의 디렉터리가 없을 때, 심볼릭 링크가 존재하지 않는 대상을 가리킬 때, 스크립트의 #! 줄에 있는 인터프리터가 설치되어 있지 않을 때도 나타납니다.
해당 ID를 가진 프로세스, 프로세스 그룹 또는 스레드가 없습니다. 예를 들어 이미 종료된 PID에 kill을 실행한 경우입니다.
시스템 호출이 끝나기 전에 시그널이 호출을 중단시켰습니다. 실제 오류는 아닙니다. 프로그램은 호출을 다시 시도하거나 SA_RESTART를 지정해 시그널 핸들러를 설치해야 합니다.
저수준 입출력 오류로, 대개 장치를 읽거나 쓸 때 발생합니다. 디스크에서는 배드 섹터나 불량 케이블을 뜻하는 경우가 많으므로 dmesg와 SMART 상태를 확인하세요. 이미 닫힌 터미널에 쓸 때도 나타납니다.
장치나 주소가 존재하지 않습니다. 장치 파일은 있지만 그 뒤에 하드웨어가 없거나, 읽는 쪽이 없는 FIFO를 O_NONBLOCK으로 쓰기용으로 열었습니다.
exec에 전달하는 인수와 환경 변수 목록이 너무 큽니다. 수천 개의 파일로 확장되는 와일드카드를 사용할 때 흔히 보는 "Argument list too long"입니다. find -exec나 xargs를 사용하세요.
파일이 인식할 수 있는 실행 형식이 아닙니다. 다른 아키텍처용 바이너리이거나, 손상되었거나, #! 줄이 없는 스크립트입니다.
파일 디스크립터가 유효하지 않거나, 이미 닫혔거나, 해당 작업을 허용하지 않는 모드로 열렸습니다. 예를 들어 읽기 전용으로 연 디스크립터에 쓰는 경우입니다.
wait나 waitpid로 기다릴 자식 프로세스가 없습니다. SIGCHLD가 무시되어 자식이 자동으로 회수되는 경우가 많습니다.
리소스를 일시적으로 사용할 수 없으므로 다시 시도하는 것이 좋습니다. 논블로킹 작업에서는 아직 데이터나 공간이 없다는 뜻이고, fork에서는 프로세스나 스레드 한도(ulimit -u 또는 cgroup의 pids.max)에 도달했다는 뜻입니다.
같은 값:EWOULDBLOCK
작업에 필요한 메모리가 부족하거나 프로세스의 메모리 한도를 초과했습니다. fork나 mmap에서는 오버커밋 정책, cgroup 한도 또는 주소 공간 부족이 원인일 수 있습니다.
파일이나 경로상 디렉터리의 권한(각 디렉터리에 실행 권한이 필요), ACL, SELinux나 AppArmor, 또는 noexec 마운트 때문에 권한이 거부되었습니다. 특권 없이 1024 미만의 포트를 사용할 때 bind도 이 오류를 반환합니다.
유효하지 않은 메모리 주소를 가리키는 포인터가 시스템 호출에 전달되었습니다. 프로그램의 버그를 나타냅니다.
작업에 디스크 같은 블록 장치가 필요한데 다른 종류의 파일을 받았습니다. 예를 들어 일반 파일을 -o loop 없이 마운트한 경우입니다.
장치나 리소스가 사용 중입니다. 열린 파일이 있거나 터미널이 그 안에 위치한 파일 시스템을 마운트 해제할 때 흔히 발생합니다. lsof나 fuser로 어떤 프로세스가 사용 중인지 확인할 수 있습니다.
같은 이름의 파일, 디렉터리 또는 다른 객체가 이미 있습니다. 예를 들어 O_EXCL로 생성할 때, -p 없이 mkdir를 사용할 때, 대상이 이미 있는 링크를 만들 때입니다.
서로 다른 파일 시스템 사이에서는 하드 링크를 만들거나 파일 이름을 바꿀 수 없습니다. mv는 복사 후 삭제하는 방식으로 처리하며, rename()을 사용하는 프로그램도 같은 방식으로 처리해야 합니다.
장치가 없거나 해당 작업을 지원하지 않습니다. 예를 들어 커널 모듈이 로드되지 않은 유형의 파일 시스템을 마운트한 경우입니다.
디렉터리여야 할 경로 구성 요소가 파일이거나, 디렉터리를 요청했는데(O_DIRECTORY) 디렉터리가 아닙니다.
디렉터리에 파일 작업을 시도했습니다. 예를 들어 쓰기용으로 열려고 한 경우입니다.
호출에 유효하지 않은 인수입니다. 범위를 벗어난 값, 호환되지 않는 옵션 조합, 객체가 지원하지 않는 작업 등이 해당합니다. 일반적인 오류이므로 구체적인 경우는 해당 호출의 man 페이지에 나와 있습니다.
시스템 전체의 열린 파일 테이블이 가득 찼습니다. 한도는 sysctl의 fs.file-max로 조정합니다.
프로세스가 열 수 있는 디스크립터 한도에 도달했습니다("Too many open files"). ulimit -n이나 systemd의 LimitNOFILE로 한도를 높이고, 프로그램이 파일이나 소켓을 닫지 않고 남겨 두는지 확인하세요.
터미널이 아닌 대상에 터미널 작업(ioctl)을 요청했습니다. 예를 들어 대화형 프로그램의 출력을 파일이나 파이프로 리디렉션한 경우입니다.
실행 파일이 사용 중입니다. 실행 중인 바이너리에 쓸 수 없고, 쓰기용으로 열려 있는 바이너리는 실행할 수 없습니다. 업데이트할 때는 새 파일을 쓴 다음 이름을 바꾸는 것이 좋습니다.
파일이 파일 시스템이 허용하는 최대 크기(FAT32에서는 4GB)나 프로세스의 RLIMIT_FSIZE 한도를 초과했습니다.
장치에 남은 공간이 없습니다. df에 여유 공간이 보인다면 df -i로 inode를 확인하세요. inotify도 fs.inotify.max_user_watches를 모두 사용하면 이 오류를 반환합니다.
파이프, FIFO, 소켓에는 위치가 없으므로 lseek를 할 수 없습니다.
파일 시스템이 읽기 전용으로 마운트되어 있습니다. 아무도 요청하지 않았는데 읽기 전용이 되었다면 커널이 오류를 감지한 것입니다. dmesg를 확인하고 fsck를 실행하세요.
파일에 대한 하드 링크의 최대 개수를 초과했거나, 일부 파일 시스템에서 디렉터리의 하위 디렉터리 최대 개수를 초과했습니다.
반대쪽 끝이 이미 닫힌 파이프나 소켓에 썼습니다("Broken pipe"). 오류와 함께 프로세스는 SIGPIPE를 받습니다. cmd | head처럼 읽는 쪽이 먼저 끝나는 경우에는 정상입니다.
수학 함수의 인수가 정의역을 벗어났습니다. 예를 들어 음수의 제곱근입니다.
함수의 결과가 너무 크거나 작아서 표현할 수 없거나, 버퍼가 결과를 담기에 부족합니다. 예를 들어 짧은 버퍼로 getcwd를 호출한 경우입니다.
교착 상태를 피했습니다. 요청한 잠금(fcntl을 사용한 파일 잠금이나 오류 검사 뮤텍스 등)이 영원히 기다리게 될 상황이었습니다.
같은 값:EDEADLOCK
경로나 그 구성 요소 중 하나가 최대 길이를 초과했습니다. Linux에서는 일반적으로 이름당 255바이트, 경로당 4096바이트입니다.
사용할 수 있는 잠금이 없습니다. NFS에서는 잠금 서비스(lockd 또는 rpc.statd)가 실행되고 있지 않다는 뜻인 경우가 많습니다.
이 커널에 해당 시스템 호출이 없거나 구현되어 있지 않습니다. 더 새로운 커널용으로 컴파일된 바이너리나, 최신 시스템 호출을 모르는 컨테이너의 seccomp 프로필에서 흔히 발생합니다.
디렉터리가 비어 있지 않습니다. 예를 들어 rmdir를 사용하거나 기존 디렉터리 위로 이름을 바꿀 때입니다. 내용까지 함께 삭제하려면 rm -r을 사용하세요.
경로를 해석하는 중에 연결된 심볼릭 링크가 너무 많았습니다(대개 순환 때문입니다). 또는 심볼릭 링크에 O_NOFOLLOW를 사용했습니다.
System V 메시지 큐에 요청한 유형의 메시지가 없습니다.
프로세스가 사용하는 동안 System V IPC 식별자(큐, 세마포어 또는 공유 메모리)가 삭제되었습니다.
채널 번호가 범위를 벗어났습니다. Linux에서는 실제로 쓰이지 않는 레거시 코드입니다.
레벨 2가 동기화되지 않았습니다. Linux에서는 실제로 쓰이지 않는 System V 레거시 코드입니다.
레벨 3이 중지되었습니다. Linux에서는 실제로 쓰이지 않는 System V 레거시 코드입니다.
레벨 3이 재설정되었습니다. Linux에서는 실제로 쓰이지 않는 System V 레거시 코드입니다.
링크 번호가 범위를 벗어났습니다. Linux에서는 실제로 쓰이지 않는 레거시 코드입니다.
프로토콜 드라이버가 연결되어 있지 않습니다. 일부 Bluetooth 드라이버 등 소수의 서브시스템이 사용합니다.
사용할 수 있는 CSI 구조체가 없습니다. Linux에서는 실제로 쓰이지 않는 레거시 코드입니다.
레벨 2가 중지되었습니다. Linux에서는 실제로 쓰이지 않는 System V 레거시 코드입니다.
유효하지 않은 교환입니다. 레거시 코드이며, 일부 드라이버와 파일 시스템이 자체적인 의미로 재사용합니다.
유효하지 않은 요청 디스크립터입니다. 레거시 코드이며, 일부 드라이버가 자체적인 의미로 재사용합니다.
교환이 가득 찼습니다. Linux에서는 실제로 쓰이지 않는 레거시 코드입니다.
"anode"가 없습니다. Linux에서는 실제로 쓰이지 않는 레거시 코드입니다.
유효하지 않은 요청 코드입니다. 레거시 코드이며, 일부 드라이버는 지원하지 않는 명령에 이 코드를 사용합니다.
유효하지 않은 슬롯입니다. Linux에서는 실제로 쓰이지 않는 레거시 코드입니다.
글꼴 파일 형식이 잘못되었습니다. Linux에서는 실제로 쓰이지 않는 레거시 코드입니다.
장치가 STREAM이 아닙니다. Linux가 구현하지 않는 System V STREAMS 인터페이스에 속한 코드입니다.
사용할 수 있는 데이터가 없습니다. Linux에서는 확장 속성이 없을 때 getxattr이 반환합니다. macOS에서는 이 경우 ENOATTR입니다.
타이머가 만료되었습니다. STREAMS에서 유래했으며, Linux에서는 일부 드라이버와 io_uring이 제한 시간이 있는 작업에 사용합니다.
STREAMS 리소스가 남아 있지 않습니다. STREAMS는 Linux가 구현하지 않는 인터페이스입니다.
컴퓨터가 네트워크에 없습니다. 거의 쓰이지 않는 레거시 코드입니다.
패키지가 설치되어 있지 않습니다. 레거시 코드이며, 일부 서브시스템은 모듈(예: 암호화 모듈)이 없을 때 사용합니다.
객체가 원격에 있습니다. NFS에서는 다른 서버에서 내보낸 경로를 나타냅니다.
링크가 끊어졌습니다. 레거시 코드이며, 일부 드라이버는 장치와의 연결이 끊겼을 때 사용합니다.
"advertise" 오류입니다. Linux에서는 쓰이지 않는 RFS 레거시 코드입니다.
"srmount" 오류입니다. Linux에서는 쓰이지 않는 RFS 레거시 코드입니다.
전송 중 통신 오류입니다. 레거시 코드이며, 일부 네트워크 및 USB 드라이버가 사용합니다.
프로토콜 오류입니다. 상대방이나 장치가 예상하지 못한 응답을 보냈습니다. USB 장치나, 주고받는 도중에 끊긴 연결에서 나타납니다.
다중 홉(multihop)을 시도했습니다. RFS 레거시 코드입니다.
RFS 고유의 오류입니다. Linux에서는 쓰이지 않습니다.
메시지가 잘못된 형식이거나 손상되었습니다. ext4, XFS, Btrfs는 메타데이터 체크섬 검증에 실패하면 별칭 EFSBADCRC로 이 오류를 반환합니다.
같은 값:EFSBADCRC
값이 대상 데이터 형식에 들어가지 않습니다. 예를 들어 대용량 파일 지원 없이 컴파일된 32비트 프로그램이 2GB를 넘는 파일을 여는 경우입니다.
이름이 네트워크에서 고유하지 않습니다. 레거시 코드입니다.
파일 디스크립터의 상태가 잘못되었습니다. ALSA와 일부 드라이버가 장치가 준비되지 않았을 때 사용합니다.
원격 주소가 변경되었습니다. 레거시 코드입니다.
필요한 공유 라이브러리에 접근할 수 없습니다. a.out 바이너리 시절의 레거시 코드입니다.
공유 라이브러리가 손상되었습니다. a.out 바이너리 시절의 레거시 코드입니다.
a.out 바이너리의 .lib 섹션이 손상되었습니다. 레거시 코드입니다.
너무 많은 공유 라이브러리를 링크하려고 했습니다. a.out 시절의 레거시 코드입니다.
공유 라이브러리는 직접 실행할 수 없습니다. a.out 시절의 레거시 코드입니다.
바이트 시퀀스가 문자 인코딩에 유효하지 않습니다. 예를 들어 iconv나 멀티바이트 함수로 변환하는 텍스트가 유효한 UTF-8이 아닌 경우입니다.
중단된 호출을 다시 시작해야 합니다. 커널 내부용이며 프로그램에 전달되어서는 안 됩니다.
STREAMS 파이프 오류입니다. ALSA는 오디오 장치가 일시 중단되었을 때 이 오류를 반환합니다.
사용자가 너무 많습니다. 디스크 할당량 시스템의 테이블이 가득 찼을 때 반환하며, 드문 경우입니다.
소켓이 아닌 디스크립터에 소켓 작업을 사용했습니다.
대상 주소가 필요합니다. 비연결형 소켓으로 대상을 지정하지 않고 보냈습니다.
메시지가 소켓에 비해 너무 큽니다. 예를 들어 최대 크기를 넘는 UDP 데이터그램이나, 조각화가 허용되지 않을 때 MTU를 넘는 데이터그램입니다.
프로토콜이 소켓 유형과 맞지 않습니다.
요청한 소켓 옵션이나 프로토콜을 사용할 수 없습니다. 예를 들어 커널이 모르는 setsockopt 옵션입니다.
프로토콜이 지원되지 않습니다. 예를 들어 해당 커널 모듈이 로드되지 않은 경우입니다.
해당 주소 체계에서는 이 소켓 유형이 지원되지 않습니다.
소켓이나 객체가 해당 작업을 지원하지 않습니다. Linux에서는 ENOTSUP과 같은 값이며, 많은 파일 시스템이 fallocate나 확장 속성처럼 구현하지 않은 기능에 이 오류를 반환합니다.
작업이 지원되지 않습니다. Linux에서는 EOPNOTSUPP과 같은 값(95)이지만 macOS에서는 서로 다른 코드입니다.
프로토콜 체계가 지원되지 않습니다.
주소 체계가 지원되지 않습니다. IPv6가 비활성화된 시스템이나 컨테이너에서 IPv6를 사용할 때 흔히 발생합니다.
주소와 포트가 이미 사용 중입니다. 다른 프로세스가 해당 포트에서 수신 대기 중이거나, 이전 연결이 아직 TIME_WAIT 상태입니다. ss -ltnp나 lsof -i :포트로 프로세스를 찾거나 SO_REUSEADDR을 사용하세요.
요청한 주소를 할당할 수 없습니다. 해당 IP가 컴퓨터의 어떤 인터페이스에도 속하지 않거나, 나가는 연결에 쓸 임시 포트가 소진되었습니다.
네트워크 인터페이스가 다운되었습니다.
대상 네트워크로 가는 경로가 없어 연결할 수 없습니다. 라우팅 테이블과 게이트웨이를 확인하세요. IPv6 연결이 없는 상태에서 IPv6로 연결할 때도 발생합니다.
네트워크가 연결을 재설정했습니다. 예를 들어 keepalive가 실패한 경우입니다.
로컬 쪽에서 연결이 중단되었습니다. 예를 들어 서버가 accept로 받아들이기 전에 클라이언트가 연결을 닫은 경우입니다.
상대방이 RST로 연결을 갑자기 끊었습니다("Connection reset by peer"). 원격 프로세스가 종료되었거나, 방화벽이나 로드 밸런서가 유휴 연결을 끊었거나, 상대방이 예상하지 않은 데이터를 보냈습니다.
네트워크 작업에 쓸 커널 버퍼 공간이 없습니다. 트래픽이 많거나 소켓 큐가 가득 찼을 때 주로 나타납니다.
소켓이 이미 연결되어 있습니다.
소켓이 연결되어 있지 않습니다. 연결하기 전에 보내거나 받으려고 했거나, 연결이 이미 닫혔습니다. FUSE 마운트에서는 해당 프로세스가 종료되면 "Transport endpoint is not connected"로 나타나며, fusermount -u로 마운트를 해제하면 해결됩니다.
shutdown으로 소켓의 해당 방향을 닫은 뒤에는 보낼 수 없습니다.
참조가 너무 많습니다. Linux에서는 Unix 소켓으로 중첩된 디스크립터를 너무 많이 전달한 경우입니다.
대상이 응답하지 않아 연결 시간이 초과되었습니다. 패킷을 조용히 버리는 방화벽, 꺼진 호스트, 도달하지 않는 경로가 주된 원인입니다.
대상이 연결을 거부했습니다. 컴퓨터는 응답하지만 해당 포트에서 수신 대기하는 것이 없거나, 방화벽이 거부로 응답합니다. 서비스가 실행 중이며 127.0.0.1뿐 아니라 올바른 인터페이스에서 수신 대기하는지 확인하세요.
대상 호스트가 다운되었습니다.
호스트로 가는 경로가 없습니다. 로컬 네트워크에서 ARP에 응답하지 않거나, 라우터나 방화벽이 도달할 수 없다고 알려 왔습니다.
소켓에서 이미 작업이 진행 중입니다. 예를 들어 아직 끝나지 않은 논블로킹 connect입니다.
작업이 진행 중입니다. 논블로킹 connect가 시작되었고 나중에 완료됩니다. 오류가 아니므로 poll이나 select로 기다려야 합니다.
파일 핸들이 오래되었습니다. NFS에서 파일이나 디렉터리가 서버에서 삭제되거나 교체된 경우입니다. 경로를 다시 열거나 다시 마운트하면 해결됩니다.
구조를 정리해야 합니다. 파일 시스템이 손상을 감지했습니다(ext4와 XFS에서는 별칭 EFSCORRUPTED). 마운트를 해제하고 fsck나 xfs_repair를 실행하세요.
같은 값:EFSCORRUPTED
XENIX 이름 있는 파일이 아닙니다. 쓰이지 않는 레거시 코드입니다.
사용할 수 있는 XENIX 세마포어가 없습니다. 쓰이지 않는 레거시 코드입니다.
XENIX 이름 있는 파일입니다. 쓰이지 않는 레거시 코드입니다.
원격 I/O 오류입니다. 예를 들어 I2C 장치나 원격 디스크가 응답하지 않은 경우입니다.
사용자나 그룹의 디스크 할당량을 초과했습니다.
장치에 미디어가 없습니다. 예를 들어 디스크가 없는 드라이브나 빈 카드 리더기입니다.
미디어 유형이 올바르지 않습니다.
작업이 취소되었습니다. 예를 들어 비동기 I/O나 io_uring의 대기입니다.
필요한 키가 커널 키링에 없습니다. fscrypt나 eCryptfs 같은 암호화 파일 시스템에서 키가 로드되지 않았을 때 나타납니다.
키가 만료되었습니다. PAM과 Kerberos도 암호나 티켓이 만료되었을 때 이 코드를 사용합니다.
키가 해지되었습니다.
서비스가 키를 거부했습니다.
견고한(robust) 뮤텍스의 소유자가 해제하지 않고 종료되었습니다. 새 소유자는 보호되는 상태를 일관되게 만든 뒤 pthread_mutex_consistent를 호출해야 합니다.
이전 소유자가 종료되었고 아무도 일관된 상태로 표시하지 않았으므로, 견고한(robust) 뮤텍스가 보호하는 상태를 복구할 수 없습니다.
Wi-Fi나 Bluetooth 무선이 RF-kill로 차단되어 작업을 할 수 없습니다. rfkill list, 물리 스위치 또는 비행기 모드 키를 확인하세요.
메모리 페이지에 하드웨어 오류가 있어 커널이 오염됨(poisoned)으로 표시했습니다.
파일 유형이 해당 작업에 적합하지 않습니다. macOS와 BSD에는 오래전부터 있었고, Linux에는 최근에 추가되었습니다.
프로세스가 너무 많습니다. BSD에서 프로세스 한도용으로 정의했지만, 실제로 fork는 EAGAIN을 반환합니다.
RPC 구조체가 잘못되었습니다(NFS가 사용하는 Sun RPC).
RPC 버전이 일치하지 않습니다(NFS가 사용하는 Sun RPC).
서버에서 RPC 프로그램을 사용할 수 없습니다.
RPC 프로그램 버전이 일치하지 않습니다.
RPC 프로그램에 해당 프로시저가 없습니다.
인증 오류입니다. 예를 들어 NFS 리소스를 마운트할 때 발생합니다.
작업에 인증자가 필요합니다.
장치의 전원이 꺼져 있습니다.
장치 오류입니다. 예를 들어 용지가 없는 프린터입니다.
실행 파일이 유효하지 않습니다.
실행 파일이 다른 종류의 CPU용입니다. 예를 들어 Rosetta 2가 없는 Apple Silicon Mac에서 x86_64 전용 바이너리를 실행하거나, Intel Mac에서 ARM 바이너리를 실행한 경우입니다.
공유 라이브러리 버전이 일치하지 않습니다.
Mach-O 파일이 잘못된 형식이거나 손상되었습니다.
확장 속성이 없습니다. Linux의 ENODATA에 해당합니다. xattr에서 나타나며, 예를 들어 com.apple.quarantine이 없는 파일에서 이를 제거하려고 할 때입니다.
MAC Framework에 해당 이름으로 등록된 정책이 없습니다.
네트워크 인터페이스의 출력 큐가 가득 찼습니다.
권한(capability)이 부족합니다. 샌드박스가 제한하는 호출이 이 오류를 반환합니다.
프로세스를 제어하던 터미널이 닫혔거나 SSH 세션이 끊겼습니다. nginx, sshd, rsyslog 같은 많은 데몬은 이 시그널을 설정을 다시 읽으라는 요청으로 사용합니다. nohup, tmux, screen을 사용하면 로그아웃할 때 프로세스가 종료되지 않습니다.
키보드에서 Ctrl+C로 보내는 인터럽트입니다. 프로그램은 이를 가로채서 정상적으로 종료할 수 있습니다. 종료 코드는 130입니다.
키보드에서 Ctrl+\로 보내는 종료 요청입니다. 코어 덤프와 함께 프로세스를 종료하지만, JVM은 대신 스레드 상태를 출력하는 데 사용합니다.
프로세서가 잘못된 명령어를 만났습니다. 더 새로운 CPU용으로 컴파일된 바이너리(예: AVX2나 AVX-512를 지원하지 않는 프로세서에서 이를 사용하는 바이너리), 손상된 코드 또는 데이터로의 점프가 원인입니다.
디버그 트랩입니다. 디버거가 중단점에 사용합니다. 디버거 없이 전달되었다면 macOS의 Swift 검사처럼 프로그램 자체가 감지한 오류인 경우가 많습니다.
프로세스가 abort()를 호출했습니다. 실패한 어설션, 처리되지 않은 C++ 예외 또는 C 라이브러리가 감지한 힙 손상("double free or corruption")이 원인입니다. 종료 코드는 134입니다.
같은 값:SIGIOT
버스 오류입니다. 일부 아키텍처에서 정렬되지 않은 메모리에 접근했거나, 파일이 잘려서 더 이상 존재하지 않는 mmap 매핑 파일 영역에 접근했습니다. /dev/shm이 가득 찼을 때도 발생합니다.
산술 예외입니다. 이름과 달리 가장 흔한 원인은 정수를 0으로 나눈 것입니다.
프로세스를 즉시 종료합니다. 가로채거나 차단하거나 무시할 수 없습니다. kill -9, 메모리가 바닥났을 때 커널의 OOM killer, 그리고 컨테이너가 메모리 한도를 초과했거나(OOMKilled) SIGTERM 후 제때 종료되지 않았을 때 Docker나 Kubernetes가 보냅니다. 종료 코드는 137입니다.
각 애플리케이션이 자유롭게 용도를 정할 수 있는 시그널입니다. 예를 들어 dd는 진행 상황을 알려 주고 nginx는 로그 파일을 다시 엽니다.
세그먼테이션 위반("Segmentation fault")입니다. 널 포인터 역참조, 배열 범위를 벗어난 접근, 무한 재귀로 인한 스택 오버플로처럼 유효하지 않은 메모리에 접근했습니다. 종료 코드는 139입니다.
각 애플리케이션이 자유롭게 용도를 정할 수 있는 두 번째 시그널입니다.
읽는 쪽이 없는 파이프나 소켓에 썼습니다. 읽는 쪽이 먼저 끝나는 cmd | head에서는 정상입니다. 서버는 보통 이 시그널을 무시하고 EPIPE 오류를 처리합니다. 종료 코드는 141입니다.
alarm이나 setitimer로 설정한 타이머가 만료되었습니다.
정상 종료 요청입니다. kill, systemctl stop, docker stop의 기본 시그널이며, Kubernetes도 Pod를 삭제할 때 보냅니다. 프로세스는 연결을 닫고 종료해야 합니다. 종료 코드는 143입니다.
보조 프로세서의 스택 오류입니다. 현재 Linux에서는 쓰이지 않습니다.
자식 프로세스가 종료, 정지 또는 재개되었습니다. 부모는 wait로 자식을 회수해야 하며, 그렇지 않으면 자식은 좀비로 남습니다.
같은 값:SIGCLD
정지된 프로세스를 재개합니다. 셸의 fg와 bg가 하는 일입니다.
프로세스를 정지합니다. 가로채거나 무시할 수 없으며, SIGCONT로 재개합니다.
터미널에서 Ctrl+Z로 보내는 정지 요청입니다. SIGSTOP과 달리 프로그램이 가로챌 수 있습니다.
백그라운드 프로세스가 터미널에서 읽으려고 했습니다.
백그라운드 프로세스가 stty tostop이 켜진 상태에서 터미널에 쓰려고 했거나, 터미널 설정을 바꾸려고 했습니다.
소켓에 긴급(대역 외) 데이터가 도착했습니다. Go는 고루틴을 중단시키기 위해 내부적으로 사용합니다.
프로세스의 CPU 시간 한도(ulimit -t)를 초과했습니다.
프로세스에 허용된 최대 파일 크기(ulimit -f)를 초과했습니다.
프로세스의 CPU 시간만 세는 가상 타이머가 만료되었습니다.
프로파일러가 사용하는 프로파일링 타이머가 만료되었습니다.
터미널 창의 크기가 바뀌었습니다. 전체 화면 프로그램은 이 시그널을 받아 화면을 다시 그립니다.
O_ASYNC로 설정한 디스크립터에서 I/O가 가능해졌습니다. Linux에서는 SIGPOLL과 같은 시그널입니다.
같은 값:SIGPOLL
전원 장애입니다. UPS 소프트웨어가 init 시스템에 알립니다.
잘못된 시스템 호출입니다. 요즘 흔한 원인은 컨테이너에서처럼 해당 호출을 차단하는 seccomp 필터입니다.
에뮬레이션 트랩(EMT)입니다. macOS와 BSD에는 있지만 x86이나 ARM의 Linux에는 없습니다.
macOS와 BSD 터미널에서 Ctrl+T로 보내는 정보 요청입니다. 많은 명령이 진행 상황을 표시해 응답합니다.
명령이 정상적으로 끝났습니다. 성공을 뜻하는 유일한 코드이며, 다른 값은 모두 오류를 나타냅니다.
일반 오류입니다. 의미는 각 프로그램이 정합니다. 자세한 내용은 보통 명령이 stderr에 출력한 내용에 있습니다. grep과 diff는 이 코드를 다른 의미로 사용하며, 각각 "일치하는 항목 없음"과 "파일이 서로 다름"을 뜻합니다.
셸 내장 명령을 잘못 사용했거나 스크립트에 구문 오류가 있습니다. 많은 프로그램이 잘못된 옵션에도 이 코드를 사용하며, grep은 실제 오류에 사용합니다.
명령을 잘못 사용했습니다. 인수가 부족하거나 남거나, 옵션이 올바르지 않습니다.
입력 데이터의 형식이 올바르지 않습니다.
입력 파일이 없거나 읽을 수 없습니다.
지정한 사용자가 없습니다. 주로 메일 프로그램이 사용합니다.
호스트 이름이 존재하지 않습니다.
필요한 서비스를 사용할 수 없거나, 다른 범주에 해당하지 않는 실패가 발생했습니다.
프로그램 내부 오류입니다.
운영 체제 오류입니다. 예를 들어 fork를 하거나 파이프를 만들 수 없는 경우입니다.
/etc/passwd 같은 시스템 파일이 없거나 오류가 있습니다.
출력 파일을 만들 수 없습니다.
파일을 읽거나 쓰는 중 입출력 오류가 발생했습니다.
일시적인 실패이므로 나중에 다시 시도하는 것이 좋습니다. 메일 서버는 메시지를 큐에 남겨 두기 위해 이 코드를 사용합니다.
원격 시스템이 프로토콜을 따르지 않는 응답을 보냈습니다.
작업에 필요한 권한이 부족합니다.
구성에 오류가 있습니다.
지정한 시간을 초과하여 timeout 명령이 종료시켰습니다.
컨테이너를 실행하기 전에 docker run 자체가 실패했습니다. 예를 들어 잘못된 옵션이나 데몬 오류 때문입니다. GNU timeout도 timeout 자신이 실패했을 때 이 코드를 반환합니다.
파일은 있지만 실행할 수 없습니다. 실행 권한이 없거나, 디렉터리이거나, 다른 아키텍처용 바이너리입니다. Docker에서는 컨테이너의 명령이 실행 파일이 아닌 경우입니다.
명령을 찾을 수 없습니다. 설치되지 않았거나, PATH에 없거나, 이름의 철자가 틀렸습니다. 스크립트에서는 #! 줄의 인터프리터가 없을 때도 나타나고, Docker에서는 컨테이너의 명령이 이미지에 없을 때 나타납니다.
128보다 큰 코드는 시그널이 프로세스를 종료했음을 나타내지만, 128은 어떤 시그널에도 해당하지 않습니다. Git은 존재하지 않는 저장소나 클론 시 인증 실패 같은 모든 치명적 오류("fatal: …")에 이 코드를 사용합니다.
종료 코드가 범위를 벗어났습니다. 8비트만 유지되므로 exit -1은 255가 됩니다. ssh도 원격 명령의 코드와 구별하기 위해 연결이나 인증에 실패하면 이 코드를 반환합니다.
Linux 값은 x86, x86-64, ARM 기준입니다. Alpha, MIPS, SPARC, PA-RISC에서는 일부 errno와 시그널의 번호가 다릅니다. 영어 메시지는 glibc의 strerror와 strsignal이 표시하는 것이며, macOS에서 다른 경우 macOS의 메시지도 표시합니다. 128보다 큰 종료 코드는 128에 시그널 번호를 더한 값으로 해석하며, 이는 bash, Docker, Kubernetes의 규칙입니다.
작동 방식
Linux에서 시스템 호출이 실패하면 -1을 반환하고, 그 이유를 나타내는 번호를 errno 변수에 남깁니다. 2는 ENOENT(파일이 없음), 13은 EACCES(권한 거부)입니다. strerror는 이 번호를 "No such file or directory"처럼 화면에 보이는 텍스트로 바꿉니다. Python은 [Errno 13]으로, Node.js는 code: 'ECONNREFUSED'로 표시하며, Go, Rust, Java는 같은 텍스트를 표시합니다. 1부터 34까지의 번호는 원래 Unix에서 온 것으로 모든 시스템에서 같습니다. 그 이후 번호는 각 시스템이 따로 매겼기 때문에 ECONNREFUSED는 Linux에서 111, macOS에서 61입니다. 이름은 이식 가능하지만 번호는 그렇지 않습니다.
시그널은 커널이나 다른 프로세스가 프로세스에 보내는 알림입니다. Ctrl+C를 누르면 SIGINT, 종료를 요청할 때는 SIGTERM, 묻지 않고 종료시킬 때는 SIGKILL, 유효하지 않은 메모리에 접근하면 SIGSEGV가 전달됩니다. 각 시그널에는 기본 동작이 있으며, 대부분은 가로채서 다른 일을 하게 할 수 있습니다. 시그널이 프로세스를 종료시키면 셸은 128에 시그널 번호를 더한 값을 종료 코드로 보고합니다. 137은 SIGKILL(9), 139는 SIGSEGV(11), 143은 SIGTERM(15)입니다. Docker와 Kubernetes도 같은 규칙을 사용합니다.
종료 코드는 프로그램이 끝날 때 남기는 번호입니다. 0은 성공, 그 밖의 값은 오류를 뜻합니다. 8비트만 유지되므로 범위는 0부터 255까지입니다. 규칙은 많지 않습니다. 126과 127은 셸이 명령을 실행할 수 없거나 찾지 못할 때 사용하고, 64부터 78까지는 BSD의 sysexits.h가 정의하며, 나머지는 각 프로그램이 정합니다. 예를 들어 grep은 아무것도 찾지 못하면 1을 반환합니다.
예시
Last State: Terminated · Reason: OOMKilled · Exit Code: 137137 = 128 + 9 · SIGKILL컨테이너가 메모리 한도를 초과해 커널이 SIGKILL로 종료시켰습니다. resources.limits.memory에서 한도를 높이거나 프로세스가 왜 그렇게 많은 메모리를 쓰는지 찾아야 합니다. 다시 시작한다고 해결되지는 않습니다.Error: connect ECONNREFUSED 127.0.0.1:5432ECONNREFUSED · Linux 111 · macOS 61 · Connection refused포트 5432에서 수신 대기하는 것이 없어서 Node.js가 PostgreSQL에 연결하지 못했습니다. 애플리케이션이 컨테이너에서 실행 중이라면 127.0.0.1은 호스트가 아니라 컨테이너 자신입니다. 데이터베이스 서비스 이름을 사용해야 합니다.OSError: [Errno 48] Address already in useEADDRINUSE · Linux 98 · macOS 4848이라는 번호를 보면 프로그램이 macOS에서 실행 중임을 알 수 있습니다. Linux에서는 같은 오류가 98입니다. 두 경우 모두 다른 프로세스가 이미 포트를 사용 중이며, lsof -i :포트로 어떤 프로세스인지 확인할 수 있습니다.활용 사례
- 번호나 errno 이름만 보여 주는 Python, Node.js, Go, C 애플리케이션의 오류를 이해합니다.
- 종료 코드로 Docker 컨테이너가 종료된 이유나 Kubernetes Pod가 재시작되는 이유를 알아냅니다.
- 35번부터 Linux와 일치하지 않는 macOS의 errno 번호를 올바른 이름으로 바꿉니다.
- 실패한 스크립트, cron 또는 CI 작업의 종료 코드를 해석합니다.
- kill로 보낼 시그널을 고르고, 프로세스가 가로채지 않으면 어떻게 되는지 알아봅니다.
- 번호 대신 이름으로 비교하는 이식 가능한 오류 처리를 작성합니다.
자주 묻는 질문
exit code 137은 무슨 뜻인가요?
프로세스가 시그널 9, 즉 SIGKILL(128 + 9)로 종료되었다는 뜻입니다. 가장 흔한 원인은 메모리입니다. 컨테이너가 한도를 초과했거나(Kubernetes는 OOMKilled로 보고), 커널의 OOM killer가 그 프로세스를 선택한 경우이며, 후자는 dmesg에 "Out of memory: Killed process"로 남습니다. docker kill을 사용했거나, SIGTERM 후 정해진 시간 안에 프로세스가 종료되지 않았을 때도 발생합니다(docker stop은 10초, Kubernetes는 30초).
SIGTERM과 SIGKILL의 차이는 무엇인가요?
SIGTERM은 프로세스에 종료를 요청하며, 프로세스는 이를 가로채서 연결을 닫고 데이터를 저장한 뒤 종료할 수 있습니다. SIGKILL은 커널이 그 자리에서 프로세스를 종료시키며, 프로세스는 아무것도 할 수 없습니다. 올바른 방법은 SIGTERM을 보내고 몇 초 기다린 다음, 그래도 살아 있을 때만 SIGKILL을 사용하는 것입니다. systemd, docker stop, Kubernetes도 이렇게 합니다.
같은 errno가 macOS에서는 왜 다른 번호인가요?
POSIX는 이름은 정의하지만 번호는 정의하지 않기 때문입니다. 1부터 34까지는 모든 시스템이 원래 Unix의 번호를 물려받았지만, 그 이후로는 macOS의 기반인 BSD와 Linux가 따른 System V가 따로 번호를 매겼습니다. 그래서 번호가 아니라 Python의 errno.ECONNREFUSED, Node.js의 err.code, C의 상수처럼 항상 이름으로 비교하는 것이 좋습니다.
EACCES와 EPERM의 차이는 무엇인가요?
EACCES("Permission denied")는 파일이나 경로상 디렉터리의 권한이 허용하지 않거나, ACL이나 SELinux가 막고 있다는 뜻입니다. chmod, chown 또는 해당 정책으로 해결합니다. EPERM("Operation not permitted")은 권한과 관계없이 작업 자체에 특권이 필요하다는 뜻입니다. 예를 들어 파일 소유자를 바꾸거나 다른 사용자의 프로세스를 종료하는 경우이며, root나 capability가 필요하거나 변경 불가 같은 속성을 제거해야 합니다.
명령이나 컨테이너의 종료 코드는 어떻게 확인하나요?
bash와 zsh에서는 echo $?가 마지막 명령의 종료 코드를 보여 주고, PowerShell에서는 $LASTEXITCODE입니다. Docker에서는 docker ps -a의 STATUS 열에 "Exited (137)"처럼 표시됩니다. Kubernetes에서는 kubectl describe pod의 "Last State: Terminated"에 OOMKilled나 Error 같은 이유와 함께 표시됩니다.