我的应用程序正在将日志写入一个目录,该目录被硬编码为“Logs”,位于我的应用程序的运行时目录下。
今天,一位客户问我是否可以将这些日志放在另一个地方(另一台计算机上)。
作为第一次测试,我尝试创建一个符号链接:
- 我停止了申请。
- 我删除了“日志”目录。
- 使用我电脑上的 WSL,我创建了一个符号链接,类似于
ln -s /mnt/c/Temp_Folder/TestLog/ /mnt/c/<Application>/Logs
。 - 我启动了我的申请。
我没有看到目录中出现任何日志C:\Temp_Folder\TestLog\
。
我看到不同的原因:
- 尝试在 Windows 计算机上使用 Linux 技术是一个完全愚蠢的想法。
- 它可能有效,但需要考虑一些额外的事情。
我希望是第二种选择,但是那样的话,我需要考虑什么事情呢?
修改于哈利的回答:ln -s
如果可以使用 Windows 技术, 为什么还要使用 WSL 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 中创建驱动器有两种甚至三种方法(驱动器映射、替换(?)和另一种(?),这些我都记不清了),我想知道符号链接/连接是否可能在一种驱动器上起作用,但在另一种驱动器上不起作用,以及是否有办法解决这个问题。
回答后编辑3u1686_重力:
即使使用 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
目录/symlink/junction,并使用资源管理器的上下文菜单创建一个简单的文本文件。由于以下错误消息,此操作不起作用:
到目前为止我学到了三件事:
- 要在 Windows 上创建符号链接,请使用
mklink
而不是 WSL 的ln -s
。为此,以管理员身份打开命令提示符。 - 要创建到远程目录的符号链接/连接,您需要使用 UNC 路径,而不是驱动器号。
fsutil
使用命令检查从远程目录创建符号链接/连接的权限fsutil behavior query symlinkEvaluation
。
接下来我需要学习的是:在哪里检查符号链接/连接目标权限?有人知道吗?
答案1
Linux 上的符号链接的实现与 Windows 上的不同:
- 在 Windows 上,符号链接是一个由内核调用实现和操作的文件表条目
- 在 Linux 上,符号链接只是一个带有特殊标志的文本文件,其内容是到目标的路径。(该路径甚至不必有效。)
这意味着通过 Windows Subsystem for Linux (WSL) 创建的符号链接(或符号链接)不能被 Windows 跟踪。
Windows 使用以下方式创建符号链接 mklink 命令。
更多信息请参阅文章
在 Windows 上创建符号链接 (又名 Symlinks) 的完整指南。
对于“拒绝访问”的问题,我引用了这篇文章 在网络驱动器上创建符号链接 的一部分 GambleNerd 的回答:
访问被拒绝修复
mklink /D
如果您以管理员身份运行该命令,并且Link
该命令的一部分是 UNC 网络路径并且您收到Access Denied
错误消息,请按照以下步骤操作以解决此问题。
- 在那里的服务器上(和/或在 Windows 客户端电脑上运行该命令时收到“访问被拒绝”错误消息)该命令的部分
Link
位于,在服务器上以管理员身份运行此命令:fsutil behavior query SymlinkEvaluation
- 如果看到
Remote to remote symbolic links are disabled.
则运行此命令:fsutil behavior set SymlinkEvaluation R2R:1
- 您可以从运行 MKLINK 命令并被拒绝访问的位置运行此命令,无论是在 Windows 服务器本身还是 Windows 客户端 PC 上
- 现在尝试再次运行您的命令,希望它现在能成功运行。
链接参考: mklink 上的访问被拒绝
答案2
有没有办法在 Windows 计算机上使用类似 Linux 的符号链接来引用另一台计算机上的位置?
这是可能的,但您需要使用 UNC 路径而不是驱动器号,因为后者不一定是全局的——虽然物理卷具有全局分配,但每个登录会话都可以在此基础上拥有自己的私有映射(例如,用户 1 可以使用 Y:\ 来表示一个位置,而用户 2 可以使用它来表示另一个位置)。可以将其想象成每个用户在 Linux 上都有自己的“安装命名空间”(pam_namespace)。
具体来说,所有“映射网络共享”驱动器号都是您的登录会话专用的,并且在跟踪符号链接时不会在内核上下文中被理解。因此,如果目标在另一台计算机上,您需要为其使用原始 UNC 路径:
cmd /c mklink /d Logs \\FileServer\Trash\Logs
您还应确保本地到远程符号链接评估尚未被禁用fsutil behavior query symlinkEvaluation
。
在哪里检查符号链接/连接目标权限?有人知道吗?
icacls
在目标上运行- 或在资源管理器中右键单击它并转到“属性>安全”。
icacls \\FileServer\Trash\Logs
此外,Windows 上的符号链接和连接能有自己的权限,可以使用 进行检查icacls Logs /l
。我怀疑这不是问题,因为链接最初会继承与普通目录相同的权限 - 但可能值得检查。
因此首先确保文件/文件夹创建成功没有涉及符号链接,即直接通过 UNC 路径(或映射驱动器,没有区别),并且只有在工作之后,才尝试通过符号链接执行相同操作。
不要忘记,如果您的应用程序作为服务运行,并具有自己的凭据(服务帐户),则必须向该帐户授予权限;如果它作为“NetworkService”运行,则必须向机器帐户 (FOOBAR$)。(如果它以“LocalService”身份运行,它将永远不会具有网络共享访问权限。)