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

时间:2017-10-10 22:53:14

标签: java jna

我想使用JNA在java中调用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());
}

}

我尝试使用基于以下doc的不同返回类型但没有任何作用。

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");
}

}

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

1 个答案:

答案 0 :(得分:0)

mount文档

  

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

这意味着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 {
    }
}

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

更新

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