Windows下的CRLF转Unix LF在Vagrant中出现问题

20
我正在使用 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 provisioner参数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文档:
二进制(布尔值)- Vagrant会自动将Windows行尾替换为Unix行尾。如果设置为true,则Vagrant不会这样做。默认情况下,它为“false”。如果shell provisioner通过WinRM进行通信,则默认为“true”。
问题出在哪里?我是否忽略了文档中的某些内容?

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

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

我还阅读了Git提供的"处理换行符"文档。当我提交到我的存储库时,CRLF会转换为LF,但是当我在Windows工作区检出更改时,LF会转换为CRLF。这正是我想要的Git工作流程。问题出在Vagrant上。我设置的binary标志没有按照文档描述的方式执行。
更新2:s.binary = true 更改后问题得到解决。然而,我认为文档中的措辞需要重新审视。文档指出:“如果这个标志为真,则 Vagrant 不会 进行此操作 [将 CRLF 更改为 LF]”。据我理解,如果设置了此标志,Vagrant 将 不会 将 CRLF 更改为 LF。然而,如果将其设置为 true,则 CRLF 会被更改为 LF。

1
你应该回答自己的问题,因为你解决了它。此外,git的行尾处理只对在文件系统和git数据库之间移动的数据产生影响。它不会在共享文件夹上进行递归的dos2unix操作。如果你有一个专门用于Windows和Linux的独立工作目录,并使用git pull在它们之间移动代码,那么它将非常有效。你可以拥有带有LF结尾的规范提交版本,以及带有CRLF行尾的Windows检出版本。(以及没有转换或强制转换为LF结尾的Linux检出版本。) - Peter Cordes
你当时使用的是哪个 Vagrant 版本? - Dean Rather
@DeanRather 我正在使用最新版的 1.7.1 - Jonathan
3个回答

15

你是对的,关于binary文档是有误导性的。我已经提出了一份拉取请求,并且文档页面已经进行了更正。

现在它的说明如下:

binary(布尔值)- Vagrant会自动将Windows行结束符替换为Unix行结束符。如果这个值为false,那么Vagrant就不会这样做。默认情况下,这个值为false。如果shell provisioner正在通过WinRM通信,则默认值为true

因此,要将Windows行结束符(CRLF)替换为Unix行结束符(LF),需要设置:

s.binary = true

备选方案包括:

  • Changing line endings manually by:

    • using dos2unix command,
    • using ex command, e.g.

      ex +'bufdo! %! tr -d \\r' -scxa *.sh
      
  • Add the following lines into your Bashrc file (e.g. ~/.bashrc)gist:

    export SHELLOPTS
    set -o igncr
    
如果您正在使用Git来管理代码版本,您应该:
  • Configure Git on OS X to properly handle line endings by setting core.autocrlf option to input or false.

    If you've installed Git On Windows, the most common mistake is to select Checkout Windows-style option during installation, so you should re-install it and choose either: Checkout as-is and commit Unix-style line endings (core.autocrlf is set to input) or Checkout as-is, commit as-is (core.autocrlf is set to false).

  • Consider creating git normalization file in your repository (.gitattributes) which ensures no CRLF line-endings are in place, neither on checkout nor on checkin, for example:

    *.sh     text eol=lf
    

    So people editing your provisioning script, they won't break the line endings.

  • Read also: Dealing with line endings at GitHub Help.

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

这是个好消息!谢谢。 - Jonathan

8
如我在更新中所指定的,更改 s.binary = true 解决了问题。然而,我认为文档中的措辞应该重新审视。文档说明:“如果这个 [标志] 是真的,那么 Vagrant 将不会将 CRLF 改为 LF。” 据我理解,如果设置了此标志,则 Vagrant 不会将 CRLF 改为 LF。然而,如果将其设置为 true,则 CRLF 会被更改为 LF。

看起来他们现在已经更正了文档:https://www.vagrantup.com/docs/provisioning/shell#binary - Kmeixner

0

或许可以补充一下:

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,这使得一切都正常工作。

简而言之,在Windows上使用Vagrant时,请在您的Vagrantfiles中使用Windows行尾(CR+LF)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接