为什么 FileSystemWatcher 在 Linux 容器监视 Windows 卷中不起作用
Why FileSystemWatcher doesn't work in Linux container watching Windows volume
给定程序:
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 使用轮询策略,所以它应该以相同的方式工作,不是吗?
切换到 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();
}
}
}
给定程序:
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 使用轮询策略,所以它应该以相同的方式工作,不是吗?
切换到 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();
}
}
}