Linuxでファイルを実行したら「No such file or directory」と言われた時には？

# What's？

Linux上で、ファイルを実行した時に「No such file or directory」と言われることがあります。

OSとファイルの想定しているアーキテクチャ（32bit or 64bit）が異なることが理由だったりするのですが、軽く見てみましょう。


# 環境

CentOS 8で確認します。

```shell
$ cat /etc/redhat-release 
CentOS Linux release 8.3.2011


$ uname -srvmpio
Linux 4.18.0-240.1.1.el8_3.x86_64 #1 SMP Thu Nov 19 17:20:08 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
```


# Liberica OpenJDKで確認

Liberica OpenJDKには、64bit用のものも32bit用のものもあるので、こちらで例を示しましょう。

[Liberica OpenJDK Download Center](https://bell-sw.com/pages/downloads/)

OpenJDK 11の64bit版をダウンロードして実行。

```shell
$ curl -sL -o - https://download.bell-sw.com/java/11.0.9.1+1/bellsoft-jdk11.0.9.1+1-linux-amd64.tar.gz | \
  tar zxvf -

$ ll jdk-11.0.9.1/bin/java
-rwxrwxr-x. 1 xxxxx xxxxx 13080 Nov  2 19:33 jdk-11.0.9.1/bin/java

$ jdk-11.0.9.1/bin/java --version
openjdk 11.0.9.1 2020-11-04 LTS
OpenJDK Runtime Environment (build 11.0.9.1+1-LTS)
OpenJDK 64-Bit Server VM (build 11.0.9.1+1-LTS, mixed mode)
```

こちらは、問題なく実行できます。

続いて、32bit版をダウンロードして同じことをしてみましょう。  
※展開されるディレクトリ名は、64bit版と同じなので注意してください

```shell
$ curl -sL -o - https://download.bell-sw.com/java/11.0.9.1+1/bellsoft-jdk11.0.9.1+1-linux-i586.tar.gz | \
  tar zxvf -

$ ll jdk-11.0.9.1/bin/java
-rwxrwxr-x. 1 xxxxx xxxxx 7484 Nov  2 19:49 jdk-11.0.9.1/bin/java

$ jdk-11.0.9.1/bin/java --version
-bash: jdk-11.0.9.1/bin/java: No such file or directory
```

32bit版の場合は「No such file or directory」と言われて実行できません。


# どうやって気づけばいい？

これ、けっこう不可解なんですけど「そんなファイルないよ」と言われている割には、実はファイル自体にはアクセスできています。

`ls`で見れていましたからね。

```shell
$ ll jdk-11.0.9.1/bin/java
-rwxrwxr-x. 1 xxxxx xxxxx 7484 Nov  2 19:49 jdk-11.0.9.1/bin/java
```

実際のところは、「実行できない」が正解です。

この状態は知らないとけっこう難しい気がしますが、`file`コマンドの実行結果がヒントになります。

```shell
$ file jdk-11.0.9.1/bin/java
jdk-11.0.9.1/bin/java: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.18, BuildID[sha1]=8cd726d22f9eaf779fdd9aa466608bf20e61c63f, not stripped
```

`ELF 32-bit LSB executable`と言われているので、32bit版の実行ファイルです。

一方で64bit版は、こういう表示になります。

```shell
$ file jdk-11.0.9.1/bin/java
jdk-11.0.9.1/bin/java: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.18, BuildID[sha1]=ee4e2e08b65cabbedc10dfb7bca1bd52f9454e01, not stripped
```

というわけで、「あれ？」と思ったファイルには、たまに`file`コマンドで見てみてもいいのではないでしょうか。

最後に、共有ライブラリへの依存を見る`ldd`で確認してみましょう。

32bit版。実行可能ファイルじゃないよ、と言われます。

```shell
$ ldd jdk-11.0.9.1/bin/java
	not a dynamic executable
```

64bit版はこんな感じになります。

```shell
$ ldd jdk-11.0.9.1/bin/java
	linux-vdso.so.1 (0x00007ffc9c9f3000)
	libz.so.1 => /lib64/libz.so.1 (0x00007f7ef36ae000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f7ef348e000)
	libjli.so => /home/xxxxx/jdk-11.0.9.1/bin/../lib/jli/libjli.so (0x00007f7ef327d000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f7ef3079000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f7ef2cb6000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f7ef3ac8000)
```

ちなみに、32bit版を32bit OSで実行するとこんな感じになります。

```shell
$ ldd jdk-11.0.9.1/bin/java
	linux-gate.so.1 =>  (0xb775d000)
	libz.so.1 => /lib/libz.so.1 (0xb773f000)
	libpthread.so.0 => /lib/libpthread.so.0 (0xb7724000)
	libjli.so => /home/xxxxx/jdk-11.0.9.1/bin/../lib/jli/libjli.so (0xb7712000)
	libdl.so.2 => /lib/libdl.so.2 (0xb770d000)
	libc.so.6 => /lib/libc.so.6 (0xb7541000)
	/lib/ld-linux.so.2 (0xb775e000)
```

OSは、こちらで確認。

```shell
$ cat /etc/redhat-release 
CentOS Linux release 7.9.2009 (AltArch)


$ uname -srvmpio
Linux 3.10.0-1160.6.1.el7.centos.plus.i686 #1 SMP Tue Nov 17 14:19:51 UTC 2020 i686 i686 i386 GNU/Linux
```