为啥 FileSystemWatcher 在监视 Windows 卷的 Linux 容器中不起作用

Posted

技术标签:

【中文标题】为啥 FileSystemWatcher 在监视 Windows 卷的 Linux 容器中不起作用【英文标题】:Why FileSystemWatcher doesn't work in Linux container watching Windows volume为什么 FileSystemWatcher 在监视 Windows 卷的 Linux 容器中不起作用 【发布时间】:2019-11-23 06:21:12 【问题描述】:

给定程序:

using System;
using System.IO;

namespace fsw_bug_poc

    class Program
    
        private static FileSystemWatcher _fileSystemWatcher;

        static void Main(string[] args)
        
            _fileSystemWatcher = new FileSystemWatcher("Watched", "*.*");
            _fileSystemWatcher.Changed += Notify;
            _fileSystemWatcher.Created += Notify;
            _fileSystemWatcher.Deleted += Notify;
            _fileSystemWatcher.Renamed += Notify;
            _fileSystemWatcher.IncludeSubdirectories = true;
            _fileSystemWatcher.EnableRaisingEvents = true;

            Console.ReadKey(false);
        

        private static void Notify(object sender, FileSystemEventArgs e)
        
            Console.WriteLine($"e.FullPath e.ChangeType");
        
    

Dockerfile:

FROM mcr.microsoft.com/dotnet/core/runtime:2.2-stretch-slim AS base
WORKDIR /app

FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
WORKDIR /src
COPY ["fsw-bug-poc.csproj", ""]
RUN dotnet restore "fsw-bug-poc.csproj"
COPY . .
WORKDIR "/src/"
RUN dotnet build "fsw-bug-poc.csproj" -c Release -o /app

FROM build AS publish
RUN dotnet publish "fsw-bug-poc.csproj" -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
RUN mkdir -p /app/Watched
VOLUME /app/Watched
ENTRYPOINT ["dotnet", "fsw-bug-poc.dll"]

根据this link 将ENV DOTNET_USE_POLLING_FILE_WATCHER=true 添加到 Dockerfile 修复了 FileSystemWatcher 在容器内不起作用。

即使使用此修复程序,当在 Windows 上运行 Linux 容器并将共享驱动程序挂载到卷时,FileSystemWatcher 也无法工作:

docker build -t fsw-bug-poc .
docker run -it --rm -v C:\Shared:/app/Watched fsw-bug-poc

修改容器内的文件:

修改共享卷文件夹中的文件:

什么都没有发生!!

有人可以解释发生了什么吗? FileSystemWatcher 正在使用轮询策略,所以它应该以相同的方式工作,不是吗?

【问题讨论】:

过去,Windows 文件通知仅适用于 Windows 机器。他们不能在我当时正在研究的 AIX、Linux 或 OS/400 上使用 SMB 共享。我以前必须轮询股票以了解变化。 我不确定这是否会影响 FileSystemWatcher 策略 - 请阅读 docs.microsoft.com/dotnet/api/… => UsePollingFileWatcher @SirRufo 你可能是对的。我以为 FileSystemWatcher 在后台使用它,但似乎恰恰相反:github.com/aspnet/FileSystem/blob/master/src/FS.Physical/… 【参考方案1】:

切换到PhysicalFileProvider.Watch 完成了这项工作。它似乎是文件系统监视策略的更便携的实现。

PhysicalFileProvider 的当前实现支持DOTNET_USE_POLLING_FILE_WATCHER 环境变量。我在FileSystemWatcher 实现中找不到它的任何引用。

using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives;
using System;
using System.IO;

namespace fsw_bug_poc

    class Program
    
        private static PhysicalFileProvider _fileProvider;
        private static IChangeToken _fileChangeToken;

        static void Main(string[] args)
        
            _fileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "."));
            WatchForFileChanges();

            Console.ReadKey(false);
        

        private static void WatchForFileChanges()
        
            _fileChangeToken = _fileProvider.Watch("*.*");
            _fileChangeToken.RegisterChangeCallback(Notify, default);
        

        private static void Notify(object state)
        
            Console.WriteLine("File change detected");
            WatchForFileChanges();
        
    

【讨论】:

_fileChangeToken ?! private IChangeToken _fileChangeToken;

以上是关于为啥 FileSystemWatcher 在监视 Windows 卷的 Linux 容器中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

C#(098):文件监视 FileSystemWatcher

使用 FileSystemWatcher 监视目录

C# FileSystemWatcher 监视仅由当前系统完成的网络驱动器上的更改

FileSystemWatcher用法详解

Filesystemwatcher 没有在看子目录

FileSystemWatcher用法详解