Windows Vagrant 中的 CRLF 到 Unix LF 问题

Windows CRLF to Unix LF Issues in Vagrant

我正在使用 Vagrant 配置一些虚拟机。情况是这样的:

主机:Windows 7(64 位)

访客:Ubuntu 14.04(64 位)

我在将 CRLF 行结尾转换为 LF 时遇到问题。这导致共享文件夹中的 bash 脚本在来宾计算机中失败(见下文)。

vagrant@vagrant-host:/vagrant/bin$ sudo bash build-ubuntu-14.04.1-c
make.sh
build-ubuntu-14.04.1-cmake.sh: line 5: $'\r': command not found
build-ubuntu-14.04.1-cmake.sh: line 19: $'\r': command not found
: invalid option04.1-cmake.sh: line 21: set: -
set: usage: set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
build-ubuntu-14.04.1-cmake.sh: line 22: $'\r': command not found
build-ubuntu-14.04.1-cmake.sh: line 24: $'\r': command not found
build-ubuntu-14.04.1-cmake.sh: line 26: $'\r': command not found
build-ubuntu-14.04.1-cmake.sh: line 29: $'\r': command not found
build-ubuntu-14.04.1-cmake.sh: line 36: $'\r': command not found
build-ubuntu-14.04.1-cmake.sh: line 42: $'\r': command not found
build-ubuntu-14.04.1-cmake.sh: line 46: $'\r': command not found
build-ubuntu-14.04.1-cmake.sh: line 48: $'\r': command not found
build-ubuntu-14.04.1-cmake.sh: line 50: $'\r': command not found
build-ubuntu-14.04.1-cmake.sh: line 226: syntax error: unexpected end of file

在我的 Vagrantfile 中,我将 shell privisioner 参数 binary 设置为 false。

# Provision the VM
ubuntu.vm.provision "shell" do |s|
  # replace Windows line endings with Unix line endings
  s.binary = false

  s.inline = "sudo apt-get update;
              sudo bash vagrant/bin/build-ubuntu-14.04.1-cmake.sh"
end

根据 Vagrant 文档:

binary (boolean) - Vagrant automatically replaces Windows line endings with Unix line endings. If this is true, then Vagrant will not do this. By default this is "false". If the shell provisioner is communicating over WinRM, this defaults to "true".

这里有什么问题?我是否忽略了文档中的内容?


更新 1: 我曾尝试按照 this Stack Overflow answer 中的建议编辑我的本地 Git 设置,但没有成功。另外,我在项目的根目录中添加了一个 .gitattributes 文件,并在该文件中添加了以下内容:

# detect all text files and automatically normalize them (convert CRLF to LF)
*       text=auto

我也阅读了 Git 提供的 "Dealing with line endings" 文档。当我提交到我的存储库时,CRLF 被转换为 LF,但是当我在 Windows 工作区中签出更改时,LF 被转换为 CRLF。这正是我在 Git 工作流程中想要的行为。问题出在 Vagrant 身上。我设置的 binary 标志没有按照文档描述的方式执行。


更新 2: 更改 s.binary = true 解决了这个问题。但是,我认为应该重新处理文档中的措辞。文档指出 "If this [the flag] is true, then Vagrant will not do this [change CRLF to LF]." 据我了解,如果设置了此标志,Vagrant 将 不会 将 CRLF 更改为 LF。但是,如果将其设置为 true,则 CRLF 会更改为 LF。

正如我上面在更新中指定的那样,更改 s.binary = true 解决了这个问题。但是,我认为应该重新处理文档中的措辞。文档指出 "If this [the flag] is true, then Vagrant will not do this [change CRLF to LF]." 据我了解,如果设置了此标志,Vagrant 将 不会将 CRLF 更改为 LF。但是,如果将其设置为 true,则 CRLF 会更改为 LF。

你是对的,documentation about binary was misleading. I've proposed a pull-request,这已在文档页面上得到更正。

所以现在它说:

binary (boolean) - Vagrant automatically replaces Windows line endings with Unix line endings. If this is false, then Vagrant will not do this. By default this is false. If the shell provisioner is communicating over WinRM, this defaults to true.

因此,要用 Unix 行结尾 (LF) 替换 Windows 行结尾 (CRLF),您需要设置:

s.binary = true

替代解决方案包括:

  • 手动更改行结尾:

    • 使用dos2unix命令,
    • 使用ex命令,例如

      ex +'bufdo! %! tr -d \r' -scxa *.sh
      
  • 将以下行添加到您的 Bashrc 文件中(例如 ~/.bashrcgist:

    export SHELLOPTS
    set -o igncr
    

如果您使用 Git 对代码进行版本控制,您应该:

  • 通过将 core.autocrlf 选项设置为 inputfalse,在 OS X 上配置 Git 以正确处理行尾。

    如果您在 Windows 上安装了 Git,最常见的错误是 select Checkout Windows-style 选项,因此您应该重新安装它并选择:按原样检出并提交 Unix 样式的行结尾(core.autocrlf 设置为 input)或 检出为-is,按原样提交core.autocrlf 设置为false)。

  • 考虑在您的存储库 (.gitattributes) 中创建 git 规范化文件,以确保在签出和签入时都没有 CRLF 行结尾,例如:

    *.sh     text eol=lf
    

    因此编辑您的配置脚本的人不会中断行尾。

  • 另请阅读:Dealing with line endings GitHub 帮助。

  • 相关:'\r': command not found - .bashrc / .bash_profile.

也许完成以上:

2020 年 9 月,在 Windows 10 台计算机上使用 Vagrant 2.2.10,默认行为显然是尝试替换 Windows 行尾。然而,这意味着如果您确实在 Vagrantfile 中使用 Linux 行结尾 - 它不会起作用!

我被几个略有不同的错误搞糊涂了,比如

"Vagrantfile:1: syntax error, unexpected tIDENTIFIER, 
expecting end-of-input [+ reference to different places in the Vagrantfile]"

通过猜测,我终于想到了将我的行结尾从 Linux LF 更改为 Windows CR+LF,这使它一切正常。

TL;DR: Using Vagrant on windows, use Windows line endings (CR+LF) in your Vagrantfiles.