java - 如何使用 JNA 读取 Linux 命令的输出

标签 java jna

我想使用 JNA 在 Java 中调用 Linux mount 命令,并从调用结果中填充挂载点列表,但无法理解接口(interface)方法的实际返回类型。

如果我使用 int 那么它会打印 -1 而不会出现任何错误。我认为这表明存在某种错误。

public class MountTest {

private interface CLibrary extends Library {
    String[] mount();
}

public static void main(String[] args) {
    CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);

    System.out.println(INSTANCE.mount());
}

}

我尝试根据以下文档使用不同的返回类型,但没有任何效果。

Default Type Mappings

我认为我的问题是基于

的签名不正确

My library sometimes causes a VM crash: Double check the signature of the method causing the crash to ensure all arguments are of the appropriate size and type. Be especially careful with native pointer variations. See also information on debugging structure definitions.

有人可以帮我解决这个问题吗?我应该使用什么返回类型,以便我可以访问挂载点列表。

更新: 我能够通过调整代码来运行 Linux 命令,如下所示:

public class MountTest {

private interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
    int runCommand(String cmd);
}

public static void main(String[] args) {
    CLibrary.INSTANCE.runCommand("mount");
}

}

现在的问题是,它打印到标准输出。我不知道如何使用 JNA 从 stdout 读取结果

最佳答案

作者:mount文档

mount() attaches the filesystem specified by source (which is often a pathname referring to a device, but can also be the pathname of a directory or file, or a dummy string) to the location (a directory or file) specified by the pathname in target.

这意味着mount系统调用只是挂载目录,它与the mount command不同。 。您可能正在寻找getmetent ,它将列出所有文件系统挂载点,实现如下:

public interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary) Native.loadLibrary("c", CLibrary.class);
    Pointer fopen(String name, String mode);
    Mount.ByReference getmntent(Pointer FILE);
}

public static void main(String[] args) {
    final Pointer mountFile = CLibrary.INSTANCE.fopen("/etc/mtab", "r");
    if (mountFile == null) {
        System.err.println("File not exists: " + mountFile);
        return;
    }
    Mount.ByReference mpoint;
    while ((mpoint = CLibrary.INSTANCE.getmntent(mountFile)) != null) {
        System.out.println(mpoint);
    }

}

public static class Mount extends Structure {
    public String mnt_fsname;
    public String mnt_dir;
    public String mnt_type;
    public String mnt_opts;
    public int mnt_freq;
    public int mnt_passno;

    @Override
    protected List getFieldOrder() {
        List<String> fieds = new ArrayList<>();
        for (final Field f : Mount.class.getDeclaredFields()) {
            if (!f.isSynthetic())
                fieds.add(f.getName());
        }
        return fieds;
    }

    public static class ByReference extends Mount implements Structure.ByReference {
    }
}

观察: 据我所知,你不能从 JNA 调用编译后的程序,只能调用库函数和系统调用,然后不可能调用 mount 命令,如果你真的想使用这个命令,那么你可能需要使用 Runtime.getRuntime().exec 或类似的东西。

<小时/>

更新

看看this answer在那里您可以区分什么是程序以及什么是系统调用或库函数

关于java - 如何使用 JNA 读取 Linux 命令的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46677204/

相关文章:

java - 重构/重新设计大型系统

java - Java中的多项——可重用性和可维护性

Java native 访问 - GetExtendedTcpTable : Bounds exceeds available space

c# - C# 是否有 Java JNA 库的替代方案?

java - 通过 JNA 使用 Xlib 移动窗口

java - 如何获取对 DLL 的 java JNA 调用以获取参数中返回的数据?

java - 将列表 <Integer> 处理到线程

java - 如何启动、暂停、继续作为 "keep busy"任务每 5 秒执行一次的任务

java - 我需要 N 体分子模拟性能方面的帮助!(java 小程序)

java - JNA通过java找不到dll文件中指定的程序