Exec Format Error: Cannot Execute Binary File — 원인과 해결

문제 요약
리눅스/유닉스 계열에서 “Cannot Execute Binary File: Exec Format Error”는 실행 요청한 파일이 현재 커널이나 사용자 공간에서 요구하는 실행 포맷과 맞지 않을 때 표시되는 일반적인 오류입니다. 근본 원인은 다양하지만, 핵심은 “실행하려는 파일(바이너리 또는 스크립트)의 형식/아키텍처/권한/무결성이 현재 환경과 호환되지 않는다”는 점입니다.
중요: 이 오류는 단순히 권한 문제(chmod로 해결)일 수도 있고, 전혀 다른 CPU 아키텍처용 바이너리를 실행하려 할 때(예: ARM 바이너리를 x86_64에서 실행) 발생할 수도 있습니다.
주요 원인 요약
- 아키텍처 불일치: 바이너리가 실행 중인 시스템의 CPU 아키텍처와 다릅니다 (예: ARM ↔ x86_64, i386 ↔ x86_64 등).
- 잘못된 실행 포맷: 파일이 ELF, Mach-O, PE 등 현재 커널이 이해하지 못하는 포맷입니다.
- 파일 손상: 다운로드/복사 중 파일이 손상되어 실행 헤더가 깨진 경우.
- 실행 권한 누락: 파일에 실행 비트가 없음.
- 필요한 인터프리터/라이브러리 미설치: 바이너리가 특정 런타임(32비트 라이브러리, 호환 레이어)을 필요로 함.
- 셸/환경 구성 문제: shebang(#!)이 잘못되었거나, CRLF(Windows) 라인엔딩으로 인해 스크립트가 실행 불가.
진단 도구(한줄 정의)
- file: 파일의 유형과 대상 아키텍처를 알려줍니다.
- readelf: ELF 헤더와 섹션 정보를 확인합니다.
- uname -m: 현재 커널의 하드웨어 아키텍처를 확인합니다.
- ldd: 동적 링커(라이브러리) 종속성을 확인합니다.
- md5sum/sha256sum: 파일 무결성(다운로드 손상 여부) 확인.
- strings: 바이너리 내부에서 텍스트/셰뱅 정보를 검색.
상세 해결 절차(단계별)
1) 파일 타입 및 아키텍처 확인
가장 먼저 할 일은 해당 파일이 어떤 포맷이고 어떤 아키텍처용인지 확인하는 것입니다.
file my_executable
uname -m
readelf -h my_executable
출력 예시(참고):
- “ELF 64-bit LSB executable, x86-64” → x86_64용 64비트 ELF
- “ELF 32-bit LSB executable, Intel 80386” → 32비트(i386)용
- “ELF 32-bit LSB pie executable, ARM” → ARM용
해석: 파일의 아키텍처가 uname -m의 값과 다르면, Exec Format Error가 발생할 가능성이 큽니다.
2) 파일 무결성 확인
다운로드 중 손상되었는지 확인합니다. 배포처에서 제공하는 체크섬과 비교하세요.
md5sum my_executable
sha256sum my_executable
체크섬이 일치하지 않으면 바이너리를 다시 다운로드하거나 배포자에게 문의하세요.
3) 실행 권한 확인 및 부여
권한이 없으면 실행이 차단됩니다. 실행 비트가 있는지 확인하고 필요하면 추가합니다.
ls -l my_executable
chmod +x my_executable
./my_executable
권한 문제만 있던 경우 이로써 해결됩니다.
4) 스크립트인지 바이너리인지 구분
파일이 텍스트 파일(쉘스크립트, 파이썬 등)인데도 binary error가 뜨는 경우가 있습니다. file 명령으로 확인하고, 스크립트라면 shebang(#!)과 라인 엔딩을 검사하세요.
file my_script
head -n 1 my_script
dos2unix my_script # 필요시 CRLF -> LF 변환
shebang이 잘못되었거나 존재하지 않는 경우, 명시적으로 인터프리터로 실행하세요:
/bin/bash my_script
python3 my_script.py
5) 아키텍처 불일치 해결
상황별 옵션:
- 동일 아키텍처의 올바른 바이너리 확보: 가장 간단하고 안전한 방법입니다. 배포처에서 호스트 아키텍처에 맞는 패키지를 다운로드하세요.
- 재컴파일: 소스가 있다면 타깃 아키텍처로 컴파일하세요 (cross-compile 포함).
- 32비트 바이너리를 64비트 시스템에서 실행해야 하는 경우: 32비트 런타임(라이브러리)을 설치합니다.
- Debian/Ubuntu 예시:
dpkg --add-architecture i386
apt update
apt install libc6:i386 libstdc++6:i386
- RHEL/CentOS 예시:
yum install glibc.i686 libstdc++.i686
- 다른 CPU 계열(예: ARM 바이너리 on x86_64)인 경우: qemu-user-static 같은 에뮬레이션을 사용하거나 컨테이너/VM에서 실행하세요.
- qemu-user-static와 binfmt 설치(예: Debian/Ubuntu):
apt install qemu-user-static
# 시스템에 따라 binfmt 지원 설정 필요
- Docker에서 cross-arch 이미지를 실행하려면 Docker Desktop 또는 qemu-binfmt hỗ trợ가 활성화되어야 합니다.
참고: 패키지 이름과 명령은 배포판과 버전에 따라 달라질 수 있습니다.
6) 실행 포맷(인터프리터) 문제 해결
바이너리가 특정 런타임(예: 오래된 libc, 특별한 로더)을 요구할 수 있습니다. ldd로 의존성을 확인하세요.
ldd my_executable
ldd가 “not a dynamic executable” 또는 오류를 반환하면, 정적 링크된 바이너리이거나 현재 환경에서 로드할 수 없는 포맷입니다. 필요한 라이브러리를 설치하거나, 호환 가능한 런타임을 제공해야 합니다.
7) 손상된 바이너리 또는 잘못된 포맷 처리
ELF 헤더가 깨진 경우(예: readelf가 오류를 낼 때), 재다운로드 또는 공급자로부터 교체본을 받아야 합니다. 임시 복구는 권장되지 않습니다.
대체 접근법 및 심화 옵션
- 컨테이너 격리: 이진이 다른 아키텍처용인 경우, 해당 아키텍처용 컨테이너 이미지나 VM을 사용하세요.
- 원격 빌드/CI: 대상 아키텍처에서 빌드 스텝을 거쳐 바이너리 생성 (cross-compile보다 더 안정적일 수 있음).
- 바이너리 재빌드: 소스가 있다면 타깃 아키텍처로 재컴파일.
- 사용자 권한 모드: setuid/setgid 문제를 의심하는 경우 보안 설정(SELinux, AppArmor) 로그를 확인하세요.
의사결정 흐름(빠른 체크용)
flowchart TD
A[시작: Cannot Execute Binary File 에러] --> B[file로 확인]
B --> C{file 결과}
C -->|ELF '다른 아키텍처'| D[아키텍처 불일치 해결: 올바른 바이너리/에뮬레이터/컨테이너]
C -->|ELF '같은 아키텍처'| E[readelf/ldd로 종속성·헤더 검사]
C -->|텍스트 / 스크립트| F[shebang·라인엔딩·인터프리터로 실행]
E --> G{ldd 결과}
G -->|라이브러리 누락| H[필요 라이브러리 설치]
G -->|정상| I[권한/무결성 문제 점검]
I --> J{권한/체크섬}
J -->|권한 없음| K[chmod +x]
J -->|체크섬 불일치| L[재다운로드]
D --> M[종료]
K --> M
H --> M
L --> M
F --> M
역할별 체크리스트
개발자/빌드 담당자:
- 대상 아키텍처 명시형 바이너리 제공 여부 확인
- 설치/배포 문서에 요구되는 런타임/라이브러리 명시
- CI에서 타깃 아키텍처별 빌드 제공 고려
운영자/시스템 관리자:
- uname -m과 file 결과 비교
- 필수 32비트 라이브러리 또는 qemu-binfmt 설치 여부 확인
- SELinux/AppArmor 등 보안 로그 검사
일반 사용자:
- 파일 권한 확인(chmod +x)
- 파일이 스크립트면 shebang과 DOS 라인엔딩 확인
- 공식 배포처에서 올바른 패키지 다운로드
테스트 사례 및 수락 기준
케이스 1: 동일 아키텍처 바이너리, 실행 권한 없음
- 입력: ELF x86_64 바이너리, 권한 rw-r–r–
- 조치: chmod +x
- 기대 결과: 정상 실행
케이스 2: 다른 아키텍처 바이너리
- 입력: ARM 바이너리 on x86_64
- 조치: file 확인 → qemu 또는 올바른 바이너리 사용
- 기대 결과: qemu 설정 시 실행 가능 또는 올바른 바이너리로 대체
케이스 3: 손상된 바이너리
- 입력: 체크섬 불일치
- 조치: 재다운로드
- 기대 결과: 체크섬 일치 후 정상 실행
수락 기준: 위 케이스별로 기대 결과가 달성되면 문제 해결로 판단합니다.
호환성 매트릭스(개념적)
- 동일 CPU 아키텍처 (예: x86_64 ↔ x86_64): 기본적으로 호환
- 64비트 ↔ 32비트 (동일 아키텍처): 32비트 라이브러리 설치 시 가능
- x86 ↔ ARM: 에뮬레이션(qemu) 또는 다른 머신 필요
- Windows PE ↔ Linux ELF: 호환 불가(와인 같은 레이어로 일부 실행 가능하지만 완전한 대체 아님)
베스트 프랙티스
- 배포 시 아키텍처 표기를 명확히 하라(패키지명/설치 가이드에 포함).
- 체크섬·서명(sha256, GPG) 제공으로 무결성 보장.
- 스크립트에는 항상 명확한 shebang을 추가하라.
- 다중 아키텍처가 필요한 환경은 컨테이너/VM 기반으로 분리 운영.
중요: 시스템 수준에서 이진을 임의로 패치하거나 헤더를 직접 수정하는 것은 권장하지 않습니다. 올바른 출처에서 재배포된 바이너리 또는 소스에서 재컴파일하는 것이 안전합니다.
문제 발생 시 SOP(표준 운영 절차)
- 오류 재현 및 로그 수집: 오류 메시지, file/readelf 결과 캡처.
- 무결성 검사: md5/sha256 체크섬 대조.
- 아키텍처 확인: uname -m, file 결과 비교.
- 권한 확인: ls -l 및 chmod 적용 테스트.
- 필요한 라이브러리 설치: ldd 결과로 의존성 해소.
- 에뮬레이터/컨테이너 사용 검토: qemu, Docker, VM.
- 결과 문서화 및 배포자 통지(필요 시).
언제 이 가이드로 해결되지 않는가(예외 사례)
- 바이너리가 플랫폼독립적이지만 런타임에 심각한 버그가 있는 경우
- 커널 자체가 특정 이진 포맷(예: 오래된 a.out)만을 지원하고 현대 포맷을 지원하지 않는 드문 환경
- 손상된 부트로더/파일시스템 문제로 파일 전체가 손상된 경우
이런 예외에서는 OS/커널 업그레이드, 파일시스템 검사(fsck), 또는 하드웨어 점검이 필요합니다.
참조용 명령 모음(치트시트)
# 파일 타입과 아키텍처 확인
file ./my_executable
readelf -h ./my_executable
objdump -f ./my_executable
# 현재 시스템 아키텍처
uname -m
# 권한 부여
chmod +x ./my_executable
# 라이브러리 의존성 확인
ldd ./my_executable
# 무결성 확인
sha256sum ./my_executable
# 32비트 런타임(예: Debian/Ubuntu)
dpkg --add-architecture i386
apt update
apt install libc6:i386 libstdc++6:i386
# qemu-user-static 설치 예시
apt install qemu-user-static
# 스크립트 CRLF 문제 해결
dos2unix my_script
요약 및 핵심 팁
- 먼저 file로 포맷과 아키텍처를 확인하세요.
- 단순 권한 문제인지, 아키텍처 불일치인지, 또는 파일 손상인지 단계적으로 분리합니다.
- 아키텍처가 다르면 올바른 바이너리 제공 또는 에뮬레이션/컨테이너 사용을 고려하세요.
- 배포자는 체크섬과 아키텍처 정보, 필수 런타임을 문서화해야 합니다.
요약: Exec Format Error는 원인이 명확한 경우가 많아 체계적으로 진단하면 대부분 짧은 시간 내 해결 가능합니다. 문제가 계속되면 오류 로그와 file/readelf 출력, 시스템 아키텍처 정보를 함께 제공하면 해결 속도가 빨라집니다.
추가 질문이 있거나 특정 상황(예: ARM 바이너리 on x86_64, Docker 환경 등)에 대한 상세한 단계가 필요하면 시스템 정보와 file/readelf 출력 결과를 붙여 질문해 주세요.
핵심 요약:
- 파일 타입/아키텍처 확인 → file, readelf
- 무결성 확인 → sha256sum
- 권한 확인 → chmod +x
- 아키텍처 불일치 → 올바른 바이너리 / 32비트 런타임 / qemu 또는 컨테이너
감사합니다.