这是几年前写的旧文,此前发布Wordpress小站上,现在又重新整理。算是温故知新,后续会继续整理。如有错误望及时指出,在此感谢。

背景:

运维同学反馈有一个部署很久的线上业务组件有大量的异常日志,拿到程序日志后,经排查,原因让人蛋疼。

原因运维对这个组件所部署的节点的磁盘进行了扩充,为了不影响线上部署的程序运行,创建一个软连接至新磁盘上,正常情况下该操作也无可厚非。蛋疼就在这里,该组件需要定时遍历文件目录,就在这个软连接上吃了瘪。

问题原因知道了,该怎么解决呢。

Path path = Paths.get("/usr/local/java");//软连接,实际指向-> /usr/local/jdk1.8.0_202
    
    Files.walkFileTree(path.**toRealPath**(), new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
            log.info("preVisitDirectory dir:{}", dir.toAbsolutePath());
            return super.preVisitDirectory(dir, attrs);
        }
    
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            log.info("visitFile file:{},RealPath:{}", file, file.toRealPath());
    
            return super.visitFile(file, attrs);
        }
    
    });
    ```

之前的代码,直接使用了path对象,这就是问题所在。

因为使用的是Path对象来进行遍历的,那么**toRealPath**方法会返回该软连接的实际路径。

*根因是在Linux系统中,所有交互资源都用文件描述符来表示,而软连接是一种文件,目录也是一种文件。*

所以造成了Files.walkFileTree遍历时,发现软连接不是目录文件的,当作普通文件来处理。