admin管理员组文章数量:1277322
I have a shell script starting a docker container. Before starting the container, it starts a background loop printing some lines to the terminal. I noticed that these printed lines do not return the cursor to the beginning of the line. What I found out: this happens only during the lifetime of the container. See minimal example:
#!/usr/bin/env bash
cleanup() {
kill "${BACKGROUND_PROCESS}"
}
trap cleanup EXIT
backgroundLoop() {
while true; do
echo .
sleep 1
done
}
backgroundLoop &
BACKGROUND_PROCESS=$!
sleep 2
echo Starting docker
docker run --rm -it alpine sleep 5
echo Docker has finished
sleep 2
cleanup
The output is:
.
.
Starting docker
.
.
.
.
.
.
Docker has finished
.
.
Can anyone explain why this happens? It seems to be related to this question, I assume that docker reconfigures the current TTY and restores it afterwards. Is that correct?
Removing -t
from the docker call actually fixes the problem, which seems to back my theory. However, I need the interactive TTY for my actual use case.
How can I change my code so that all output lines are printed with correct carriage returns?
UPDATE:
I got an answer to this question which solves the problem for my minimal example I posted above by calling stty -onocr
in the docker container before the actual command.
My real-world scenario, however, uses a custom docker image with a bash script as entry point, so I cannot pass commands as arguments. Minimal example of the entrypoint script entrypoint.sh
:
#!/usr/bin/env sh
sleep 5
Then replace the docker call in the test script
docker run --rm -it alpine sleep 5
with
docker run --rm -it -v ./entrypoint.sh:/entrypoint.sh --entrypoint /entrypoint.sh alpine
The output is the same, but the proposed fix does not work in this case. Any ideas how to apply the fix to this slightly different environment?
I have a shell script starting a docker container. Before starting the container, it starts a background loop printing some lines to the terminal. I noticed that these printed lines do not return the cursor to the beginning of the line. What I found out: this happens only during the lifetime of the container. See minimal example:
#!/usr/bin/env bash
cleanup() {
kill "${BACKGROUND_PROCESS}"
}
trap cleanup EXIT
backgroundLoop() {
while true; do
echo .
sleep 1
done
}
backgroundLoop &
BACKGROUND_PROCESS=$!
sleep 2
echo Starting docker
docker run --rm -it alpine sleep 5
echo Docker has finished
sleep 2
cleanup
The output is:
.
.
Starting docker
.
.
.
.
.
.
Docker has finished
.
.
Can anyone explain why this happens? It seems to be related to this question, I assume that docker reconfigures the current TTY and restores it afterwards. Is that correct?
Removing -t
from the docker call actually fixes the problem, which seems to back my theory. However, I need the interactive TTY for my actual use case.
How can I change my code so that all output lines are printed with correct carriage returns?
UPDATE:
I got an answer to this question which solves the problem for my minimal example I posted above by calling stty -onocr
in the docker container before the actual command.
My real-world scenario, however, uses a custom docker image with a bash script as entry point, so I cannot pass commands as arguments. Minimal example of the entrypoint script entrypoint.sh
:
#!/usr/bin/env sh
sleep 5
Then replace the docker call in the test script
docker run --rm -it alpine sleep 5
with
docker run --rm -it -v ./entrypoint.sh:/entrypoint.sh --entrypoint /entrypoint.sh alpine
The output is the same, but the proposed fix does not work in this case. Any ideas how to apply the fix to this slightly different environment?
Share Improve this question edited Feb 26 at 11:21 carlfriedrich asked Feb 25 at 11:37 carlfriedrichcarlfriedrich 4,0931 gold badge24 silver badges38 bronze badges 2 |2 Answers
Reset to default 1Tell the container not to add CR characters to the output by running stty -onocr
in your container by changing the docker run
command to
docker run --rm -it alpine stty -onocr && sleep 5
Why does my terminal not perform carriage returns while docker is running?
Because docker executable switches the terminal in raw mode when spawning the terminal, as part of the -t
option you passed to docker run.
See man stty
, https://en.wikipedia./wiki/Terminal_mode .
How can I change my code so that all output lines are printed with correct carriage returns?
Option #1:
You can remove -t
flag from docker run.
Option #2:
You can just set NORAW=1
environment variable.
$ ( set -x; ( sleep 0.2; echo .; echo .; echo .; echo .; ) & NORAW=1 docker run -ti --rm alpine sleep 5 ; wait )
+ NORAW=1
+ docker run -ti --rm alpine sleep 5
+ sleep 0.2
+ echo .
.
+ echo .
.
+ echo .
.
+ echo .
.
+ wait
See https://github/docker/cli/blob/068a01ea9470df6494cc92d9e64e240805ae47a7/cli/streams/in.go#L32 .
Option #3:
You can revert from raw mode, for example with stty -raw
. Something along:
$ ( set -x; ( sleep 0.2; stty -raw </dev/tty; echo .; echo .; echo .; echo .; ) & docker run -ti --rm alpine sleep 5 ; wait )
+ docker run -ti --rm alpine sleep 5
+ sleep 0.2
+ stty -raw
+ echo .
.
+ echo .
.
+ echo .
.
+ echo .
.
+ wait
The first + echo .
gets printed just before stty -raw
is able to take place. After -raw
, terminal is cooked.
so I cannot pass commands as arguments
If you control command line, you can pass anything as arguments. For example:
docker run --rm -it -v ./entrypoint.sh:/entrypoint.sh \
--entrypoint /usr/bin/env alpine sh -c 'stty -raw; . entrypoint.sh'
本文标签: bashWhy does my terminal not perform carriage returns while docker is runningStack Overflow
版权声明:本文标题:bash - Why does my terminal not perform carriage returns while docker is running? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741205701a2358106.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
-it
and done? – KamilCuk Commented Feb 26 at 12:11ctrl+c
forwarded to the container, and that's not possible without-it
as far as I know. – carlfriedrich Commented Feb 26 at 12:17