简体   繁体   English

Java捕获Linux挂载/卸载文件夹

[英]Java catch linux mount / unmount for a folder

I have a java project which one of its components is to monitor a specific folder which is mounted to my machine. 我有一个Java项目,它的组件之一是监视安装到我的计算机上的特定文件夹。
My linux version is OpenSUSE 42.1 我的linux版本是OpenSUSE 42.1

For monitoring the folder I'm using java's Watch Service . 为了监视文件夹,我使用了Java的Watch Service
Attached is the main code for folder monitoring we found online and modified to our on need. 随附的是我们在线找到并根据需要进行修改的文件夹监视的主要代码。
(sorry for the lack of copy rights, can't find where it was taken from) . (很抱歉,缺少版权,无法找到它的来源)。
Constructor: 构造函数:

/**
 * Creates a WatchService and registers the given directory
 */
public WatchDir(Path dir, Kind<?>... dirWatchKinds) throws IOException {
    this.watcher = FileSystems.getDefault().newWatchService();
    this.keys = new HashMap<WatchKey,Path>();

    register(dir, dirWatchKinds);
    Runtime.getRuntime().addShutdownHook(new Thread() {
        public void run() {
            try {
                watcher.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });
}

Run method (implemented as runnable): 运行方法(实现为可运行):

/**
 * Process all events for keys queued to the watcher
 */
public void run() {
    while (shouldRun) {

        // wait for key to be signalled
        WatchKey key;
        try {               
            key = watcher.take();
        } catch (Exception x) {             
            return;
        }

        Path dir = keys.get(key);
        if (dir == null) {
            log.error("WatchKey not recognized!!");
            continue;
        }

        for (WatchEvent<?> event: key.pollEvents()) {
            WatchEvent.Kind<?> kind = event.kind();

            if (kind == OVERFLOW) {
                continue;
            }

            // Context for directory entry event is the file name of entry
            WatchEvent<Path> ev = cast(event);
            Path name = ev.context();
            Path child = dir.resolve(name);

           handleDirEvent(child, ev.kind());

        }

        // reset key and remove from set if directory no longer accessible
        boolean valid = key.reset();
        if (!valid) {
            // Check that dir path still exists. If not, notify user and whoever run the thread
            if (Files.notExists(dir)){
                //log.error(String.format("Directory ", arg1));
                fireFileChangedEvent(dir.getFileName().toString(), FileState.Deleted);
            }

            keys.remove(key);

            // all directories are inaccessible
            if (keys.isEmpty()) {
                break;
            }
        }
    }
}

Now for my problem. 现在我的问题。
The mounted folder is prone to disconnections which probably will be handled out side of my program scope (from terminal I guess). 挂载的文件夹容易断开连接,这很可能会在我的程序范围之外处理(我猜是从终端发出的)。
Currently when it happens, the watcher.take() is getting notified, without any events to handle, 目前,发生这种情况时, watcher.take()会收到通知,没有任何要处理的事件,
and on the boolean valid = key.reset() it gets value false which then results in thread termination eventually. 并在boolean valid = key.reset()上获取值false,最终导致线程终止。
From that point I don't really know when the folder will be mounted again - for re-running the monitor thread. 从那时起,我真的不知道何时将再次安装该文件夹-重新运行监视器线程。

What is the best way to monitor mount / unmount of the folder? 监视文件夹安装/卸载的最佳方法是什么?
Please note : the monitored endpoint folder not necessarily is the mounting point, it (the mounted folder) could be one of its ancestors. 请注意 :监视的端点文件夹不一定是安装点,它(已安装的文件夹)可能是其祖先之一。

Any help would be appreciated! 任何帮助,将不胜感激!

Your could look at the /proc/mounts file to see if the mount still exist or not. 您可以查看/proc/mounts文件以查看安装是否仍然存在。

Not sure about OpenSUSE but I assume they work the same as Redhat style linux. 不确定OpenSUSE,但我认为它们的工作方式与Redhat风格的linux相同。 https://www.centos.org/docs/5/html/5.2/Deployment_Guide/s2-proc-mounts.html https://www.centos.org/docs/5/html/5.2/Deployment_Guide/s2-proc-mounts.html

Following @StefanE answer, I found the following good example for using java native for reading this file. 在@StefanE答案之后,我发现了以下使用Java本机读取此文件的好示例。
Taken from this answer , 这个答案中
it parses nicely the /etc/mtab file, and in my specific usage I'll check this file each time interval to see if the folder is mounted again. 它很好地解析了/etc/mtab文件,在我的特定用法中,我将在每个时间间隔检查该文件以查看是否再次安装了该文件夹。

    mntent mntEnt;
    Pointer stream = CLib.INSTANCE.setmntent("/etc/mtab", "r");
    while ((mntEnt = CLib.INSTANCE.getmntent(stream)) != null) {
        if (mntEnt.mnt_type.equalsIgnoreCase("cifs")){
            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);

for my specific usage it results with 对于我的特定用法,它的结果是

Mounted from: //192.168.163.129/storage1/rawData
Mounted on: /mntMS/StorageServer1/rawData
File system type: cifs

Mounted from: //192.168.163.129/storage2/output
Mounted on: /mntMS/StorageServer2/output
File system type: cifs

Mounted from: //192.168.163.129/storage2/rawData
Mounted on: /mntMS/StorageServer2/rawData
File system type: cifs

Mounted from: //127.0.0.1/storage1/output
Mounted on: /mntMS/StorageServer1/output
File system type: cifs

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM