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

Posted

技术标签:

【中文标题】如何使用 JNA 读取 Linux 命令的输出【英文标题】:How to read the output of a Linux command using JNA 【发布时间】:2017-10-10 22:53:13 【问题描述】:

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

如果我使用 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:仔细检查导致崩溃的方法的签名,以确保所有参数的大小和类型都合适。对本机指针变体要特别小心。另请参阅有关调试结构定义的信息。

谁能帮我解决这个问题。我应该使用什么返回类型才能访问挂载点列表。

更新: 我可以通过如下调整代码来运行 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 从标准输出读取结果

【问题讨论】:

不如直接调用mount函数,使用JNA,看它的返回值(int)判断是否成功:man7.org/linux/man-pages/man2/mount.2.html 我想要的是所有当前附加文件系统的列表,它实际上是已知挂载点的列表。在这种情况下,我不认为返回值会有所帮助 【参考方案1】:

由mount 提供文档

mount() 附加由 source 指定的文件系统(通常是 引用设备的路径名,但也可以是设备的路径名 目录或文件,或虚拟字符串)到位置(目录或 文件)由目标中的路径名指定。

这意味着mount syscall 只是挂载目录,它与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 
    

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


更新

看看this answer,你可以区分什么是程序,什么是系统调用或库函数

【讨论】:

以上是关于如何使用 JNA 读取 Linux 命令的输出的主要内容,如果未能解决你的问题,请参考以下文章

shell 如何获取一条命令的输出结果

如何在不使用命令的情况下以编程方式关闭/重启 linux 机器(运行时)

运行文件时如何使用qprocess实时读取输出

linux如何使用grep ,wc -l命令统计一个文件中的多个字符串的个数,并且只读取1次文件。

使用JNA读取dll文件

jna读取中文乱码