0

I'll go straight to an example:

docker run --rm -i alpine /bin/sh -vs <<EOF
echo BEFORE
cat /etc/*elease
echo AFTER
EOF

Output:

echo BEFORE
cat /etc/*elease
echo AFTER
BEFORE
3.9.3
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.9.3
PRETTY_NAME="Alpine Linux v3.9"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://bugs.alpinelinux.org/"
AFTER

Note that commands itself (like echo BEFORE) printed by sh -v appear before any command output (like BEFORE).

I would expect to see

echo BEFORE
BEFORE
cat /etc/*elease
3.9.3
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.9.3
PRETTY_NAME="Alpine Linux v3.9"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://bugs.alpinelinux.org/"
echo AFTER
AFTER

I tried using stdbuf and script as for example described here, but to no avail.

I don't think I am the only one who has this problem. So I wonder

  • What is the cause of such mixed up output?
  • Is there a way to fix it?
Evgeny A.
  • 731
  • 2
  • 8
  • 19
  • 1
    [POSIX.1](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set) just says "the shell shall write its input to standard error as it is read", so this reads to me as though the shell is reading all of its input before it does anything. That seems like a reasonable implementation choice especially for small inputs. Is there a specific thing in your application that depends on this behavior, and can you include its source code in the question? – David Maze Nov 01 '19 at 15:55
  • @DavidMaze, It indeed seems that sh and bash do not guarantee that input line will be printed right before the command output. However, using -v or -x option (which suffers from the same problem) is often recommended: https://stackoverflow.com/questions/2853803/how-to-echo-shell-commands-as-they-are-executed – Evgeny A. Nov 01 '19 at 18:37
  • > Is there a specific thing in your application that depends on this behavior? No, not at all. I asked this question mainly out of curiosity. I was just dumping some information from a docker image (like /etc/*elease, python version, openssl version etc.) and came across this behavior. – Evgeny A. Nov 01 '19 at 18:38
  • @DavidMaze, With the help of your link I realized that it was stdout and stderr which mixed up. The problem can be solved by redirecting stdout to stderr with `exec 1>&2` (put it before the other commands) – Evgeny A. Nov 01 '19 at 19:18

1 Answers1

1

I was able to solve this problem by redirecting stdout to stderr:

docker run --rm -i alpine /bin/sh -vs <<EOF
exec 1>&2
echo BEFORE
cat /etc/*elease
echo AFTER
EOF
Evgeny A.
  • 731
  • 2
  • 8
  • 19