[英]Output of pv on docker-compose startup not working as expected
我正在尝试 output 在 mariadb Z05B6053C41A21430AFD6FC3B7Z 容器中导入.sql
文件的进度。
我有以下文件/目录设置:
│- docker-compose.yml
│- Dockerfile
│- import.sh
└── sql
- test.sql (rather big: ~ 1GB)
我的docker-compose.yml
就像...
services:
db:
build: ./
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- ./:/docker-entrypoint-initdb.d
...使用以下 Dockerfile 安装pv
(管道查看器)。 pv
应该给我一个进度条,目前导入的距离...
FROM mariadb
RUN apt-get update && apt-get install -y pv
import.sh
将通过/docker-entrypoint-initdb.d
中的映射卷执行,如此处所述。
#!/bin/bash
# create db
mysql -uroot -proot <<-EOF
CREATE DATABASE test;
EOF
# import sql file and output progress with pv
echo "importing test.sql..."
pv --force "/docker-entrypoint-initdb.d/sql/test.sql" | mysql -uroot -proot "test"
现在,如果我docker-compose up
它只会在导入结束时输出100%
pv output :
importing test.sql...
953MiB 0:01:24 [11.2MiB/s] [================================>] 100% 0:05:42
如果我在容器内执行相同的命令,它会起作用,它会给我一个移动的进度条:
pv --force "/docker-entrypoint-initdb.d/sql/test.sql" | mysql -uroot -proot "test"
60.4MiB 0:00:14 [5.79MiB/s] [=> ] 6% 0:04:53
如何在docker-compose up
获得此进度条,而不是长时间等待和100%
output?
首先让我们了解pv
如何能够将纯文本 output 上的移动进度条渲染到终端: pv
实际上只是在每次进度更新时将纯文本打印到其标准输出:
"[==> ] 25%\r"
"[======> ] 50%\r"
"[=========> ] 76%\r"
"[============>] 100%\n"
这里的每一行代表一个单独的进度更新, pv
输出引号内的文本(所以没有引号)。
但这不会多行打印到终端: \r
是一个回车符,它将把 cursor 移回行首而不开始新行。 所以下一个进度 output 将覆盖前面的文本,导致进度条 animation。
只有在最后一次更新pv
之后才会打印换行符\n
,从而导致 output 之后的最后一个换行符。
Now to the problem with docker-compose
: starting an app with docker-compose up
will start all services, attach to their output and log it to its own output - prefixed with the respective service name:
app_1 | starting App...
db_1 | initializing database
....
为此, docker-compose
将从每个容器中读取每个 output 行,并在打印之前为其添加服务名称前缀。
但正如我们之前看到的pv
实际上只打印一行! 这就是为什么docker-compose
会缓冲 output 直到最后才打印出来的原因!
我在这里看到两种可能的解决方案:
docker-compose run db
来初始化数据库:这将运行容器,其 output 直接连接到控制台并打印 output 而无需任何缓冲或后处理。 在这种情况下,您甚至可以省略--force
标志。
\r
替换为\n
以强制将每个进度更新打印在新行上,例如使用tr
。 此外,要确保禁用任何 output 缓冲,您可以使用stdbuf
(请参阅pipe 中的关闭缓冲):(pv --force -p "/docker-entrypoint-initdb.d/sql/test.sql" | mysql -uroot -proot "test") 2>&1 | stdbuf -o0 tr '\r' '\n'
将记录
db_1 | [==> ] 25%
db_1 | [======> ] 50%
db_1 | [=========> ] 76%
db_1 | [============>] 100%
这是上面的一个小演示:
# Dockerfile
FROM alpine
RUN apk add pv
# docker-compose.yml
services:
app:
build: .
command: sh -c "pv --force -p -Ss 1024 -L 100 /dev/urandom 2>&1 > /dev/null | tr '\r' '\n'"
根据评论,上述演示不适用于基于 ubuntu 的图像。 在这样的图像中tr
似乎会缓冲它的 output 并且只有在它退出后才打印所有内容。
但是,可以使用stdbuf
禁用 output 缓冲区(另请参阅 pipe 中的关闭缓冲):
# Dockerfile
FROM ubuntu
RUN apt-get update && apt-get install -y pv
# docker-compose.yml
services:
app:
build: .
command: sh -c "pv --force -p -Ss 1024 -L 100 /dev/urandom 2>&1 > /dev/null | stdbuf -o0 tr '\r' '\n'"
我找到了一个不错的解决方案:
将--numeric
标志添加到我的pv
命令中。
-n,--数字
数字 output。 pv 不会给出进度的视觉指示,而是给出 integer 百分比,每行一个,标准错误,适合管道(通过卷积重定向)进入对话框(1)。 请注意,如果使用 -n,则不需要 -f。
所以我的import.sh
中的命令是:
pv --numeric "/docker-entrypoint-initdb.d/sql/test.sql" | mysql -uroot -proot "test"
这给了我以下 output:
importing test.sql...
36
53
80
100
由于这不如pv
的典型 output 好,所以这个答案并不完美......
我还尝试了更好的 output 没有换行符,例如:
importing test.sql...
36% 53% 80% 100%
附加awk
命令:
(pv --numeric "/docker-entrypoint-initdb.d/sql/test.sql" | mysql -uroot -proot "test") 2>&1 | awk '{printf "%s% ",$0}'
但是同样的问题:这仅在容器内部有效,而在docker-compose up
的 output 上无效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.