【问题标题】:How can I get a list of all mounted filesystems in Java on Unix?如何在 Unix 上获取 Java 中所有已安装文件系统的列表?
【发布时间】:2020-02-20 21:33:43
【问题描述】:

我在 Unix 平台上运行 Java。如何通过 Java 1.6 API 获取所有已挂载文件系统的列表?

我尝试过File.listRoots(),但它返回一个文件系统(即/)。如果我使用df -h,我会看到更多:

Filesystem      Size   Used  Avail Capacity   iused     ifree %iused  Mounted on
/dev/disk0s2   931Gi  843Gi   87Gi    91% 221142498  22838244   91%   /
devfs          187Ki  187Ki    0Bi   100%       646         0  100%   /dev
map -hosts       0Bi    0Bi    0Bi   100%         0         0  100%   /net
map auto_home    0Bi    0Bi    0Bi   100%         0         0  100%   /home
/dev/disk1s2   1.8Ti  926Gi  937Gi    50% 242689949 245596503   50%   /Volumes/MyBook
/dev/disk2     1.0Gi  125Mi  875Mi    13%     32014    223984   13%   /Volumes/Google Earth

我也希望看到/home(至少)。

【问题讨论】:

  • /home 就在中间,但只有在 /home 是从另一个设备安装时才会显示,但显然......
  • 我知道是的。但是File.listRoots() 不会返回/home。这就是重点。
  • 应该这样吗? / 是 unix 文件系统唯一真正的 root。如果你说你用这个函数做什么可能会更好?
  • 我明白,但挂载的文件系统列表与文件系统命名空间不同。

标签: java unix filesystems


【解决方案1】:

在 Java7+ 中你可以使用 nio

import java.io.IOException;
import java.nio.file.FileStore;
import java.nio.file.FileSystems;

public class ListMountedVolumesWithNio {
   public static void main(String[] args) throws IOException {
      for (FileStore store : FileSystems.getDefault().getFileStores()) {
         long total = store.getTotalSpace() / 1024;
         long used = (store.getTotalSpace() - store.getUnallocatedSpace()) / 1024;
         long avail = store.getUsableSpace() / 1024;
         System.out.format("%-20s %12d %12d %12d%n", store, total, used, avail);
      }
   }
}

【讨论】:

  • 这是一个不错的选择!不幸的是,从 FileStore 到 Path/File 没有简单的方法。解析 toString() 是一个 hackish 解决方法,可能会破坏......
【解决方案2】:

Java 不提供对挂载点的任何访问。您必须通过Runtime.exec() 运行系统命令mount 并解析其输出。要么这样,要么解析/etc/mtab的内容。

【讨论】:

  • 我的 Mac OS X 机器(Mountain Lion)上没有/etc/mtab,但我的 Ubuntu 服务器上有。
  • OS X 在许多方面都与“真正的”Unix 大不相同,因此任何特定于操作系统的事情都可能不得不为它做不同的事情。无论如何,mount 似乎是一个适用于 Mac 的通用工具。我将df 用于类似的任务,这也有效。
  • 在 OS X 上,您可以使用 (new File("/Volumes")).listFiles() 解析 /Volumes 的内容。其中一个条目是指向/ 的符号链接,您可以使用getCanonicalPath() 对其进行测试。您还必须测试并排除不是挂载点的文件,例如讨厌的 .DS_Store
  • 对于 java7+ 看看Erik Martino answer
【解决方案3】:

您可以尝试使用以下方法解决问题:

我的代码

public List<String> getHDDPartitions() {
    try {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("/proc/mounts"), "UTF-8"));
        String response;
        StringBuilder stringBuilder = new StringBuilder();
        while ((response = bufferedReader.readLine()) != null) {
            stringBuilder.append(response.replaceAll(" +", "\t") + "\n");
        }
        bufferedReader.close();
        return Lists.newArrayList(Arrays.asList(stringBuilder.toString().split("\n")));
    } catch (IOException e) {
        LOGGER.error("{}", ExceptionWriter.INSTANCE.getStackTrace(e));
    }
    return null;
}

public List<Map<String, String>> getMapMounts() {
    List<Map<String, String>> resultList = Lists.newArrayList();
    for (String mountPoint : getHDDPartitions()) {
        Map<String, String> result = Maps.newHashMap();
        String[] mount = mountPoint.split("\t");
        result.put("FileSystem", mount[2]);
        result.put("MountPoint", mount[1]);
        result.put("Permissions", mount[3]);
        result.put("User", mount[4]);
        result.put("Group", mount[5]);
        result.put("Total", String.valueOf(new File(mount[1]).getTotalSpace()));
        result.put("Free", String.valueOf(new File(mount[1]).getFreeSpace()));
        result.put("Used", String.valueOf(new File(mount[1]).getTotalSpace() - new File(mount[1]).getFreeSpace()));
        result.put("Free Percent", String.valueOf(getFreeSpacePercent(new File(mount[1]).getTotalSpace(), new File(mount[1]).getFreeSpace())));
        resultList.add(result);
    }
    return resultList;
}

