"Fishing line and bobbin stuck on tree at Douthat State Park" by "Virginia State Parks" on Flickr

Note to self: Linux shell scripts don’t cope well with combined CRLF + LF files… Especially in User-Data / Custom Data / Cloud-Init scripts

This one is more a nudge to myself. On several occasions when building Infrastructure As Code (IAC), I split out a code sections into one or more files, for readability and reusability purposes. What I tended to do, and this was more apparent with the Linux builds than the Windows builds, was to forget to set the line terminator from CRLF to LF.

While this doesn’t really impact Windows builds too much (they’re kinda designed to support people being idiots with line endings now), Linux still really struggles with CRLF endings, and you’ll only see when you’ve broken this because you’ll completely fail to run any of the user-data script.

How do you determine this is your problem? Well, actually it’s a bit tricky, as neither cat, less, more or nano spot this issue. The only two things I found that identified it were file and vi.

The first part of the combined file with mixed line endings. This part has LF termination.
The second part of the combined file with mixed line endings. This part has CRLF termination.
What happens when we cat these two parts into one file? A file with CRLF, LF line terminators obviously!
What the combined file looks like in Vi. Note the blue ^M at the ends of the lines.

So, how to fix this? Assuming you’re using Visual Studio Code;

A failed line-ending clue in Visual Studio Code

You’ll notice this line showing “CRLF” in the status bar at the bottom of Code. Click on that, which brings up a discrete box near the top, as follows:

Oh no, it’s set to “CRLF”. That’s not what we want!

Selecting LF in that box changes the line feeds into LF for this file, but it’s not saved. Make sure you save this file before you re-run your terraform script!

Notice, we’re now using LF endings, but the file isn’t saved.

Fantastic! It’s all worked!

In Nano, I’ve opened the part with the invalid line endings.

Oh no! We have a “DOS Format” file. Quick, let’s fix it!

To fix this, we need to write the file out. Hit Ctrl+O. This tells us that we’re in DOS Format, and also gives us the keyboard combination to toggle “DOS Format” off – it’s Alt+D (In Unix/Linux world, the Alt key is referred to as the Meta key – hence M not A).

This is how we fix things

So, after hitting Alt+D, the “File Name to write” line changes, see below:

Yey, no pesky “DOS Format” warning here!

Using either editor (or any others, if you know how to solve line ending issues in other editors), you still need to combine your script back together before you can run it, so… do that, and your file will be fine to run! Good luck!

Featured image is “Fishing line and bobbin stuck on tree at Douthat State Park” by “Virginia State Parks” on Flickr and is released under a CC-BY license.

JonTheNiceGuy

He/Him. Husband and father. Linux advocating geek. Co-Host on the AdminAdmin Podcast, occasional conference speaker.

4 thoughts to “Note to self: Linux shell scripts don’t cope well with combined CRLF + LF files… Especially in User-Data / Custom Data / Cloud-Init scripts”

  1. Very useful.

    Came across the very problem recently when creating (copying and modifying really) a python script in VScode and then getting an error when the script was ran on a Linux server.

    I ended up using the app (dos2unix) referenced in this post – https://askubuntu.com/questions/896860/usr-bin-env-python3-r-no-such-file-or-directory/896880#896880

    And your post got me thinking that I should just set the default file ending to LF in VScode – it’s in settings ( ctrl + , ) – Text Editor – Files – Eol – set it to \n

    Any issues doing this that you are aware of.

    Cheers

    1. Thanks Simon,

      I’ve not seen any negative effects to having Windows Powershell scripts being LF-only terminated, but I have seen issues with Batch Files, so if you’re editing either of those, that might be an issue… but if you’re mostly working with files in the Linux world, then you should be fine :)

  2. Hiya Jon – for what its worth, cat -A will show the giveaway ^M control characters of a CRLF!

    (andyf@eff):/mnt/c/temp$ cat -A wintextfile-utf8.txt
    this is a file^M$
    with presumably windows line endings^M$
    no empty line at the end

    (andyf@eff):/mnt/c/temp$ cat -A wintextfile-utf8.txt
    this is a file^M$
    with presumably windows line endings^M$
    no empty line at the end

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.