我在 WSL2 下的 Debian 中工作,但是因为我的项目文件存在于 Windows 文件系统中,所以我一直在通过 WSL 互操作使用 Git for Windows,并带有这样的 shell 函数:
git() {
case "$PWD" in
/mnt/*)
/mnt/c/Program\ Files/Git/bin/git.exe "$@"
;;
*)
/usr/bin/git "$@"
;;
esac
}
通常这很好用并且可以快速完成工作(比 git 从 VM 内部访问 repo 中的每个文件要快得多)。
但是,我注意到,很多时候,它最终会留下杂散的 git 进程。好吧,在我的 git 命令完成运行之后,我仍然有很多git.exe
只是坐在那里,有时仍然持有打开的文件句柄,但实际上并没有做任何事情。
它有时会导致后续 git 命令的执行速度明显变慢,工作树中的文件被阻止,并且假设最终可能导致 repo 损坏。
我已经确定,当我将 git 命令的长输出通过管道传输到WSLless
或head
WSL 时,通常会发生这种情况,例如
git log | less
git log | head -n 64
并非所有管道都像这样 - 例如,管道到cat
,nano -
或确实tail
正确终止了 git.exe。
是什么原因造成的,有没有办法解决它?
git version 2.33.0.windows.2
这可能是由于 Windows 和 Unix 上的不同信号处理。
在 Unix 上,当管道右侧的进程(例如
less
)退出时,左侧的进程在尝试再次写入管道时会收到一个 SIGPIPE,或者,如果它阻塞了,则会收到一个 EPIPE 错误。通常,该信号会终止进程并阻止它产生更多输出。但是,Windows 没有此功能或 SIGPIPE,因此该进程在完成写入数据或出现错误之前不会终止。您会注意到不会导致挂起进程的命令会读取所有输入,而会导致挂起进程的命令则不会。
如果要在 WSL 下使用程序,则应避免以这种方式使用 Git for Windows,因为它无法接收 SIGPIPE 并退出。