我有一个 Java 桌面应用程序,应该可以在 GNU Linux 发行版(Debian 和 Ubuntu)和 MUSL Linux 发行版(Alpine)中运行。我的应用程序也使用本机库,并且两种类型的 Linux 发行版的本机库构建都不同。
我会将两者与我的申请放在不同的文件夹中。因此,在运行时 Java 程序需要根据 Linux(GNU 或 MUSL)选择正确的本地库发行版。
我没有找到任何机制可以知道在Java程序中,哪个Linux发行版JVM正在运行。
我想从Linux的/etc/文件夹中读取操作系统文件的一种方法。但我认为这不是一个好的解决方案(因为某些自定义构建可能会更改此细节),有人可以为这个问题建议一些更好的解决方案吗?或者如何做到这一点?
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
/etc/os-release
lsb_release
/etc/lsb-release
/etc/*-release
NAME
这样的键可以帮助您。
您可以随意复制和使用该文件或变体,或者只是将该项目用作依赖项。
来检测正在运行的 Linux 发行版 不幸的是,没有那么多替代方案来检测您是否在 MUSL 或 GLIBC 上运行