简体   繁体   English

wsl2网络驱动下git如何处理

[英]How to handle git under wsl2 network drive

I just configured docker to run under wsl2.我刚刚配置了 docker 在 wsl2 下运行。 That worked without any relevant problems and our projects are running fine.这没有任何相关问题,我们的项目运行良好。

I followed this article by docker on how to setup the wsl2 docker environment: https://www.docker.com/blog/docker-desktop-wsl-2-best-practices/ I followed this article by docker on how to setup the wsl2 docker environment: https://www.docker.com/blog/docker-desktop-wsl-2-best-practices/

The article recommends to put the project files into the linux system and NOT access it by using the mounts under /mnt for performance reasons.文章建议将工程文件放到 linux 系统中,出于性能考虑,不要使用/mnt下的挂载来访问它。

For accessing the files, the article suggests the following options:为了访问这些文件,本文建议使用以下选项:

  • Use Visual Studio Code (which can access wsl directly)使用Visual Studio Code(可以直接访问wsl)
  • Use the network share under \\wsl$\使用\\wsl$\下的网络共享
  • Run the IDE directly inside the linux直接在linux里面运行IDE

Some collegues use IDE's that are neither compatible with linux nor can access wsl.有的同学使用的IDE既不兼容linux也不能访问wsl。 So I tried to let them access the project through the network share.所以我尝试让他们通过网络共享访问项目。 Those collegues use the git integration in their IDE's and are not comfortable with the git cli.那些同事在他们的 IDE 中使用 git 集成,并且对 git cli 不满意。

Git works well, with just a little problem. Git 运行良好,只是有点小问题。 We have files in the repository, that have the executable permission (+x).我们在存储库中有文件,这些文件具有可执行权限 (+x)。 Thoses file have the perms 755 on linux and 644 on windows network drive.这些文件在 linux 上的权限为 755,在 windows 网络驱动器上的权限为 644。

Because the actual file perms differ from the linux environment, git detects a change for those files.因为实际的文件权限与 linux 环境不同,所以 git 检测到这些文件的更改。

Is there a way, to expose the correct file perms to the windows environment?有没有办法将正确的文件权限暴露给 windows 环境?

Do you have any other ideas on how to solve the problem?你对如何解决这个问题还有其他想法吗?

To sync Linux file permissions, you need to enable metadata for your Linux distro.要同步 Linux 文件权限,您需要为 Linux 发行版启用元数据。 Create /etc/wsl.conf file with this content:使用以下内容创建/etc/wsl.conf文件:

[automount]
root = /
options = "metadata"

root is optional but useful, mounting your Windows drive to /c instead of /mnt/c , which saves you a few keystrokes. root是可选的,但很有用,将 Windows 驱动器安装到/c而不是/mnt/c ,这样可以节省一些按键。

To make sure this takes effect, sign out Windows and in again.为确保此操作生效,请注销 Windows 并再次登录。

Check out the documentation for more details, as well as advanced settings like setting umask .查看 文档了解更多详细信息,以及设置umask等高级设置。

While at that, remember to enable Git's auto CRLF handling :此时,请记住启用 Git 的自动 CRLF 处理

$ git config --global core.autocrlf true

Which will save you a lot of trouble when working with Git on WSL.在 WSL 上使用 Git 时,这将为您省去很多麻烦。

I had a similar problem with git where you may not be able to run a commit with various cryptic errors.我在git遇到了类似的问题,您可能无法运行带有各种神秘错误的提交。 Part of that is how git opens files, so hopefully this post goes some way to unpicking that.部分原因是git如何打开文件,所以希望这篇文章能在某种程度上解决这个问题。

Background背景

In the latest Windows builds there are some changes in WSL regarding how it interacts with your file system.在最新的 Windows 版本中,WSL 与文件系统交互的方式发生了一些变化。 One problem is the fact that previously, the incompatibility between Windows and Linux file-systems meant most files effectively had permissions '777' on external storage, so any user could read/write/execute anything.一个问题是,以前,Windows 和 Linux 文件系统之间的不兼容意味着大多数文件实际上对外部存储具有“777”权限,因此任何用户都可以读取/写入/执行任何内容。 This isn't really ideal for Linux, as you can't store private keys etc. Microsoft have changed that behaviour now so files can have both Windows (NTFS) and Linux permissions, through extension attributes.这对于 Linux 来说并不理想,因为您不能存储私钥等。微软现在已经改变了这种行为,因此文件可以同时具有 Windows (NTFS) 和 ZEDC9F0A5A5D57797BF68E3736474383Z 权限,通过扩展属性。 On a normal drive it's fine to overcome, you can mount the drive with metadata using the following command:在普通驱动器上可以克服,您可以使用以下命令安装带有元数据的驱动器:

umount /mnt/c;
mount -t drvfs C:\\ /mnt/c/ -o metadata

