为什么FileSystemWatcher在Linux容器中无法监视Windows卷

时间:2019-07-14 04:37:26

标签: c# linux docker .net-core filesystemwatcher

给出程序:

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 linkENV 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

修改容器内的文件:

running touch inside the container

touch working inside container

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

modifying files in the shared folder

什么也没发生!

nothing happens when modifying shared folder on windows

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

1 个答案:

答案 0 :(得分:1)

切换到PhysicalFileProvider。Watch完成了这项工作。对于文件系统监视策略,这似乎是一种更可移植的实现。

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

using System;
using System.IO;

namespace fsw_bug_poc
{
    class Program
    {
        private static FileSystemWatcher _fileSystemWatcher;

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

            Console.ReadKey(false);
        }           

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

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