我的应用程序正在将日志写入一个目录,该目录是硬编码的“Logs”,位于我的应用程序的运行时目录下。
今天,一位客户问我是否可以将这些日志放在另一个地方(另一台计算机上)。
作为第一个测试,我尝试创建一个符号链接:
- 我停止了应用程序。
- 我删除了“Logs”目录。
- 在我的计算机上使用 WSL,我创建了一个符号链接,例如
ln -s /mnt/c/Temp_Folder/TestLog/ /mnt/c/<Application>/Logs
. - 我开始了我的申请。
我没有看到目录中出现任何日志C:\Temp_Folder\TestLog\
。
我看到不同的原因:
- 尝试在 Windows 计算机上使用 Linux 技术要么是一个完全愚蠢的想法。
- 要么它可能有效,但需要考虑一些额外的事情。
我希望是第二个选择,但是那样的话,我需要考虑哪些事情呢?
在Harry的回答后进行编辑:如果您可以使用 Windows 技术,
为什么要使用 WSL ?:-)ln -s
mklink
我喜欢这个想法,但不幸的是它似乎不起作用,正如您从以下实验中看到的那样:
C:\<Runtime_Dir>mklink /D Logs E:\TestLog\
=> result:
29/03/2024 08:21 <SYMLINKD> Logs [E:\TestLog\]
=> 因此,确实Logs
创建了目录符号链接,但是当我启动应用程序时,似乎不再写入任何日志(我看到它们是在控制台窗口中创建的,但它们没有写在文件中)。
其他一些实验:(我记得之前有一个路口,但细节已经忘记了)
C:\<Runtime_Dir>mklink /D /J Logs E:\TestLog\
Local volumes are required to complete the operation.
C:\<Runtime_Dir>mklink /D /H Logs E:\TestLog\
The system cannot find the path specified.
C:\<Runtime_Dir>mklink /J Logs E:\TestLog\
Local volumes are required to complete the operation.
经过更多实验后编辑2:
在引用另一个驱动器时,它似乎不起作用,但当我引用同一台计算机上的另一个目录时,它似乎确实起作用,正如您在此处看到的:
C:\<Runtime_Dir>mklink /D Logs C:\Temp_Folder\TestLog\
symbolic link created for Logs <<===>> C:\Temp_Folder\TestLog\
C:\<Runtime_Dir>mklink /D /J Logs C:\Temp_Folder\TestLog\
Junction created for Logs <<===>> C:\Temp_Folder\TestLog\
我可以确认,在这两种情况下,日志都会被创建!
换句话说,问题不在于 Windows 符号链接/连接不起作用:问题在于符号链接/连接引用了另一个驱动器。
我记得在 Windows 中创建驱动器有两种甚至三种方法(驱动器映射、替换(?)和另一种(???),这在我的脑海中非常模糊),我想知道符号链接/连接故事是否可以在一种驱动器上工作,但不能在另一种驱动器上工作,以及是否有办法解决这个问题。
在u1686_gravity的答案之后编辑3 :
即使使用 UNC 路径并具有“正确”的配置行为,它似乎仍然不起作用:
fsutil behavior query symlinkEvaluation
Local to local symbolic links are enabled.
Local to remote symbolic links are enabled. => That's the one, isn't it?
Remote to local symbolic links are disabled.
Remote to remote symbolic links are disabled.
C:\<Runtime_Dir>mklink /D Logs \\petrvs01\Log\TestLog\
symbolic link created for Logs <<===>> \\petrvs01\Log\TestLog\
链接已创建,但那里没有创建日志文件。
因此,因为我认为我的方向是正确的,所以我决定执行另一个测试:使用 Windows 资源管理器进入Logs
目录/符号链接/连接点并使用资源管理器的上下文菜单创建一个简单的文本文件。这不起作用,因为出现以下错误消息:
到目前为止我学到了三件事:
- 要在 Windows 上创建符号链接,请使用
mklink
而不是 WSL 的ln -s
. 为此以管理员身份打开命令提示符。 - 要创建到远程目录的符号链接/连接,您需要使用 UNC 路径,而不是驱动器号。
fsutil
使用命令检查从远程目录创建符号链接/连接到远程目录的权限fsutil behavior query symlinkEvaluation
。
接下来我需要学习:在哪里检查符号链接/连接目标权限?有人有想法吗?
Linux 上符号链接的实现方式与 Windows 上不同:
这意味着 Windows 无法跟踪通过 Windows Linux 子系统 (WSL) 创建的符号链接。
Windows 使用 mklink 命令创建符号链接。
有关详细信息,请参阅文章
在 Windows 上创建符号链接(又名符号链接)的完整指南。
对于“访问被拒绝”的问题,我引用了 GambleNerd在网络驱动器上创建符号链接 部分 答案的帖子:
这是可能的,但您需要使用 UNC 路径而不是驱动器号,因为后者不一定是全局的 - 虽然物理卷具有全局分配,但每个登录会话都可以在其之上有自己的私有映射(例如,用户 1 可以有 Y :\ 代表一个位置,用户 2 可以让它代表另一个位置)。可以把它想象成每个用户在 Linux 上都有自己的“挂载命名空间”(pam_namespace)。
具体来说,所有“映射网络共享”驱动器号都是您的登录会话专用的,并且在遵循符号链接时在内核上下文中不会被理解。因此,如果目标位于另一台计算机上,则需要为其使用原始 UNC 路径:
您还应该确保本地到远程符号链接评估尚未通过
fsutil behavior query symlinkEvaluation
.icacls
在目标上运行– 或在资源管理器中右键单击它并转到“属性 > 安全”。此外,Windows 上的符号链接和连接可以拥有自己的权限,可以使用 进行检查
icacls Logs /l
。我怀疑这会是问题,因为链接最初会继承与普通目录相同的权限 - 但它可能值得检查。因此,首先确保文件/文件夹创建可以在不涉及符号链接的情况下进行,即直接通过 UNC 路径(或映射驱动器,没有区别),并且只有在工作完成后,才尝试通过符号链接执行相同的操作。
不要忘记,如果您的应用程序作为服务运行,并具有自己的凭据(服务帐户),则必须向该帐户授予权限;如果它作为“NetworkService”运行,则必须向计算机帐户(FOOBAR$)授予权限。(如果它作为“LocalService”运行,它将永远不会具有网络共享访问权限。)