「cannot execute binary: exec format error」:原因と解決策の徹底解説
はじめに
LinuxやUnix系OSを使用している際に、実行ファイルを起動しようとしたり、シェルスクリプトを実行しようとしたりしたとき、「cannot execute binary: exec format error」というエラーメッセージに遭遇することがあります。このエラーは、ユーザーを困惑させることが少なくありません。なぜなら、ファイルが存在し、権限も正しく設定されているように見えるのに、OSがそのファイルを「実行可能なバイナリ」として認識できない、あるいは実行するための情報が不足していることを示唆しているからです。
このエラーは単一の原因によって引き起こされるものではなく、その性質上、非常に多岐にわたる要因が考えられます。アーキテクチャの不一致、ファイル形式の不整合、ファイル破損、スクリプトの記述問題、さらにはカーネルやファイルシステム、セキュリティ設定に至るまで、様々なレベルで問題が発生する可能性があります。
本記事では、「cannot execute binary: exec format error」が発生する主な原因を詳細に掘り下げ、それぞれの原因に対する具体的な確認方法と解決策を網羅的に解説します。約5000語にわたる詳細な解説を通じて、読者がこのエラーに遭遇した際に、冷静かつ体系的に原因を特定し、解決に至るための知識と実践的なスキルを習得できることを目指します。
エラーメッセージの解釈:「exec format error」とは何か?
「cannot execute binary: exec format error」というエラーメッセージは、文字通り「バイナリを実行できません:実行形式エラー」という意味です。
LinuxやUnix系OSにおいて、プログラムを実行する際には、カーネルのシステムコールであるexecve()
(または関連するシステムコール群)が使用されます。このexecve()
システムコールは、指定されたファイルをプログラムとして実行しようとします。この際、カーネルは実行しようとしているファイルの内容を読み込み、そのファイルがどのような種類の実行ファイルであるかを識別し、メモリにロードして実行を開始するための様々な準備を行います。
「exec format error」は、この識別や準備の段階で問題が発生したことを示しています。具体的には、カーネルが以下のいずれか、または複数の理由により、指定されたファイルを有効な実行形式(フォーマット)を持つプログラムとして認識できない場合に発生します。
- ファイルがそもそも実行可能なバイナリ形式ではない。
- ファイルは実行可能なバイナリ形式だが、現在のシステム環境(CPUアーキテクチャ、OSのビット数など)とは互換性がない。
- ファイルは実行可能な形式であるはずだが、破損しているか、内容が不完全である。
- ファイルはスクリプトだが、実行に必要なインタプリタ情報(シバン行など)に問題がある。
- ファイルシステムやカーネルの設定により、そのファイルを実行する仕組みが有効になっていない。
- セキュリティ機構によって実行がブロックされている。
このエラーは、ファイルが存在しない場合や、ファイルに対する読み取り権限がない場合に表示される「No such file or directory」や「Permission denied」とは異なります。ファイル自体は存在し、多くの場合、読み取り権限も付与されているにもかかわらず、実行の「形式」に関する問題として報告されるのが特徴です。
主要な原因とその詳細な解説
「exec format error」の主な原因は以下のカテゴリに分類できます。それぞれの原因について、詳細な説明、確認方法、そして具体的な解決策を解説します。
原因1: アーキテクチャの不一致 (Architecture Mismatch)
これは「exec format error」の最も一般的な原因の一つです。コンパイル済みの実行ファイルは、特定のCPUアーキテクチャ(例: x86-64, ARM64, ARMv7など)および特定のビット数(32ビットまたは64ビット)向けにビルドされています。実行しようとしているシステムのCPUアーキテクチャやビット数が、そのバイナリが想定しているものと異なる場合に、このエラーが発生します。
詳細な説明:
- CPUアーキテクチャ: 現在主流のデスクトップ/サーバー向けCPUはx86-64 (AMD64) です。一方で、Raspberry Piのようなシングルボードコンピューターや多くのモバイルデバイスはARMアーキテクチャを使用しています。古いシステムではx86 (i386) 32ビットアーキテクチャもまだ使われています。バイナリは特定のアーキテクチャの命令セットで記述されているため、異なるアーキテクチャのCPU上では直接実行できません。
- ビット数: x86の場合、32ビット (i386) と64ビット (x86-64) があります。64ビットOS上で32ビットバイナリを実行することは可能ですが、そのためにはOS側に32ビット互換ライブラリ(例:
libc6:i386
など)がインストールされている必要があります。逆に、32ビットOS上で64ビットバイナリを実行することは、通常は不可能です。 - クロスコンパイル: 別のアーキテクチャ向けにコンパイルされたバイナリを、そのターゲットアーキテクチャではないホストシステム上で実行しようとした場合によく発生します。例えば、x86-64のPC上でARM向けにコンパイルされたバイナリを実行しようとする場合などです。
確認方法:
-
バイナリのアーキテクチャを確認する (
file
コマンド):
最も重要なコマンドです。実行しようとしているファイルがどのアーキテクチャ向けにビルドされているかを確認できます。
bash
file /path/to/your/executable
出力例とその解釈:ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l...
- これは 64ビットのx86-64アーキテクチャ 向けELFバイナリです。
ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/l...
- これは 32ビットのIntel 80386 (x86) アーキテクチャ 向けELFバイナリです。
ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/l...
- これは 64ビットのARM (aarch64) 向けELFバイナリです。
ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/l...
- これは 32ビットのARM 向けELFバイナリです。
file
コマンドの出力で、「executable」となっているにも関わらず、続くアーキテクチャ情報が実行しているシステムのアーキテクチャと一致しない場合、アーキテクチャの不一致が原因である可能性が高いです。 -
システムのアーキテクチャを確認する (
uname -m
,lscpu
コマンド):
現在実行しているシステムのCPUアーキテクチャを確認します。
bash
uname -m
出力例:x86_64
: 64ビットのx86-64アーキテクチャです。i686
またはi386
: 32ビットのx86アーキテクチャです。aarch64
: 64ビットのARMアーキテクチャです。armv7l
: 32ビットのARMv7アーキテクチャです。
より詳細なCPU情報は
lscpu
コマンドで確認できます。
bash
lscpu
Architecture
やCPU op-modes(s)
(32-bit, 64-bit) の項目を確認してください。
解決策:
-
適切なアーキテクチャ用のバイナリを入手/コンパイルする:
これが最も根本的な解決策です。実行したいプログラムを提供している場所(公式ウェブサイト、リポジトリ、コンパイル元のソースコードなど)から、現在使用しているシステムのアーキテクチャおよびビット数に合ったバージョンのバイナリを入手してください。
もしソースコードがある場合は、現在のシステム上で再コンパイルしてください。 -
64ビットOS上で32ビットバイナリを実行する場合(互換ライブラリのインストール):
多くの64ビットLinuxディストリビューションは、32ビットバイナリを実行するための互換機能を持っていますが、必要な32ビット版ライブラリがデフォルトでインストールされていない場合があります。この場合、必要なライブラリパッケージをインストールすることで解決できます。
パッケージ名はディストリビューションによって異なります。- Debian/Ubuntu系:
bash
sudo dpkg --add-architecture i386 # 32bitアーキテクチャを追加
sudo apt update
sudo apt install libc6:i386 libncurses5:i386 libstdc++6:i386 # 必要な32bitライブラリ例
実行しようとしているバイナリが依存する具体的なライブラリは、ldd /path/to/your/32bit/executable
コマンドで確認できます。「not found」となっている32ビット版ライブラリをインストールする必要があります。 - RHEL/CentOS/Fedora系:
bash
sudo yum install glibc.i686 libstdc++.i686 # 必要な32bitライブラリ例
またはdnf
を使用します。
bash
sudo dnf install glibc.i686 libstdc++.i686 - Arch Linux系:
multilib
リポジトリを有効にし、必要な32ビットライブラリをインストールします。
/etc/pacman.conf
を編集し、[multilib]
セクションのコメントアウトを解除します。
bash
[multilib]
Include = /etc/pacman.d/mirrorlist
その後、データベースを更新し、必要なライブラリをインストールします。
bash
sudo pacman -Sy
sudo pacman -S lib32-glibc lib32-gcc-libs # 必要な32bitライブラリ例
- Debian/Ubuntu系:
-
適切な実行環境を使用する:
クロスコンパイルされたバイナリや、現在のシステムとは異なるアーキテクチャ向けのバイナリを実行する必要がある場合は、そのバイナリが想定するアーキテクチャのシステムを用意する必要があります。これは、仮想マシン(VirtualBox, VMwareなど)、コンテナ(Dockerなど)、または別の物理マシンを使用することで実現できます。
特定のアーキテクチャをエミュレートするツール(例:qemu-user
)を使用する方法もありますが、パフォーマンスが低下することがあります。
原因2: ファイル形式の不一致または破損 (File Format Mismatch or Corruption)
Linux/Unixにおける標準的な実行可能ファイル形式はELF (Executable and Linkable Format) です。もし実行しようとしているファイルがELF形式ではない場合、またはELF形式であっても内容が破損している場合、OSはそれを実行可能なプログラムとして正しくロードできません。
詳細な説明:
- 非ELF形式のファイル:
- WindowsのPE (Portable Executable) ファイル:
.exe
,.dll
などの拡張子を持つファイル。これらはWindows専用の形式であり、Linux上で直接実行することはできません。 - macOSのMach-Oファイル: macOSの実行可能ファイル形式。Linux上では直接実行できません。
- 単なるデータファイル: テキストファイル、画像ファイル、アーカイブファイルなどを誤って実行しようとした場合。
- WindowsのPE (Portable Executable) ファイル:
- ファイル破損:
- ダウンロード中にファイルが不完全になった、またはエラーが発生した。
- ファイルをコピーする際にエラーが発生した。
- ファイルが保存されているストレージメディアに物理的な問題がある。
- ファイル自体がウイルスやマルウェアによって改変/破損された。
- スクリプトファイルをバイナリとして扱おうとした:
シェルスクリプトやPythonスクリプトなどのテキストファイルを実行しようとした際に、システムがそれをバイナリファイルとして誤って解釈しようとする場合があります(例えば、シバン行がない、または不適切である場合など)。
確認方法:
-
ファイルのタイプを確認する (
file
コマンド):
file
コマンドは、ファイルの内容を分析してそのタイプを特定します。実行形式かどうか、どのような形式か、破損している可能性があるかなどを判断するのに役立ちます。
bash
file /path/to/your/file
出力例とその解釈:/path/to/your/file: ELF 64-bit LSB executable, x86-64, ...
- これは期待通りのLinux実行可能なELFバイナリです。もしこれで
exec format error
が出るなら、アーキテクチャの不一致、ファイル破損、または他の高度な問題が考えられます。
- これは期待通りのLinux実行可能なELFバイナリです。もしこれで
/path/to/your/file: PE32+ executable (console) x86-64, for MS Windows
- これはWindowsのPE形式です。Linux上では直接実行できません。
/path/to/your/file: Mach-O 64-bit executable x86_64
- これはmacOSのMach-O形式です。Linux上では直接実行できません。
/path/to/your/file: ASCII text
または/path/to/your/file: Bourne-Again shell script, ASCII text, with CRLF line terminators
- これはテキストファイルまたはスクリプトファイルです。バイナリではありません。スクリプトの場合は、スクリプトとして実行する必要があります(後述の原因4参照)。
with CRLF line terminators
はWindows形式の改行コードを示しており、Linuxで問題を引き起こす可能性があります。
- これはテキストファイルまたはスクリプトファイルです。バイナリではありません。スクリプトの場合は、スクリプトとして実行する必要があります(後述の原因4参照)。
/path/to/your/file: data
- これは
file
コマンドがその形式を特定できなかったことを示します。バイナリである可能性も、単なるデータである可能性もあり、破損していることも考えられます。
- これは
-
ファイルのサイズやソースを確認する:
ダウンロードしたファイルの場合、ダウンロード元で示されているファイルサイズとローカルのファイルサイズが一致するか確認します。また、信頼できるソースからダウンロードしたか確認します。 -
ファイルのハッシュ値を確認する:
提供元がファイルのハッシュ値(MD5, SHA256など)を公開している場合、ダウンロードしたファイルのハッシュ値を計算して一致するか確認します。一致しない場合は、ファイルが破損しているか改ざんされています。
bash
sha256sum /path/to/your/file
解決策:
- 適切な形式のファイルを使用する:
- WindowsやmacOSの実行ファイルの場合は、Linux互換の代替プログラムを探すか、互換レイヤー(Wine)を使用するか、仮想マシン上でWindows/macOSを起動して実行することを検討してください。
- スクリプトファイルの場合は、後述の「原因4: スクリプトのシバン行またはインタプリタの問題」を参照し、スクリプトとして正しく実行するための設定を確認してください。
- ファイルを再ダウンロードまたは再構築する:
ファイルが破損している可能性がある場合は、再度ダウンロードするか、ソースコードから再コンパイルするなどして、ファイルを新しく入手してください。可能であれば、異なるミラーサイトやダウンロード方法(例:wget
,curl
の代わりにブラウザ、FTPの代わりにHTTPなど)を試してみてください。 - ファイルの整合性を確認する:
提供されている場合は、ハッシュ値を確認します。 - ストレージの問題を診断する:
ディスクやSSDに問題がある可能性がある場合は、ファイルシステムチェック(fsck
コマンドなど)や、ディスク診断ツールを使用することを検討します。
原因3: ファイル権限の問題 (File Permission Issues)
Linux/Unixでは、ファイルを実行するためにはそのファイルに実行権限(execute permission)が付与されている必要があります。この権限が付与されていない場合、システムはファイルを読み取ることはできても、プログラムとして実行することはできません。
詳細な説明:
- 実行権限 ‘x’:
ls -l
コマンドの出力で、所有者、グループ、その他のユーザーに対して ‘x’(実行)の文字が表示されている必要があります。例えば-rwxr-xr-x
は、所有者には読み取り/書き込み/実行、グループとその他のユーザーには読み取り/実行権限があることを示します。 - ファイルシステムのマウントオプション ‘noexec’: ファイルシステムが
noexec
オプション付きでマウントされている場合、そのファイルシステム上のどのファイルも実行できなくなります。これは、/tmp
ディレクトリなどがセキュリティ上の理由でよくこのオプション付きでマウントされるケースがあります。 - スクリプトファイルの場合: バイナリファイルだけでなく、シェルスクリプトや他のスクリプトファイルも、直接
./script.sh
のように実行するには実行権限が必要です。ただし、bash script.sh
のようにインタプリタを明示して実行する場合は、スクリプトファイル自体には実行権限は必須ではなく、読み取り権限があれば実行できます。しかし、エラーメッセージが「exec format error」である場合、多くは./script.sh
のように直接実行しようとしていて、かつ権限またはシバン行に問題があるケースが考えられます。
確認方法:
-
ファイルの権限を確認する (
ls -l
コマンド):
bash
ls -l /path/to/your/file
出力の最初の10文字を確認します。例えば、-rw-r--r--
のように ‘x’ が一つも含まれていない場合、実行権限がありません。 -
ファイルシステムのマウントオプションを確認する (
mount
コマンド):
ファイルが存在するファイルシステムがnoexec
オプション付きでマウントされているか確認します。
bash
mount
出力の中から、該当するファイルシステムの行を探し、括弧内のオプションにnoexec
が含まれていないか確認します。
解決策:
-
実行権限を付与する (
chmod
コマンド):
ファイルに実行権限が付与されていない場合は、chmod
コマンドを使用して権限を追加します。所有者のみに実行権限を付与する場合:
bash
chmod u+x /path/to/your/file
すべてのユーザーに実行権限を付与する場合:
bash
chmod +x /path/to/your/file
実行権限を付与した後、再度ls -l
で確認し、権限が追加されていることを確認してください。 -
ファイルシステムのマウントオプションを変更する:
ファイルシステムがnoexec
でマウントされている場合は、そのオプションを削除して再マウントする必要があります。これは通常、システムの設定ファイルである/etc/fstab
を編集して行います。/etc/fstab
をテキストエディタで開きます(要root権限)。- 該当するファイルシステムの行を見つけ、オプションリストから
noexec
を削除し、代わりにexec
を追加または確認します。 - 変更を保存します。
- ファイルシステムを再マウントします。
bash
sudo mount -o remount,exec /path/to/mount_point
またはシステムを再起動します。
注意: システムパーティション(ルート/
など)やセキュリティ上重要なパーティション(/tmp
など)のマウントオプションを変更する場合は、システム全体のセキュリティや安定性に影響を与える可能性があるため、十分注意して行ってください。
原因4: スクリプトのシバン行またはインタプリタの問題 (Shebang or Interpreter Issues in Scripts)
シェルスクリプト、Pythonスクリプト、Perlスクリプトなどのインタプリタ型言語で書かれたファイルを実行可能にするには、ファイルの先頭行に「シバン行 (shebang line)」を記述するのが一般的です。このシバン行は #!
で始まり、そのスクリプトを実行するためのインタプリタへのパスを指定します(例: #!/bin/bash
, #!/usr/bin/python3
)。
「exec format error」がスクリプトファイルで発生する場合、以下の問題が考えられます。
詳細な説明:
- シバン行が間違っている、または存在しない: システムはシバン行を見て、どのプログラムでスクリプトを実行すればよいかを判断します。シバン行がない場合、システムはそれをバイナリとして実行しようとして失敗することがあります。また、シバン行に書かれたパスが間違っている(例:
/bin/bash
ではなく/usr/bin/bash
であるべきなど)場合も問題になります。 - 指定されたインタプリタが存在しない: シバン行に指定されたインタプリタ(例:
/usr/bin/python3
)がシステムにインストールされていない、または指定されたパスに存在しない場合。 - インタプリタ自体に問題がある: シバン行で指定されたインタプリタプログラム自体が、アーキテクチャの不一致や権限の問題などで実行できない場合。
- Windows形式の改行コード: Windows環境で作成・編集されたスクリプトファイルは、行末にCRLF (
\r\n
) という改行コードを使用します。LinuxはLF (\n
) を使用します。シバン行を含むファイルの先頭にCR (\r
) があると、システムがシバン行を正しく解釈できず、エラーとなることがあります。例えば#!/bin/bash\r
と認識されてしまい、/bin/bash\r
という名前のインタプリタを探しに行ってしまいます。
確認方法:
- シバン行を確認する (
head
コマンド):
ファイルの最初の数行(特に1行目)を確認します。
bash
head -n 1 /path/to/your/script.sh
シバン行 (#!...
) が正しく記述されているか確認します。パスが絶対パスであるか確認します。 - ファイルのタイプを確認する (
file
コマンド):
file
コマンドの出力で、ファイルがスクリプトとして認識されているか、改行コードに問題がないかを確認します。
bash
file /path/to/your/script.sh
出力例:/path/to/your/script.sh: Bourne-Again shell script, ASCII text, with CRLF line terminators
のようにCRLF line terminators
が表示されていないか確認します。 - インタプリタの存在とパスを確認する (
which
コマンド):
シバン行に指定されているインタプリタがシステムに存在するか、またそのパスが正しいか確認します。例えばシバン行が#!/usr/bin/python3
なら:
bash
which python3
出力されるパスがシバン行と一致するか、またコマンドが見つかるか確認します。 - インタプリタ自体の実行可能性を確認する:
which
で確認したインタプリタのパスに対し、file
コマンドを実行して、そのインタプリタバイナリ自体に問題がないか確認します(アーキテクチャ不一致など)。
解決策:
- 正しいシバン行を記述する:
スクリプトファイルの1行目に、適切なインタプリタへの絶対パスを含むシバン行を正確に記述します。
例:- Bashスクリプト:
#!/bin/bash
- Pythonスクリプト:
#!/usr/bin/env python3
(または#!/usr/bin/python3
など、which python3
の出力で確認) - Perlスクリプト:
#!/usr/bin/perl
#!/usr/bin/env <interpreter_name>
の形式は、インタプリタが/usr/bin
以外の場所にインストールされている場合でも、システムのPATH環境変数を使ってインタプリタを見つけてくれるため、よりポータブルです。
- Bashスクリプト:
- 必要なインタプリタをインストールする:
シバン行で指定されたインタプリタがシステムにインストールされていない場合は、パッケージマネージャーを使ってインストールします(例:sudo apt install python3
,sudo yum install perl
)。 - 改行コードを変換する:
Windows形式のCRLF改行コードが原因の場合は、LFのみに変換します。dos2unix
コマンドが便利です。
bash
sudo apt install dos2unix # Debian/Ubuntu系の場合
sudo yum install dos2unix # RHEL/CentOS/Fedora系の場合
dos2unix /path/to/your/script.sh
dos2unix
コマンドが使えない場合は、sed
コマンドでも変換できます。
bash
sed -i 's/\r//' /path/to/your/script.sh - インタプリタを明示して実行する:
シバン行の問題や権限の問題を回避するために、スクリプトをインタプリタを明示して実行することもできます。
bash
bash /path/to/your/script.sh
python3 /path/to/your/script.py
この方法の場合、スクリプトファイル自体に実行権限は不要です(読み取り権限は必要)。エラーメッセージが「exec format error」ではなくなった場合は、原因はスクリプトのシバン行または権限設定にあった可能性が高いです。
原因5: カーネルまたはファイルシステムの問題 (Kernel or Filesystem Issues)
より低レベルな部分、つまりOSの心臓部であるカーネルや、ファイルが格納されているファイルシステム自体に問題がある場合も、「exec format error」が発生することがあります。
詳細な説明:
- バイナリフォーマットローダーの問題 (binfmt_misc): Linuxカーネルは、様々な実行可能ファイル形式(ELFだけでなく、Java
.class
ファイル、Pythonスクリプトなどを直接実行可能にするための設定など)を処理するための仕組みbinfmt_misc
を持っています。この設定が壊れている、または特定のフォーマット(特にELF)を処理するためのモジュールがロードされていない場合、正しく実行形式を認識できなくなることがあります。 - ファイルシステムドライバーの問題: ファイルシステムの種類(ext4, XFS, NFS, FUSEなど)によっては、特定の状況下で実行に関連する問題が発生する可能性があります。特にネットワークファイルシステム (NFS) やFUSEベースのファイルシステムでは、設定や安定性によって問題が生じやすい場合があります。
- ファイルシステムの破損: ファイルシステム自体が破損している場合、ファイルの内容が正しく読み取れず、実行形式として認識できないことがあります。
- カーネルの不具合: 稀ですが、カーネルのバグによって特定の実行形式が正しく処理されない可能性もゼロではありません。
確認方法:
- カーネルログを確認する (
dmesg
):
システム起動時やプログラム実行時にカーネルレベルで発生したエラーメッセージが記録されています。エラー発生直後にdmesg
コマンドを実行し、関連するログ(execve
,binfmt
などを含むメッセージ)がないか確認します。
bash
dmesg | tail
dmesg | grep -i exec
dmesg | grep -i binfmt binfmt_misc
の設定を確認する:
/proc/sys/fs/binfmt_misc
ディレクトリには、現在カーネルが認識しているバイナリフォーマットローダーの設定が表示されます。
bash
ls /proc/sys/fs/binfmt_misc/
cat /proc/sys/fs/binfmt_misc/register # 現在登録されているハンドラー
cat /proc/sys/fs/binfmt_misc/elf # ELFハンドラーが有効か確認
elf
ファイルの内容がenabled
になっているか確認します。- ファイルシステムをチェックする (
fsck
):
問題のファイルが存在するファイルシステムに対し、整合性チェックを実行します。これは通常、ファイルシステムをアンマウントした状態で行う必要があります。
bash
# 例: /dev/sda1 の場合 (アンマウントが必要)
sudo umount /dev/sda1
sudo fsck /dev/sda1
注意: ルートファイルシステム (/
) のfsck
は、システム起動時のリカバリモードなどで行うのが一般的です。稼働中のシステムパーティションに対して安易にfsck
を実行しないでください。 - ファイルシステムの種類を確認する (
mount
または/etc/fstab
):
mount
コマンドの出力や/etc/fstab
ファイルで、該当ファイルシステムの種類(ext4, xfs, nfs, fuseなど)を確認します。特定のファイルシステムでの既知の問題がないか検索することができます。
解決策:
binfmt_misc
設定を確認・修正する:
通常、ELFフォーマットのハンドリングはデフォルトで有効になっています。もしelf
の状態がdisabled
になっていたり、ファイル自体が存在しない場合は、binfmt_misc
サービスや関連カーネルモジュールに問題がある可能性があります。システムサービス (systemctl status systemd-binfmt.service
) を確認したり、必要であればカーネルモジュールをロードしたりします(通常は自動)。非常に稀なケースであり、一般的なユーザーが手動で修正することは少ないです。- ファイルシステムの問題を修復する:
fsck
でファイルシステムの破損が見つかった場合は、修復を試みます。重要なデータは事前にバックアップしておきましょう。 - 別のファイルシステムにコピーして実行してみる:
ファイルシステム自体の問題(権限、属性、特殊なマウントオプションなど)を切り分けるために、問題のファイルを別の標準的なファイルシステム(例:/tmp
ディレクトリや別のパーティションのext4ファイルシステム)にコピーし、そこで実行してみます。もしコピー先で実行できる場合、元のファイルシステムに問題がある可能性が高いです。 - カーネルのアップデートまたはダウングレード:
もしカーネルの不具合が疑われる場合は、カーネルを最新バージョンにアップデートするか、問題が発生しなかった以前のバージョンにダウングレードすることを検討します。これは上級者向けの操作であり、システムにリスクを伴う可能性があります。
原因6: SELinux/AppArmorなどのセキュリティ機構 (SELinux/AppArmor or Other Security Mechanisms)
SELinux (Security-Enhanced Linux) や AppArmor のような強制アクセス制御 (MAC) セキュリティフレームワークは、システム上のプログラムが実行できる操作を細かく制限できます。これらのポリシーによって、特定のプログラムの実行自体がブロックされている場合、「exec format error」と表示されることがあります。
詳細な説明:
- セキュリティポリシーによるブロック: SELinuxやAppArmorは、プログラムの種類や実行コンテキストに基づいて、ファイルへのアクセス、ネットワーク通信、他のプログラムの起動などを制限します。厳格なポリシーが設定されている場合、新しくインストールしたプログラムや、通常とは異なる場所にあるプログラムの実行がポリシー違反とみなされ、ブロックされることがあります。
- 監査ログへの記録: セキュリティ機構によってブロックされた操作は、通常、システムやセキュリティ関連のログファイル(特に監査ログ)に記録されます。
確認方法:
- SELinuxの状態を確認する:
bash
getenforce
出力がEnforcing
の場合、SELinuxが有効かつ強制モードで動作しています。Permissive
は警告のみ、Disabled
は無効です。
より詳細なステータスはsestatus
で確認できます。 - AppArmorの状態を確認する:
AppArmorがインストールされ有効な場合、以下のコマンドで状態を確認できます。
bash
sudo aa-status - 監査ログを確認する:
SELinuxによる拒否は、監査ログに記録されます。ログファイルの場所はディストリビューションによって異なりますが、一般的には/var/log/audit/audit.log
です。
bash
sudo tail /var/log/audit/audit.log
sudo grep AVC /var/log/audit/audit.log # SELinuxのアクセス拒否ログを検索
AppArmorのログは、syslogやカーネルログ (dmesg
) に出力されることが多いです。
bash
dmesg | grep -i apparmor
解決策:
- セキュリティポリシーを調整する:
これが推奨される方法ですが、複雑な操作が必要です。SELinuxの場合は、監査ログのAVCメッセージを解析し、audit2allow
のようなツールを使ってポリシーモジュールを生成・ロードすることで、特定の操作を許可することができます。AppArmorの場合は、プロファイルを編集または再学習 (aa-genprof
,aa-complain
など) します。これらの操作は、セキュリティの専門知識を必要とします。 - 一時的にPermissiveモードにする(トラブルシューティング目的):
原因がSELinux/AppArmorにあるかを切り分けるために、一時的にポリシーを強制しないPermissiveモードに変更することができます。- SELinux:
sudo setenforce Permissive
- AppArmor:
sudo aa-complain /path/to/your/executable
またはsudo service apparmor reload
(プロファイルをコンプレインモードに変更後)
この状態で再度プログラムを実行してみて、エラーが発生しなくなった場合、原因はセキュリティポリシーにあった可能性が高いです。ただし、Permissiveモードはセキュリティレベルを低下させるため、原因特定後は速やかにEnforcingモードに戻し、適切なポリシー調整を行うべきです。 本番環境では、原則として無効化や恒久的なPermissiveモードの使用は推奨されません。
- SELinux:
- セキュリティ機構を無効化する(非推奨):
トラブルシューティングの最終手段として、SELinuxやAppArmor自体を完全に無効化することも可能ですが、これはシステムのセキュリティを著しく低下させるため、本番環境では絶対に行わないでください。 無効化は通常、起動設定(カーネルパラメータや/etc/sysconfig/selinux
などの設定ファイル)を変更して行い、システム再起動が必要です。
原因7: ライブラリの依存関係または動的リンカーの問題 (Library Dependencies or Dynamic Linker Issues)
実行ファイルが他の共有ライブラリに依存している場合、それらのライブラリが見つからない、または互換性のないバージョンである場合に実行エラーが発生します。通常、この種のエラーは「No such file or directory (for library)」や「symbol lookup error」などのメッセージで報告されることが多いですが、特定の状況、特に32ビットバイナリを64ビット環境で実行しようとして32ビットライブラリが不足しているようなケースでは、「exec format error」と関連して発生することもあります。
詳細な説明:
- 不足している共有ライブラリ: 実行ファイルがロードされる際に、そのファイルが必要とする
.so
などの共有ライブラリがシステム上の標準的なパスに見つからない。 - ライブラリのバージョン不一致: 見つかったライブラリが、実行ファイルがビルドされた際に想定されていたバージョンと異なるため、必要な関数やシンボルが見つからない。
- 動的リンカーの問題: 実行ファイルをロードし、必要なライブラリを見つけてリンクする役割を担う動的リンカー (
/lib/ld-linux.so.X
や/lib64/ld-linux-x86-64.so.X
など) 自体に問題がある場合。
確認方法:
- 依存ライブラリを確認する (
ldd
コマンド):
実行ファイルが依存している共有ライブラリのリストを確認します。
bash
ldd /path/to/your/executable
出力で「not found」となっているライブラリがないか確認します。32ビットバイナリの場合は、32ビット版のライブラリへの依存が表示されます。
bash
ldd /path/to/your/32bit/executable # 32bitバイナリの場合
ldd
自体が「not a dynamic executable」や類似のエラーを出す場合、そのファイルはスタティックリンクされているか、実行可能なELF形式ではない可能性があります(原因2)。 - 実行トレースを確認する (
strace
コマンド):
プログラムが実行される際にカーネルが実行するシステムコールをトレースします。ファイルのオープン、ライブラリのロードなどの詳細な過程を確認でき、問題箇所を特定するのに役立ちます。
bash
strace /path/to/your/executable
出力で、ファイルオープン(openat
,open
)が失敗している箇所や、execve
コール自体の詳細を確認します。エラーコード (ENOEXEC
など) が表示されることがあります。
解決策:
- 不足しているライブラリをインストールする:
ldd
の出力で「not found」となっているライブラリを、パッケージマネージャーを使ってインストールします。32ビットバイナリの場合は、対応する32ビット版ライブラリパッケージを探してインストールします(原因1の解決策参照)。
どのパッケージに特定のライブラリファイルが含まれているかは、ディストリビューションの検索機能(例: Debian/Ubuntuのapt-file search <library_file_name>
、RHEL/CentOSのyum provides <library_file_name>
またはdnf provides <library_file_name>
)で調べられます。 - 環境変数
LD_LIBRARY_PATH
を設定する:
特定のディレクトリにあるライブラリを使用させたい場合は、LD_LIBRARY_PATH
環境変数にそのディレクトリのパスを設定して実行します。これは開発環境やテストなどで一時的に使用する方法であり、システム全体に設定することは推奨されません。
bash
export LD_LIBRARY_PATH=/path/to/your/libraries:$LD_LIBRARY_PATH
/path/to/your/executable - Rpath/Runpath の確認:
実行ファイル自体に特定のライブラリパス情報(Rpath/Runpath)が埋め込まれている場合があります。これはobjdump -x /path/to/your/executable | grep RPATH
で確認できます。もしそこに古いパスや存在しないパスが指定されている場合、問題の原因となることがあります。解決には通常、ソースからの再コンパイルが必要です。 - 動的リンカーの確認:
ldd
の出力で、動的リンカー自体のパスが表示されます(例:/lib64/ld-linux-x86-64.so.2
)。このファイルが破損しているか、誤ったバージョンになっている場合は、システムの基本的なライブラリ(glibcなど)に問題がある可能性が高く、システムパッケージの再インストールやシステムの復旧が必要になる場合があります。
トラブルシューティングの手順
「cannot execute binary: exec format error」に遭遇した場合、以下の手順で体系的に原因を特定し、解決策を試すことをお勧めします。
- エラーメッセージを正確に確認する:
表示されたエラーメッセージを正確に把握します。「exec format error」以外の付随情報(ファイル名、追加のエラーコードなど)がないか確認します。 - ファイルの存在と読み取り権限を確認する:
まず基本として、実行しようとしているファイルが指定されたパスに存在するか、そしてそのファイルに対する読み取り権限が実行ユーザーにあるかを確認します。
bash
ls -l /path/to/your/file
ファイルが存在しない、または読み取り権限がない場合は、それぞれ「No such file or directory」や「Permission denied」エラーになるはずですが、稀に別のエラーとして現れることもあります。 file
コマンドでファイルタイプとアーキテクチャを確認する (最も重要):
bash
file /path/to/your/file
この出力は、ファイルがどのような種類のファイルであり、どのようなアーキテクチャ向けにビルドされているかを示す最も重要な手がかりです。ELF executable
: バイナリ形式。アーキテクチャ (x86-64
,ARM
,Intel 80386
など) を確認します。script
: スクリプト形式。シバン行や改行コードに問題がないか確認します(手順5へ)。PE
,Mach-O
: WindowsまたはmacOSの形式。Linuxでは直接実行できません(原因2)。data
,ASCII text
など: 実行ファイルとして認識されていない。目的のファイルか、破損していないか確認します(原因2)。
- システムアーキテクチャと比較する:
手順3で確認したバイナリのアーキテクチャと、現在のシステムアーキテクチャを比較します。
bash
uname -m
アーキテクチャやビット数が異なる場合は、原因1の解決策(適切なバイナリの入手、互換ライブラリのインストールなど)を試します。 - ファイル権限を確認し、必要なら実行権限を付与する:
bash
ls -l /path/to/your/file
実行権限 (‘x’) がない場合は、chmod +x /path/to/your/file
で付与します(原因3)。
もしファイルシステムがnoexec
でマウントされていないかも確認します(mount
コマンド、原因3)。 - スクリプトの場合はシバン行とインタプリタを確認する:
file
コマンドでスクリプトと判断された場合、以下の点を確認します(原因4)。head -n 1 /path/to/your/script
でシバン行をチェック。- シバン行のインタプリタパスを
which
で確認。 file
コマンド出力にCRLF line terminators
がないか確認。
シバン行の修正、インタプリタのインストール、改行コードの変換を行います。
ldd
で依存ライブラリを確認する:
file
コマンドでELFバイナリと判断されたが実行できない場合、必要な共有ライブラリが不足していないか確認します(特に32ビットバイナリの場合)。
bash
ldd /path/to/your/executable
「not found」があれば、対応するライブラリパッケージをインストールします(原因7)。strace
で実行トレースを確認する:
上記の手順で原因が特定できない場合、strace
でプログラムの実行をトレースし、システムコールレベルでのエラーを確認します。
bash
strace /path/to/your/file
execve()
システムコールの呼び出しや、その後のファイルオープン、メモリマッピングなどでエラー(特にENOEXEC
)が発生していないか詳細にログを調べます。- カーネルログ (
dmesg
) やシステムログを確認する:
カーネルやシステムレベルでのエラーが発生している可能性があるため、ログを確認します。特にエラー発生直後のログが重要です(原因5, 6)。
bash
dmesg | tail
sudo journalctl -xe # systemd環境の場合 - SELinux/AppArmor の状態を確認する:
セキュリティ機構が有効になっている場合、一時的にPermissiveモードにして実行できるか確認します(原因6)。原因特定後はポリシーの調整を行います。
bash
getenforce # SELinux
sudo aa-status # AppArmor
一時的に変更:sudo setenforce Permissive
またはsudo aa-complain /path/to/your/file
- ファイルのソースやファイルシステムを確認する:
ダウンロードしたファイルの場合は、ダウンロード元や方法を変えて再入手してみます。ファイルがネットワークファイルシステム(NFSなど)上にある場合は、ローカルにコピーして実行できるか確認します(原因2, 5)。ファイルシステムの破損も考慮します(原因5)。
これらの手順を順に実行することで、ほとんどの「exec format error」の原因を特定し、適切な解決策を見つけることができるはずです。
特定のシナリオとケーススタディ
Dockerコンテナ内でのエラー
Dockerコンテナは、ホストOSとは独立した環境を提供しますが、内部で使用されるベースイメージは特定のOSやアーキテクチャに基づいています。コンテナ内で「exec format error」が発生する場合、以下の原因が考えられます。
- ホストとコンテナのアーキテクチャ不一致: 例えば、x86-64ホスト上でARMベースのコンテナイメージを実行しようとする、またはその逆の場合。QEMUなどのエミュレーターが使用されますが、互換性の問題が生じることがあります。
- コンテナイメージ内のアーキテクチャ不一致: コンテナイメージ自体が、異なるアーキテクチャ向けのバイナリを含んでいる場合。
- ベースイメージと追加バイナリのアーキテクチャ不一致: x86-64のベースイメージに、誤って32ビットのx86バイナリやARMバイナリを追加した場合。
- コンテナ内の必要なライブラリ不足: 特に32ビットバイナリを64ビットコンテナ内で実行する場合など、互換ライブラリがイメージに含まれていない場合。
- Scratchイメージや最小限イメージ使用時の問題: 極端に小さなコンテナイメージ(Alpine Linuxなど)では、基本的なライブラリやシェル(Bashなど)、インタプリタがデフォルトで含まれていない場合があります。
- ボリュームマウントされたファイルの権限や形式: ホストからコンテナにボリュームとしてマウントされた実行ファイルが、コンテナ内のファイルシステムで実行可能になっていない、またはホスト側の属性を引きずっている場合。
解決策:
- コンテナイメージのアーキテクチャを確認する:
docker inspect <image_name>
コマンドの出力でArchitecture
を確認します。ホストと一致しない場合は、適切なアーキテクチャのイメージを選択するか、マルチアーキテクチャイメージを構築/使用します。 - Dockerfile を確認する: バイナリのコピー元や、インストールしているパッケージを確認し、ターゲットアーキテクチャに合ったものを選んでいるか確認します。32ビットバイナリを含める場合は、
Dockerfile
内でdpkg --add-architecture i386
やyum install *.i686
など、32ビット互換パッケージのインストールを含める必要があります。 - 必要なパッケージ(ライブラリ、インタプリタ)をインストールする: 最小限のイメージを使用している場合は、
apk add
,apt-get install
,yum install
などで必要なランタイム(libc、インタプリタなど)を追加します。 - ボリュームマウントのオプションを確認する: Docker Compose の
volumes
設定などで、実行権限が正しく設定されているか確認します。
クロスコンパイル環境でのエラー
あるアーキテクチャのシステム(ホスト)で、別のアーキテクチャ(ターゲット)向けのバイナリをコンパイルすることをクロスコンパイルといいます。この環境で、誤ってターゲット向けのバイナリをホスト上で実行しようとすると、「exec format error」が発生します。
詳細な説明:
- ターゲットバイナリの誤実行: ビルドプロセスで生成されたターゲット向けの実行ファイルやテストバイナリを、ターゲット環境ではなく開発用のホスト環境で直接実行しようとした。
解決策:
- ターゲット環境で実行する: クロスコンパイルされたバイナリは、そのターゲットアーキテクチャのシステム(物理デバイス、仮想マシン、エミュレーター、コンテナなど)で実行する必要があります。
- エミュレーターを使用する: ホスト上でターゲットアーキテクチャのバイナリを実行するために、QEMU User Emulation のようなツールを使用することができます。例えば、
qemu-aarch64 /path/to/arm64/executable
のように実行します。これをbinfmt_misc
と組み合わせて、透過的に実行できるように設定することも可能です。 - ホスト上で実行可能なツール(ビルドツールなど)とターゲットバイナリを区別する: クロスコンパイル環境では、ホスト上で実行されるコンパイラやビルドツールと、ターゲット向けに生成される成果物(バイナリ)を明確に区別し、誤ってターゲットバイナリをホスト上で実行しないように注意が必要です。
ネットワークファイルシステム (NFS) 上でのエラー
NFSのようなネットワークファイルシステム上で実行ファイルを実行しようとした際に、エラーが発生する場合があります。
詳細な説明:
- NFSマウントオプション: NFSクライアント側で
noexec
オプション付きでマウントされている場合、そのボリューム上のファイルは実行できません(原因3と同様)。 - ファイル属性の不整合: クライアントとサーバー間でファイル属性(権限など)が正しく同期されない、または解釈が異なる場合。
- ネットワークの問題やNFSサーバーの不安定性: ファイル内容の読み取りが途中で中断されたり、不正なデータが返されたりすることで、カーネルが実行形式を正しく認識できなくなる。
- User ID/Group ID (UID/GID) マッピングの問題: NFSv4などではUID/GIDマッピングが行われますが、設定ミスがあるとファイルの所有者や権限が正しく認識されない場合があります。
解決策:
- クライアント側のNFSマウントオプションを確認する:
/etc/fstab
やmount
コマンドの出力で、該当するNFSマウントにnoexec
オプションが付いていないか確認します。付いている場合はexec
に変更して再マウントします(原因3と同様)。 - ローカルにコピーして実行してみる: 問題のファイルをNFSボリュームからローカルのファイルシステムにコピーし、そこで実行できるか確認します。もしローカルでは実行できる場合、NFSのマウント設定やネットワーク、サーバー側の問題が原因である可能性が高いです。
- NFSサーバーとクライアントの設定を確認する: エクスポートオプション(
no_root_squash
,all_squash
など)、バージョン、UID/GIDマッピング設定などを確認します。 - ネットワークの安定性を確認する: ネットワーク遅延やパケットロスが問題を引き起こしていないか確認します。
まとめ
「cannot execute binary: exec format error」は、Linux/Unix環境でプログラム実行時によく遭遇するエラーですが、その原因は単一ではなく、ファイルそのものの属性、実行環境、権限、さらに低レベルなカーネルやファイルシステム、セキュリティ機構に至るまで、多岐にわたります。
本記事で解説した主な原因は以下の通りです。
- アーキテクチャの不一致: バイナリが想定するCPUやビット数が、実行システムのそれと異なる。
- ファイル形式の不一致または破損: LinuxのELF形式ではないファイル(Windows PE, macOS Mach-Oなど)を実行しようとした、またはファイルが破損している。
- ファイル権限の問題: 実行ファイルに実行権限がない、またはファイルシステムが
noexec
でマウントされている。 - スクリプトのシバン行またはインタプリタの問題: スクリプトファイルのシバン行が不正、インタプリタが存在しない、または改行コードがWindows形式。
- カーネルまたはファイルシステムの問題: バイナリフォーマットローダーの設定、ファイルシステムドライバーの問題、ファイルシステムの破損など。
- SELinux/AppArmorなどのセキュリティ機構: セキュリティポリシーによって実行がブロックされている。
- ライブラリの依存関係または動的リンカーの問題: 必要な共有ライブラリが見つからない(特に32ビット環境関連)。
これらの原因を特定するための最も重要な最初のステップは、file
コマンドを使用して対象ファイルのタイプとアーキテクチャを確認することです。続くステップとして、ls -l
で権限を確認し、必要に応じて ldd
で依存ライブラリ、head
でスクリプトのシバン行、mount
でファイルシステムオプション、dmesg
や監査ログでシステムレベルのエラー、strace
で実行トレースを詳細に調査します。
体系的なトラブルシューティングの手順を踏むことで、原因を絞り込み、適切な解決策(適切なバイナリの入手、権限の変更、ライブラリのインストール、スクリプトの修正、ファイルシステムの修復、セキュリティポリシーの調整など)を適用することができます。
このエラーは、OSがどのように実行ファイルを認識し、ロードするかの仕組みを理解する良い機会でもあります。本記事が、「exec format error」に遭遇した際の冷静な対処と問題解決の一助となれば幸いです。