【问题标题】:Carriage-returns are not applied when running `tail -f` in the background while running `docker exec -it` in the foreground在后台运行 `tail -f` 而在前台运行 `docker exec -it` 时不应用回车
【发布时间】:2021-03-15 03:22:34
【问题描述】:

当我在后台运行tail -f 并在前台运行docker exec -it 时,tail-command 的输出已损坏。

例如,当我运行以下命令时:

$ tail -f log.txt &
$ docker exec -it my-container /bin/bash

我将以下 3 行附加到 log.txt:

cat
dog
bird

然后我得到以下奇怪的输出:

root@4083b121d1793:~# cat
                         dog
                            bird

注意换行符。 我猜没有应用回车。

为什么会出现这种奇怪的行为? 有什么解决办法吗?


更新

版本:

  • 适用于 Mac 3.2.1 的 Docker 桌面
  • Docker 引擎 20.10.5

【问题讨论】:

    标签: macos docker tail tty


    【解决方案1】:

    这似乎是因为在 docker CLI 中调用了MakeRaw()。文档解释说该函数将文件描述符(stdin)转换为“原始模式”,因此一旦终端会话结束,它就可以恢复到其原始状态。这些函数调用都是在 docker/cli 源代码中的 hijack.go 在 CLI 中设置交互式 exec 会话时发生的。

    This 是源代码中发生这种情况的地方。从中可以看出,如果设置NORAW环境变量,就可以得到正常的输出:

    // 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)
    

    这是我测试的方法,在运行 exec 命令时设置变量 NORAW

    1号航站楼:

    $ tail -f log.txt
    $ NORAW=1 docker exec -it containername /bin/bash
    root@docker:/work$
    

    2号航站楼:

    $ echo -e "something\nto\ntest" >> log.txt
    

    返回 1 号航站楼:

    root@docker:/work$ something
    to
    test
    

    我已经完全复制了你之前的内容,但我碰巧在 Windows 和 WSL2 上进行测试。

    但是,当设置NORAW 时,您将不会像往常一样恢复到原始终端会话。在^Dexit 之后,您将立即将最后一个终端提示粘贴到您的光标所在的位置:

    root@docker:/work$   $
    ^ docker prompt      ^ original terminal prompt session
    

    【讨论】:

    • 行编辑在 bash 中还能正常工作吗?
    • @AnttiHaapala 你的意思是我可以使用退格和 bash readline ^A^W 等吗?如果是这样,那么是的,我可以在使用NORAW=1 时像往常一样退格和编辑这些行。我相信MakeRaw() 只是将终端恢复到您调用docker exec 之前的原始状态@
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-27
    • 2015-08-16
    • 1970-01-01
    相关资源
    最近更新 更多