Unfortunately they seem to have rolled that change out to network and external filesystems too (like exFAT ), which doesn't have extensible attributes and gets in a bit of a mess, making external drives unusable.不幸的是,他们似乎也将这种变化推广到了网络和外部文件系统(如exFAT ),它没有可扩展的属性并且有点混乱,使得外部驱动器无法使用。 For example, if the file is read-only in Windows then you can't write to it in WSL;例如,如果文件在 Windows 中是只读的,那么您不能在 WSL 中写入; you can't override it with sudo either because Windows permissions override WSL ones regardless.您也不能用sudo覆盖它,因为 Windows 权限会覆盖 WSL 权限。 The changes break a lot of programs, which I found out today trying to upload changes to git.这些更改破坏了很多程序,我今天发现它们试图将更改上传到 git。 It's one of those new problems which doesn't actually have solutions on the Internet yet, so I've attached a file will solve that issue.这是互联网上实际上还没有解决方案的新问题之一,所以我附上了一个文件来解决这个问题。

To run, first compile the shared object:要运行,首先编译共享的 object:

cc -Wall -O3 -D_GNU_SOURCE -fPIC -c -o githack.o githack.c; gcc -o githack.so -nostartfiles -shared githack.o -ldl;

Then run the command prefixed with LD_PRELOAD :然后运行以LD_PRELOAD为前缀的命令:

LD_PRELOAD=./githack.so git commit -a -m "Another interesting commit"

How to investigate for other programs如何调查其他程序

For git , the issue specifically is seen:对于git ,具体问题如下:

error: insufficient permission for adding an object to repository database .git/objects

To find out why it failed, you can use strace :要找出失败的原因,您可以使用strace

strace git commit -a -m "Another interesting commit"

>

...

gettimeofday({tv_sec=1592618056, tv_usec=52991}, NULL) = 0

getpid()                               = 651

openat(AT_FDCWD, ".git/objects/78/tmp_obj_flbKNc", O_RDWR|O_CREAT|O_EXCL, 0444) = -1 EACCES (Permission denied)

write(2, "error: insufficient permission f"..., 88error: insufficient permission for adding an object to repository database .git/objects

) = 88

close(4)                               = 0

...

Immediately before the error line printed we see why it failed ( -1 ), so to fix it requires intercepting that call.在打印错误行之前,我们立即看到它失败的原因( -1 ),因此要修复它需要拦截该调用。 You can determine that from ltrace :您可以从ltrace确定:

ltrace git commit -a -m "Latest local copy from George"

>

...

open64(".git/objects/78/tmp_obj_zDayCc", 194, 0444)                                                                                                         = -1

__errno_location()                                                                                                                                          = 0x7f2777001000

__errno_location()                                                                                                                                          = 0x7f2777001000

__vsnprintf_chk(0x7fffd4786d00, 4096, 1, 4096)                                                                                                              = 80

__fprintf_chk(0x7f277631c680, 1, 0x7f27773eacfc, 0x7f27773c8083error: insufficient permission for adding an object to repository database .git/objects

)                                                                                            = 88

close(4)

...

And so the attached code at the bottom of this post intercepts the open64 code with flags equal 194 .因此,这篇文章底部的附加代码拦截了标志等于194open64代码。

Solution code (name githack.c)解决方案代码(名称 githack.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
//#define openat ignorethisopen
#define open ignorethisopen
#define open64 ignorethisopen64
#include <fcntl.h>
//#undef openat
#undef open
#undef open64
#include <dlfcn.h>


/*
    'strace git ...' will show git fail on an openat() command
    this is probably implemented as open64() on your system
    you can confirm this by use of 'ltrace git ...'
    you may also need to adjust the oflag comparison of 194
    George O'Neill 2020/06/20 (feel free to reach out if issues remain)
*/


/*static int (*___openat)(int, char *, int, mode_t);*/
static int (*___open)(const char *, int, mode_t);
static int (*___open64)(const char *, int, mode_t);


static void* dlwrap(const char *fn)
{
    const char *e;
    void *p = dlsym(RTLD_NEXT, fn);
    if ((e=dlerror())!=0)
        fprintf(stderr, "dlsym(RTLD_NEXT,'%s'): %s\r\n", fn, e);
    return p;
}


void _init(void)
{
    ___open = dlwrap("open");
    ___open64 = dlwrap("open64");
}


/*int openat(int dirfd, const char *pathname, int oflag, mode_t mode)*/
int open(const char *pathname, int oflag, mode_t mode)
{
    if (oflag && oflag == 194)
        return ___open(pathname, oflag, S_IRWXU);
    return ___open(pathname, oflag, mode);
}


int open64(const char *pathname, int oflag, mode_t mode)
{
    if (oflag && oflag == 194)
        return ___open64(pathname, oflag, S_IRWXU);
    return ___open64(pathname, oflag, mode);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM