egor-tensin/setup-cygwin

Can't run most basic commands due to CRLF: ls\r not found

Endle opened this issue · 8 comments

Endle commented

Proof of concept:


on:
  push:
    branches: [ develop,cygwin ]
  pull_request:
    branches: [ develop ]
  workflow_dispatch:

jobs:


  win-build-upstream-mono:
    runs-on: windows-2019
    steps:
      - uses: actions/checkout@v2
      - name: Set up Cygwin
        uses: egor-tensin/setup-cygwin@v3
        with:
          platform: x64
          packages: git unzip
      - name: check env
        shell: bash
        run: |
          ls
          pwd
          ls -a

   

I have such error:


Run ls
  ls
  pwd
  ls -a
  shell: C:\tools\cygwin\bin\bash.EXE --noprofile  -e -o pipefail {0}
  env:
    CYGWIN: 
D:\a\_temp\a2ea1fad-fdcb-46f8-8a2c-62d654473fda: line 1: $'ls\r': command not found
Error: Process completed with exit code 127.

@Endle Hello! You're doing it a bit wrong, I'm afraid. First, bash really doesn't like \r\n line endings. To work around that in Cygwin, you need to pass the -o igncr option. Second, I'm pretty sure that Cygwin's bash requires that you invoke it as a "login shell" (using --login). To make it work, you can do something like this:

steps:
  - name: check env
    run: |
      ls
      pwd
      ls -a
    shell: C:\tools\cygwin\bin\bash.exe --login --norc -eo pipefail -o igncr '{0}' 

For an example, please see my test workflow at

But you don't even need to do that, since Cygwin's /usr/bin (as well as /usr/local/bin) is added to the system PATH, so you can just call ls and pwd directly:

steps:
  - name: check env
    run: |
      ls.exe
      pwd.exe
      ls.exe -a
Endle commented

Thank you! Using the full configuration resolves my problem

shell: C:\tools\cygwin\bin\bash.exe --login --norc -eo pipefail -o igncr '{0}' 

I created a PR for those who may have similar doubts #5

Recent bash for cygwin 4.4.12(3)-release is broken: it didn't want to propagate igncr:

C:\cygwin64\bin\bash.exe -o igncr
echo $SHELLOPTS
> braceexpand:emacs:hashall:histexpand:history:igncr:interactive-comments:monitor
bash
echo $SHELLOPTS
> braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor

That's why any subscript fails, so bash -o igncr is not a solution. Setting SHELLOPTS directly is not possible: cygwin developers made it readonly. MSVC and regular cmd support today is much simplier than cygwin.

cygwin developer

If SHELLOPTS should not be inherited by design so igncr should not be a part of SHELLOPTS. igncr is a special workaround for windows that should live his own life outside of SHELLOPTS logic. It is not possible to explain this simple idea for cygwin developers, so we have to somehow put this crowbar directly.

C:\cygwin64\bin\bash.exe -cl "env SHELLOPTS=igncr bash"
echo $SHELLOPTS
> braceexpand:emacs:hashall:histexpand:history:igncr:interactive-comments:monitor
bash
echo $SHELLOPTS
> braceexpand:emacs:hashall:histexpand:history:igncr:interactive-comments:monitor

--norc is not really required, rc files is mostly noop, it is better to manage pipefail in script itself, so solution looks as follows:

run: C:\cygwin64\bin\bash.exe -cl "env SHELLOPTS=igncr '%cd%\scripts\some.sh'"

Thank you.

@andrew-aladev I don't think anything's broken; I just run the test workflow and it works fine with shell:: https://github.com/egor-tensin/setup-cygwin/actions/runs/790816641.

cygwin developers made it readonly

AFAIR, SHELLOPTS has always been read-only; it's readonly on all my Linux machines. Quote from the manual (as read on Linux):

This variable is read-only.

I think it's meant to be modified using set -o.

Now, in your example, igncr works fine for the outer instance of bash. The inner instance of bash doesn't inherit SHELLOPTS, and it never does this not on Cygwin, nor on Linux. To make it inherit SHELLOPTS, you need to either put export SHELLOPTS in your .bashrc, or put SHELLOPTS in your environment. For example, from a cmd prompt:

> set SHELLOPTS=igncr
> bash.exe --login -c "bash -c 'echo $SHELLOPTS'"
braceexpand:hashall:igncr:interactive-comments

Same from a Cygwin prompt:

# env SHELLOPTS=igncr bash -c 'bash -c "echo $SHELLOPTS"'
braceexpand:hashall:igncr:interactive-comments

Take a look at this question for reference: https://unix.stackexchange.com/q/387186

@andrew-aladev Please either don't use nested bash invocations (is there way around it? This issue was about a legitimate use-case concerning GitHub Actions.), or put something like SHELLOPTS: igncr in the env: block of your workflow jobs.

Hello @egor-tensin, your test script doesn't include subscripts, so it won't fail. You can include any subscript and it will fail.

SHELLOPTS has always been read-only; it's readonly on all my Linux machines

This is just design limitation made by bash developers, you shouldn't consider it serious.

Please either don't use nested bash invocations

Real world application uses high degree of inheritance, why not? This is just bash. But bash !== cygwin bash, bash developers will never add igncr into SHELLOPTS.

Please consider adding some sort of SHELLOPTS=igncr universal workaround in README.

You can include any subscript and it will fail.

Yes, if the "sub" script has \r\n as line terminators. In which case any Linux bash will choke on it too (I think it's stupid BTW). bash scripts run on Cygwin also tend to be run on real Linux machines quite often, so scripts writers should make sure \n is used as line terminator in their scripts (I do this using .gitattributes).

Please consider adding some sort of SHELLOPTS=igncr universal workaround in README.

I will, thanks.

Done