NodejsがさまざまなLinuxディストリビューション間で一見バイナリ互換性を達成する方法

NodejsがさまざまなLinuxディストリビューション間で一見バイナリ互換性を達成する方法

ダウンロードサイトにアクセスするとノードjs(他のファイルから)というファイルをLinux Binaries (x64)含むtarアーカイブを選択できます。bin/nodejs

Nodejsが実行できることが知られている(または表示される)「汎用」バイナリを提供する方法どのLinuxディストリビューション?私は彼らが彼らのウェブサイトにそのような声明をしないことを知っていますが、特定のOSバージョン(Ubuntu、DebianなどのNodejs)がないので、それが私が想定しているものです。

このトピック(Linuxディストリビューション間のバイナリ互換性)を読んでいる間、基本的にこれは実際ではないといういくつかの答えを見つけました。

いいえ、DebianとUbuntuはバイナリと互換性がありません。 DebianとUbuntuは、異なるABI、異なるカーネルバージョン、異なるライブラリ、異なるパッケージ/バージョンなどの異なるコンパイラを使用できます。すべてのUbuntuパッケージがDebianにあるわけではなく(逆も同様です)、debパッケージもアンインストール可能なバージョンによって異なります。

...

したがって、技術的にはバイナリと互換性がありません。

回答質問「Ubuntu LTSバイナリはDebianと互換性がありますか?」

わかりました。一部部分についてABIアーキテクチャ、コールルール、システムコールなどのものは、同じアーキテクチャとコールルールが使用されている場合、ある程度互換性があることが私の考えでは理解されます。なぜなら、すべてのLinuxディストリビューションの中核はLinuxカーネルだからです。

しかし、まだ理解するのは難しいです。なぜ人々は、2つのLinuxディストリビューションがバイナリと互換性がないと言います。

うんそれは互換性がありませんか?

NodeJSが「すべての」Linuxディストリビューションに1つのバイナリバージョンを提供しているように見えるのはなぜですか?

これは、「バイナリXをディストリビューションx、y、zと互換性を持たせる方法」より教育的な質問に近いです。

ベストアンサー1

ABI(Application Binary Interface)にはいくつかのレベルがあります。どこでも動作するバイナリを作成するには、次のいずれかのレベルをターゲットにする必要があります。ターゲットとする2つのレベルは、カーネルABIまたはLSB ABIです。

.debパッケージはDebianとUbuntuの間で互換性がないかもしれません。なぜなら、一方または他方に頼ることができますが、同時に両方に頼ることはできないからです。ただし、多くの .deb パッケージは一部の Ubuntu および Debian バージョンで実行されます。悪いことに、RedHat rpmはパッケージング形式を理解できないため、Ubuntuシステムで実行される可能性はありません。

依存関係は、実行可能ファイルが他のLinuxバージョンで実行されるのを防ぎます。ほとんどすべてのプログラムは外部ライブラリに依存しています。実行可能ファイルをビルドすると、Linux(およびWindowsや他のUNIXを含む他の多くのオペレーティングシステム)は、これらの外部ライブラリを実行可能ファイルの一部として含めず、スタブにのみリンクし、実際のライブラリは多くの実行可能ファイルには含まれません。実行可能ファイル間の共有。これにより、ディスクとメモリの実行可能ファイルのサイズが小さくなり、場合によっては実行可能ファイルを再構築しなくてもライブラリのバグを修正できます。ただし、Linuxバージョンに正しいバージョンの共有ライブラリがない場合、実行可能ファイルは機能しません。

共有ライブラリを使用する実行可能ファイルは動的にリンクされています。つまり、共有ライブラリへの最終接続が実行時に動的に実行されることを意味します。実行可能ファイルを静的にリンクすることも可能です。その結果、より大きな実行ファイルが生成されますが、より広い範囲のシステムで実行できます。その時点で、ABIはもはやLinuxバージョンではなく、カーネル自体です。通常、カーネルは以前のバージョンと互換性があり、実行可能ファイルは将来のバージョンと互換性があります。つまり(いくつかの広いカーネルバージョン内では)、古い実行可能ファイルは最新のカーネルで実行され、最新のカーネルは古い実行可能ファイルを実行できます。実行ファイル形式自体は、Linuxの歴史上ほとんど変更されていないため、制限的です。

