在 Java 中决定 linux 的 GNU 或 MUSL 版本
Decide GNU or MUSL build of linux in Java
我有一个 Java 桌面应用程序,它应该在 GNU Linux 发行版(Debian 和 Ubuntu)和 MUSL Linux 发行版中 运行 (高山)。我的应用程序也使用本机库,并且本机库构建对于两种类型的 Linux 发行版都是不同的。
我将在不同的文件夹中随我的应用程序一起交付。因此在 运行 时间 Java 程序需要根据 Linux(GNU 或 MUSL)选择正确的本地库分布。
我没有找到任何机制来了解 Java 程序,Linux 发行版 JVM 运行正在运行。
我正在考虑从 Linux 的 /etc/ 文件夹中读取 OS 文件的一种方法。但我认为这不是一个好的解决方案(因为某些自定义构建可能会更改此细节),有人可以针对此问题提出一些更好的解决方案吗?或者如何做到这一点?
您可以通过关注 this Whosebug answer
来检测哪个 Linux 分布是 运行
遗憾的是,没有那么多替代方法可以检测您是 运行 MUSL 还是 GLIBC
使用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!");
}
}
}
可能有类似的方法具有独特的功能来区分其他 libc 变体与 MUSL,但据我所知,MUSL 试图与标准兼容,以至于它实际上不允许识别自己。
查找 GNU 发行版的另一个选项是 uname -o
您可以使用 ProcessBuilder 执行的命令。
在非 GNU (Alpine) 上它只是“Linux”,而在 Ubuntu、Debian 和 OpenSUSE 上它是“GNU/Linux”。
您还可以通过遍历 /lib*
目录查找 libc 变体来成功确定 GNU 与 MUSL。这类似于 when compiling the JDK 所采用的方法,它执行 ldd
命令并从该输出中解析库。
例如,在 Alpine linux 中迭代 /lib
目录得到这个 link: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) 项目,并通过几乎所有选项来确定您是哪个发行版 运行。您可以在 this class.
中看到所有这些工作的结果
我将在该文件中引用一条评论:
There are two competing options for family/version information. Newer
systems are adopting a standard /etc/os-release file:
https://www.freedesktop.org/software/systemd/man/os-release.html
Some systems are still using the lsb standard which parses a variety
of /etc/*-release files and is most easily accessed via the
commandline lsb_release -a, see here:
https://linux.die.net/man/1/lsb_release In this case, the
/etc/lsb-release file (if it exists) has optional overrides to the
information in the /etc/distrib-release files, which show:
"Distributor release x.x (Codename)"
代码的逻辑是:
- 尝试
/etc/system-release
- 尝试
/etc/os-release
- 运行
lsb_release
命令
- 阅读
/etc/lsb-release
- 查找并阅读任何
/etc/*-release
文件。
这些文件包含 NAME
之类的键,可以帮助您解决问题。
随意复制和使用该文件或变体,或者仅将该项目用作依赖项。
我有一个 Java 桌面应用程序,它应该在 GNU Linux 发行版(Debian 和 Ubuntu)和 MUSL Linux 发行版中 运行 (高山)。我的应用程序也使用本机库,并且本机库构建对于两种类型的 Linux 发行版都是不同的。
我将在不同的文件夹中随我的应用程序一起交付。因此在 运行 时间 Java 程序需要根据 Linux(GNU 或 MUSL)选择正确的本地库分布。
我没有找到任何机制来了解 Java 程序,Linux 发行版 JVM 运行正在运行。
我正在考虑从 Linux 的 /etc/ 文件夹中读取 OS 文件的一种方法。但我认为这不是一个好的解决方案(因为某些自定义构建可能会更改此细节),有人可以针对此问题提出一些更好的解决方案吗?或者如何做到这一点?
您可以通过关注 this Whosebug answer
来检测哪个 Linux 分布是 运行遗憾的是,没有那么多替代方法可以检测您是 运行 MUSL 还是 GLIBC
使用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!");
}
}
}
可能有类似的方法具有独特的功能来区分其他 libc 变体与 MUSL,但据我所知,MUSL 试图与标准兼容,以至于它实际上不允许识别自己。
查找 GNU 发行版的另一个选项是 uname -o
您可以使用 ProcessBuilder 执行的命令。
在非 GNU (Alpine) 上它只是“Linux”,而在 Ubuntu、Debian 和 OpenSUSE 上它是“GNU/Linux”。
您还可以通过遍历 /lib*
目录查找 libc 变体来成功确定 GNU 与 MUSL。这类似于 when compiling the JDK 所采用的方法,它执行 ldd
命令并从该输出中解析库。
例如,在 Alpine linux 中迭代 /lib
目录得到这个 link: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) 项目,并通过几乎所有选项来确定您是哪个发行版 运行。您可以在 this class.
我将在该文件中引用一条评论:
There are two competing options for family/version information. Newer systems are adopting a standard /etc/os-release file: https://www.freedesktop.org/software/systemd/man/os-release.html
Some systems are still using the lsb standard which parses a variety of /etc/*-release files and is most easily accessed via the commandline lsb_release -a, see here: https://linux.die.net/man/1/lsb_release In this case, the /etc/lsb-release file (if it exists) has optional overrides to the information in the /etc/distrib-release files, which show: "Distributor release x.x (Codename)"
代码的逻辑是:
- 尝试
/etc/system-release
- 尝试
/etc/os-release
- 运行
lsb_release
命令 - 阅读
/etc/lsb-release
- 查找并阅读任何
/etc/*-release
文件。
这些文件包含 NAME
之类的键,可以帮助您解决问题。
随意复制和使用该文件或变体,或者仅将该项目用作依赖项。