Does the CI Runner have something against pipes? (gitlab.com)

I am trying to run a script, but am confused about why my Jobs are failing.

To get right to the point, the following worked:

script:
  - wget -O - https://www.manager.io/releases/ 2>/dev/null > /tmp/manager_out
  - cat /tmp/manager_out | head -n 1 > /tmp/manager_out1
  - cat /tmp/manager_out1 | sed -e 's/^.*<table//g;s/\/table>.*$//g' > /tmp/manager_out2
  - cat /tmp/manager_out2 | grep -Eo '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' > /tmp/manager_out3
  - cat /tmp/manager_out3 | head -n 1 > /tmp/manager_version
  - echo $(cat /tmp/manager_version)

Combining the above into one big pipe and redirecting to a file did not work:

script:
  - wget -O - https://www.manager.io/releases/ 2>/dev/null | head -n 1 | sed -e 's/^.*<table//g;s/\/table>.*$//g' | grep -Eo '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' | head -n 1 > /tmp/manager_version
  - echo $(cat /tmp/manager_version)

This resulted in: ERROR: Job failed: exit code 141.


However, running the long pipe without the redirect did work.

script:
  - wget -O - https://www.manager.io/releases/ 2>/dev/null | head -n 1 | sed -e 's/^.*<table//g;s/\/table>.*$//g' | grep -Eo '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' | head -n 1
  - MANAGER_SERVER_VERSION=$(wget -O - https://www.manager.io/releases/ 2>/dev/null | head -n 1 | sed -e 's/^.*<table//g;s/\/table>.*$//g' | grep -Eo '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' | head -n 1)

But we can see below, that it failed when I tried to assign it to a variable:

$ wget -O - https://www.manager.io/releases/ 2>/dev/null | head -n 1 | sed -e 's/^.*<table//g;s/\/table>.*$//g' | grep -Eo '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' | head -n 1
19.7.65
ERROR: Job failed: exit code 141

I was hoping that I would get a 141 error with the first script on the place where it failed out. Unfortunately, I’m not lucky enough to get an error.

I also spun up a DO droplet and installed docker:latest on it to test out these commands in /bin/sh. Unfortunately, they all worked exactly as expected, so it’s something special that Gitlab’s Runner is doing that is causing this.

/ # MANAGER_SERVER_VERSION=$(wget -O - https://www.manager.io/releases/ 2>/dev/null | head -n 1 | sed -e 's/^.*<table//g;s/\/table>.*$//g' | grep -Eo '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' | head -n 1)                     
/ # echo $MANAGER_SERVER_VERSION                  
19.7.65

I’m pretty sure that I re-wrote it enough times to ensure that the most very basic way to do it worked, with no real explanation of why the abbreviated way returned 141 errors. Is there some quoting or bashisms in there that I’m missing? Or some external line length limitation?

FWIW this was literally 5 minutes ago, so whatever versions of stuff that gitlab.com is running is what I was using.

So after about a week, I’ve got the following output:

$ wget -O - https://www.manager.io/releases/ 2>/dev/null > /tmp/manager_out
$ cat /tmp/manager_out | head -n 1 > /tmp/manager_out1
ERROR: Job failed: exit code 141

Now this workaround is failing!

1 Like

Similar issue here. Some pipelines just randomly fail due to 141 exit codes for piped commands…

I was able to get it working.

I put all of the commands into an executable shell script, ran that script, and saved the output to an environment variable. I was able to do all of my piping, etc. in there. I would assume that the same could be written out to a file if needed.


FWIW I also tried redirects (<<<$(cat /tmp/file)) instead of using pipes, but that failed since this is a bashism and the CI Runner is using /bin/sh.

1 Like

gitlab-runner unconditionally runs set -eo pipefail currently.

See also: Custom docker image fails with `illegal option pipefail` in the gitlab script