private Integer getFreeSpacePercent(long total, long free) {
    Double result = (Double.longBitsToDouble(free) / Double.longBitsToDouble(total)) * 100;
    return result.intValue();
}

【讨论】:

  • 这项工作做得很好。我不知道你为什么没有更多的赞成票。干得好!
【解决方案4】:

OSHI(Java 的操作系统和硬件信息库)在这里很有用:https://github.com/oshi/oshi

查看此代码:

@Test
public void test() {

    final SystemInfo systemInfo = new SystemInfo();
    final OSFileStore[] fileStores = systemInfo.getOperatingSystem().getFileSystem().getFileStores();
    Stream.of(fileStores)
    .peek(fs ->{
        System.out.println("name: "+fs.getName());
        System.out.println("type: "+fs.getType() );
        System.out.println("str: "+fs.toString() );
        System.out.println("mount: "+fs.getMount());
        System.out.println("...");
    }).count();

}

【讨论】:

    【解决方案5】:

    您可以使用 JNA 调用 getmntent 函数(使用“man getmntent”获取更多信息)。

    这里有一些示例代码可以帮助您入门:

    import java.util.Arrays;
    import java.util.List;
    
    import com.sun.jna.Library;
    import com.sun.jna.Native;
    import com.sun.jna.Pointer;
    import com.sun.jna.Structure;
    
    public class MntPointTest {
        public static class mntent extends Structure {
            public String mnt_fsname; //Device or server for filesystem
            public String mnt_dir; //Directory mounted on
            public String mnt_type; //Type of filesystem: ufs, nfs, etc.
            public String mnt_opts;
            public int mnt_freq;
            public int mnt_passno;
    
            @Override
            protected List getFieldOrder() {
                return Arrays.asList("mnt_fsname", "mnt_dir", "mnt_type", "mnt_opts", "mnt_freq", "mnt_passno");
            }
        }
    
        public interface CLib extends Library {
            CLib INSTANCE = (CLib) Native.loadLibrary("c", CLib.class);
    
            Pointer setmntent(String file, String mode);
            mntent getmntent(Pointer stream);
            int endmntent(Pointer stream);
        }
    
        public static void main(String[] args) {
            mntent mntEnt;
            Pointer stream = CLib.INSTANCE.setmntent("/etc/mtab", "r");
            while ((mntEnt = CLib.INSTANCE.getmntent(stream)) != null) {
                System.out.println("Mounted from: " + mntEnt.mnt_fsname);
                System.out.println("Mounted on: " + mntEnt.mnt_dir);
                System.out.println("File system type: " + mntEnt.mnt_type);
                System.out.println("-------------------------------");
            }
    
            CLib.INSTANCE.endmntent(stream);
        }
    }
    

    【讨论】:

    • 感谢您的出色回答!您是否知道是否有将所有常用方法映射到 java 的项目或库(我的意思是像 mount/umount 和朋友)?
    • 我正在github.com/dblock/oshi 开展一个项目,该项目对关键操作系统本机代码(内存、文件、cpu、电池等)进行这种基于 JNA 的映射。
    【解决方案6】:

    当@Cozzamara 指出这是要走的路时,我已经在使用mount 的路上。我最终得到的是:

        // get the list of mounted filesystems
        // Note: this is Unix specific, as it requires the "mount" command
        Process mountProcess = Runtime.getRuntime ().exec ( "mount" );
        BufferedReader mountOutput = new BufferedReader ( new InputStreamReader ( mountProcess.getInputStream () ) );
        List<File> roots = new ArrayList<File> ();
        while ( true ) {
    
            // fetch the next line of output from the "mount" command
            String line = mountOutput.readLine ();
            if ( line == null )
                break;
    
            // the line will be formatted as "... on <filesystem> (...)"; get the substring we need
            int indexStart = line.indexOf ( " on /" );
            int indexEnd = line.indexOf ( " ", indexStart );
            roots.add ( new File ( line.substring ( indexStart + 4, indexEnd - 1 ) ) );
        }
        mountOutput.close ();
    

    【讨论】:

    • 这行:roots.add ( new File ( line.substring ( indexStart + 4, indexEnd - 1 ) ) ); 应该是:roots.add ( new File ( line.substring ( indexStart + 4, indexEnd) ) );
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-18
    • 1970-01-01
    • 1970-01-01
    • 2018-05-29
    • 2014-05-06
    • 2011-11-05
    相关资源
    最近更新 更多