Windows CRLF to Unix LF Issues in Vagrant

Jonathan picture Jonathan · Feb 21, 2015 · Viewed 8.2k times · Source

I'm working on provisioning a few VMs using Vagrant. Here's the situation:

Host: Windows 7 (64-bit)

Guest: Ubuntu 14.04 (64-bit)

I am having an issue getting the CRLF line endings to convert to LFs. This is causing the bash scripts in the shared folder to fail within the guest machine (see below).

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

In my Vagrantfile I have set the shell privisioner parameter binary to 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

As per the Vagrant documentation:

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".

What's the issue here? Am I overlooking something in the documentation?


Update 1: I have tried to edit my local Git settings as recommended in this Stack Overflow answer, but no luck. Also, I have added a .gitattributes file to the root directory of the project and added the following to that file:

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

I have also read over "Dealing with line endings" document provided by Git. When I commit to my repository CRLFs are converted to LFs, but when I checkout changes in a Windows workspace the LFs are converted to CRLFs. This is the exact behavior I want in my Git workflow. The issue is with Vagrant. The binary flag that I set doesn't perform the way the documentation describes.


Update 2: Changing s.binary = true fixed the issue. However, I think the wording in the documentation should be re-addressed. The documentation states that "If this [the flag] is true, then Vagrant will not do this [change CRLF to LF]." As I understand then, Vagrant will not change CRLFs to LFs if this flag is set. However, CRLFs are changed to LFs if this is set to true.

Answer

kenorb picture kenorb · Mar 14, 2016

You're right, the documentation about binary was misleading. I've proposed a pull-request and this has been corrected on the documentation page.

So now it states:

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.

So to replace Windows line endings (CRLF) with Unix line endings (LF) you need to set:

s.binary = true

Alternative solutions includes:

  • 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
    

If you're using Git for versioning your code, you should:

  • 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.