オペレーティングシステムを実行しているCPUのアーキテクチャも、いくつかの例外を除いて実行可能ファイルと一致する必要があります。 (通常、関連するマッチライブラリがある場合、i386バイナリはx86_64システムで実行できます。)複数のCPUアーキテクチャのコードを含むファットバイナリを作成できます。これは一部のオペレーティングシステムでは一般的ですが、Linuxではまれです。

コンテナ化された実行可能ファイルもあります。この場合、カメと同様に、実行可能ファイルはファイルシステム(squashfsなど)に組み込まれており、すべての依存ライブラリとサポートファイルをバイナリ内から別々のファイルに渡します。これがappimageがすることです。

file上記のように、コマンドはldd時々バイナリがどのように構築されたかを知らせることができます。たとえば、

$ file /bin/ls
/bin/ls: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=897f49cafa98c11d63e619e7e40352f855249c13, for GNU/Linux 3.2.0, stripped
$ ldd /bin/ls
    linux-vdso.so.1 (0x00007fff95ae1000)
    libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007fc6aebb8000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc6ae990000)
    libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007fc6ae8f9000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fc6aec50000)

このバイナリはx86_64アーキテクチャ用であり、ダイナミックリンカバージョン2に動的にリンクされており、上記のさまざまな共有ライブラリの特定のバージョンが必要です。

これを以下と比較してみてください。

$ file /bin/busybox
/bin/busybox: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=36c64fc4707a00db11657009501f026401385933, for GNU/Linux 3.2.0, stripped
$ ldd /bin/busybox
    not a dynamic executable

この静的にリンクされたバイナリは、x86_64 ELFバージョン1をサポートするすべてのLinuxカーネルで実行されます。

$ file prusaslicer.AppImage
prusaslicer.AppImage: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.18, stripped
$ ldd prusaslicer.AppImage
    not a dynamic executable

これは動的にリンクされた実行可能ファイルのように見えますが、動的リンカー自体以外の共有ライブラリの依存関係はありません。これは実際にコンテナ化された実行可能ファイルであり、実行時に内部ファイルシステムをマウントし、内部で実際の実行可能ファイルを実行します。 (実行せずに)唯一の手がかりはファイル名(およびサイズ)です。これを実行した後、Fuseはマウントされたファイルシステムを調べることができますが、これはやや隠されています。

質問した具体的な例を見てみましょう... node.jsのx86_64 Linuxバージョンをダウンロードして、次のことを見つけました。

$ file bin/node 
bin/node: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=e8b23b15ec6280a0d4838fbba1171cb8d94667c5, with debug_info, not stripped
$ ldd bin/node
    linux-vdso.so.1 (0x00007ffd633f0000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007efec3198000)
    libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007efec2f6c000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007efec2e85000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007efec2e65000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007efec2e60000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007efec2c36000)
    /lib64/ld-linux-x86-64.so.2 (0x00007efec31e5000)

したがって、外部共有ライブラリの依存関係が多数ある動的にリンクされた実行可能ファイルとして実行できるシステムは限られていますが、特定のライブラリを含めたりインストールしたりできるバージョンの範囲はかなり広くなる可能性があります。これはほとんどのLinuxシステムに必要な基本ライブラリであり、さまざまなオペレーティングシステムのバージョンにこれらのライブラリのバージョンがあるほど安定しています。時には、それらの一部が欠落している場合は、Linuxバージョンに適したlsb-baseまたはlsb-coreパッケージをインストールすることで使用できます。 LSB(Linux Standard Base)は、サードパーティの開発者に共通の目標を提供したいすべてのLinuxディストリビューションの最小共通分母となる基本的な標準ライブラリと他のプロジェクトのセットを含むABI標準です。

実行されていないが実行する必要があると言う実行可能ファイルがある場合は、上記のような検索操作を実行して、システムに欠落している項目を確認し、不足しているライブラリをインストールできます。

おすすめ記事