决定用Java构建Linux的GNU还是MUSL

问题描述 投票:0回答:2

我有一个 Java 桌面应用程序,应该可以在 GNU Linux 发行版(Debian 和 Ubuntu)和 MUSL Linux 发行版(Alpine)中运行。我的应用程序也使用本机库,并且两种类型的 Linux 发行版的本机库构建都不同。

我会将两者与我的申请放在不同的文件夹中。因此,在运行时 Java 程序需要根据 Linux(GNU 或 MUSL)选择正确的本地库发行版。

我没有找到任何机制可以知道在Java程序中,哪个Linux发行版JVM正在运行。

我想从Linux的/etc/文件夹中读取操作系统文件的一种方法。但我认为这不是一个好的解决方案(因为某些自定义构建可能会更改此细节),有人可以为这个问题建议一些更好的解决方案吗?或者如何做到这一点?

java native glibc jna musl
2个回答
7
投票

使用Java/JNA,您可以映射

gnu_get_libc_version()
函数并尝试在加载
libc
后执行它。如果它有效,那么您就使用了 glibc (GNU)。如果您收到
UnsatisfiedLinkError
提示找不到该函数,则说明您使用的是其他 libc。

映射功能:

public interface Libc extends Library {
    Libc INSTANCE = Native.load("c", Libc.class);

    String gnu_get_libc_version();
}

称呼它:

public class GnuOrMusl {
    public static void main(String[] args) {
        try {
            System.out.println("On GNU libc version " + Libc.INSTANCE.gnu_get_libc_version());
        } catch (UnsatisfiedLinkError e) {
            System.out.println("Not on glibc!");
        }
    }
}

请注意,如果您处于具有 glibc 兼容性的容器化环境中,此检测可能表明 glibc,但这引发了一个问题:哪种版本的库适合该环境。

可能有类似的方法具有独特的功能来区分其他 libc 变体和 MUSL,但据我所知,MUSL 试图如此符合标准,以至于它实际上不允许识别自己。


查找 GNU 发行版的另一个选项是

uname -o
命令,您可以使用 ProcessBuilder 执行该命令。

在非 GNU (Alpine) 上它只是“Linux”,而在 Ubuntu、Debian 和 OpenSUSE 上它是“GNU/Linux”。


您还可以通过迭代

/lib*
目录查找 libc 变体来成功确定 GNU 与 MUSL。这类似于编译 JDK 时所采用的方法,即执行 ldd 命令并从该输出中解析库。
例如,迭代 Alpine linux 中的 

/lib

目录会给出以下链接:

libc.musl-x86_64.so.1 -> ld-musl-x86_64.so.1
在 Debian 

/lib32

libc.so.6 -> libc-2.28.so
,在 OpenSUSE
/lib64
中我看到类似的东西:
libc.so.6 -> libc-2.26.so
,而 Ubuntu
/lib/aarch64-linux-gnu
libc-2.27.so
如果您仍使用 Java,确定要搜索的 

/lib

路径可能需要一些反复试验。解析诸如

ldd `which ls`
之类的命令行输出可能会得到一个包含
gnu
musl
的字符串。

就确定使用哪个 Linux 发行版而言,从
/etc

文件夹中读取是一个很好的直觉。我管理基于 Java 的操作系统和硬件信息 (OSHI) 项目,并浏览了几乎所有选项来确定您正在运行哪个发行版。您可以在

本课程
中看到所有劳动成果。 我将引用该文件中的评论:

家庭/版本信息有两个相互竞争的选项。较新 系统采用标准 /etc/os-release 文件:
https://www.freedesktop.org/software/systemd/man/os-release.html

一些系统仍在使用 lsb 标准,该标准解析各种 /etc/*-release 文件的文件,最容易通过 命令行 lsb_release -a,请参见此处:

https://linux.die.net/man/1/lsb_release

在这种情况下, /etc/lsb-release 文件(如果存在)具有可选的覆盖 /etc/distrib-release 文件中的信息显示: “发行商版本 x.x(代号)”

代码的逻辑是:

尝试
    /etc/system-release
  1. 尝试
  2. /etc/os-release
  3. 运行
  4. lsb_release
  5. 命令
    阅读
  6. /etc/lsb-release
  7. 查找并阅读任何 
  8. /etc/*-release
  9. 文件。
    
    
  10. 这些文件包含像
NAME

这样的键可以帮助您。

您可以随意复制和使用该文件或变体,或者只是将该项目用作依赖项。


0
投票
这个 StackOverflow 答案

来检测正在运行的 Linux 发行版 不幸的是,没有那么多替代方案来检测您是否在 MUSL 或 GLIBC 上运行

© www.soinside.com 2019 - 2024. All rights reserved.