When I run tail -f
in the background and docker exec -it
in the foreground, the outputs of tail-command are corrupted.
For example, when I run the following commands:
$ tail -f log.txt &
$ docker exec -it my-container /bin/bash
and I append the following 3 lines to log.txt:
cat
dog
bird
then I get the following strange outputs:
root@4083b121d1793:~# cat
dog
bird
Notice the line breaks. I'm guessing carriage returns are not applied.
Why does this strange behavior occur? Is there any solution?
Update
Versoins:
This seems to happen because of the call to MakeRaw() in the docker CLI. The docs explain that the function turns the file descriptor (stdin) into "raw mode" so it can be restored to its original state once the terminal session ends. These function calls all happen when setting up the interactive exec session in the CLI in hijack.go in the docker/cli source code.
This is where that happens in the source code. You can see from this that if you set the NORAW
environment variable, you get the normal output:
// SetRawTerminal sets raw mode on the input terminal
func (i *In) SetRawTerminal() (err error) {
if os.Getenv("NORAW") != "" || !i.commonStream.isTerminal {
return nil
}
i.commonStream.state, err = term.SetRawTerminal(i.commonStream.fd)
Here is how I tested this, setting the variable NORAW
when running the exec command:
Terminal 1:
$ tail -f log.txt
$ NORAW=1 docker exec -it containername /bin/bash
root@docker:/work$
Terminal 2:
$ echo -e "something\nto\ntest" >> log.txt
Back in Terminal 1:
root@docker:/work$ something
to
test
I had reproduced exactly what you had before but I happened to be testing on Windows and in WSL2.
However, when NORAW
is set, you will not be restored as usual to your original terminal session. After ^D
or exit
, you will the last terminal prompt will immediately be pasted where your cursor is:
root@docker:/work$ $
^ docker prompt ^ original terminal prompt session