【发布时间】:2020-12-23 03:39:27
【问题描述】:
总结:
在 64 位 cygwin 的最新(2020 年 9 月)版本中,/bin/ 和 /lib 目录中的符号链接具有令人费解的特性,并且似乎与其他各种记录的符号链接不同。问题是:
-
为什么它们在 CMD.EXE 中隐藏,但在其他地方可见,不像 其他符号链接类型
-
是否可以创建具有相同功能的符号链接?如果有,怎么做?
TL;DR
请参阅@matzeri 的回答:SYSTEM 属性设置在/bin/awk,使其对 CMD.EXE 会话不可见。
/bin 和 /lib 下面的符号链接似乎是此处描述的两种“默认 cygwin 符号链接”之一:
Cygwin 创建的默认符号链接要么是特殊的重解析 在 Windows 10 上与 WSL 共享的点,或包含 魔术饼干后跟链接指向的路径。这 重解析点在 NTFS 上使用,在几乎任何其他的普通文件上 文件系统。 见symbolic links
但是,/bin 下面的所有符号链接都设置了 SYSTEM 属性,/lib 下面的大多数符号链接都没有。我不知道我是如何在 NTFS 上创建一个带有魔法 cookie 的符号链接的。
以下是问题的长版本
cygwin 下有多种类型的符号链接。其他问题解释它们的历史,描述它们的差异,并展示如何创建它们等。例如:
check the difference of symlink type in cygwin
下面是关于 windows 上符号链接的一些历史和问题的讨论:
Symlinks on the mounted Windows directories are not compatible with native
如上所述,有快捷方式、连接点和符号链接,所有这些都可以从 CMD.EXE 会话中看到,如图所示。
但是,在我的 64 位 cygwin 安装下,还有另一种我找不到任何解释的类型。其中一些出现在/bin、/lib 下方,也许还有其他地方。它们与其他 3 种区别的主要特征是它们在 CMD.EXE 会话中不可见。
这是一个例子: 如果我尝试通过 /bin 目录中的 CMD.EXE 列出“awk”,则该文件似乎不存在:
$ cd /bin
$ cmd.exe /c dir awk
Volume in drive C is opt
Volume Serial Number is D0C8-EA58
Directory of C:\cygwin64\bin
File Not Found
这是 ls 的样子:
$ ls -l awk
lrwxrwxrwx 1 philwalk None 8 May 14 12:26 awk -> gawk.exe
但根据我的经验,大多数符号链接在 CMD.EXE 会话中是可见的。让我们为测试创建一个符号链接:
$ CYGWIN=winsymlinks:nativestrict # make sure we don't create an old-style symlink
$ ln -s `which ls.exe` ls-link
$ cmd.exe /c dir ls-link
Volume in drive C is opt
Volume Serial Number is D0C8-EA58
Directory of C:\opt\ue
2020-09-03 13:12 <SYMLINK> ls-link [C:\cygwin64\bin\ls.exe]
1 File(s) 0 bytes
0 Dir(s) 295,290,556,416 bytes free
这表明 CMD.EXE 可以看到这种类型的符号链接。
似乎所有符号链接都可以像这样取消引用:
$ cygpath -w `which awk`
C:\cygwin64\bin\gawk.exe
那么基于 Windows 的程序可以取消引用它们吗?它可以看到它们吗?因为它们对 CMD.EXE 不可见,所以我猜想它们对任何其他窗口(即非 cygwin)程序都不可见。
这是一个 Scala 脚本,deref.sc,它将测试这些问题:
#!/usr/bin/env scala
import java.nio.file._
for( posixPath <- args ){
val cyg = cygpath(posixPath)
val windows = Paths.get(posixPath)
val exists = Files.exists(windows)
printf("file path [%s]\n",posixPath )
printf("cygpath [%s]\n",cyg)
printf("windows [%s]\n",windows)
if( exists ){
printf("exists [%s] # visible to jvm-based programs\n",exists)
} else {
printf("exists [%s] # NOT visible to jvm-based programs\n",exists)
}
val realpath = if( exists ){
if( Files.isSymbolicLink(windows) ){
Files.readSymbolicLink(windows)
} else {
windows.toRealPath()
}
}
printf("real windows [%s]\n",realpath)
printf("\n")
}
def cygpath(posixPath:String) = {
import scala.sys.process._
Seq("cygpath.exe","-m",posixPath).lazyLines_!.mkString("")
}
这是 deref.sc 的输出,应用于 /bin/awk 和 ./ls-link。 (我们必须通过 /bin/awk 的 windows 可见版本)
$ deref.sc ls-link
cygpath [ls-link]
windows [.\ls-link]
exists [true] # visible to jvm-based programs
real windows [C:\cygwin64\bin\ls.exe]
$ cd /bin
$ deref.sc awk
file path [awk]
cygpath [C:/cygwin64/bin/gawk.exe]
windows [awk]
exists [true] # visible to jvm-based programs
real windows [C:\cygwin64\bin\awk]
所以这说明,虽然有些windows程序(比如CMD.EXE)看不到c:/cygwin64/bin/awk,但是其他的(比如基于jvm的程序)可以!
我最初的问题是基于 Windows 程序无法看到这些新符号链接的错误假设,由于这不正确,剩余的问题是:
这些新符号链接是什么,它们是如何创建的?它们真的不同吗,或者这可能是权限的副作用?以管理员身份运行 CMD.EXE 似乎没有什么区别。
我验证了 c:/cygwin64/bin/awk 在 WSL 会话中也是可见的,尽管鉴于 jvm 可以看到它们,这并不奇怪。
更新:看起来,虽然/bin/awk 对我们的程序可见,但java.nio.file.Files.isSymbolicLink() 并不认为它是符号链接。它的内容由字符串"!<symlink>gawk.exe" 组成,因此它似乎是早期的 cygwin 符号链接实现,在 windows 提供本机符号链接之前。
除了在 CMD.EXE 中不可见之外,其他没什么特别的。
【问题讨论】:
-
awk是一个带有SystemWindows 属性的普通文件,因此默认情况下是隐藏的。使用dir /A显示隐藏文件。 -
这是 cygwin 特定的符号链接。在 Windows 中,这只是一个包含
!<symlink>gawk.exe\0的纯文本文件