结合使用 envsubst 和 tee 随机生成一个空文件
Usage of envsubst combined with tee randomly results in an empty file
我想了解一个简单脚本中发生的事情,它似乎会产生随机结果。
我想做什么:
用环境中定义的值替换预先存在的文件中的变量。
这是在带有 bash 脚本的 Docker 容器内完成的,该脚本运行命令:
envsubst '$VAR1 $VAR2' < $FILE | tee $FILE
会发生什么:
- 有时有问题的
$FILE
在命令之前有内容,但在命令之后什么也没有。
如何重现问题:
- Docker文件:
FROM debian:stretch
RUN apt-get update -qy
RUN apt-get install -qy gettext
COPY main-script /main-script
RUN chmod +x /main-script
ENTRYPOINT [ "/main-script" ]
- Bash 脚本:
#!/bin/bash
mkdir -p /test
export TEST1=1
export TEST2=2
export TEST3=3
for I in {1..300} ; do
echo '$TEST1 $TEST2 $TEST3' > /test/file-$I
done
for FILE in /test/file-* ; do
envsubst < $FILE | tee $FILE
done
for FILE in /test/file-* ; do
if [[ -z "$(cat $FILE)" ]]; then
echo "$FILE is empty!"
FAIL=1
fi
done
if [[ -n "$FAIL" ]]; then
exit 2
fi
输出看起来像这样:
...
/test/file-11 is empty!
/test/file-180 is empty!
/test/file-183 is empty!
/test/file-295 is empty!
管道是异步的,您引入了竞争条件。您无法预测 envsubst
是在 tee
截断之前还是之后从 $FILE
读取。
正确的做法是将修改写入一个临时文件,然后在成功后用临时文件替换原来的。
tmp=$(mktemp)
envsubst < "$FILE" > "$tmp" && mv "$tmp" "$FILE"
我想了解一个简单脚本中发生的事情,它似乎会产生随机结果。
我想做什么:
用环境中定义的值替换预先存在的文件中的变量。
这是在带有 bash 脚本的 Docker 容器内完成的,该脚本运行命令:
envsubst '$VAR1 $VAR2' < $FILE | tee $FILE
会发生什么:
- 有时有问题的
$FILE
在命令之前有内容,但在命令之后什么也没有。
如何重现问题:
- Docker文件:
FROM debian:stretch
RUN apt-get update -qy
RUN apt-get install -qy gettext
COPY main-script /main-script
RUN chmod +x /main-script
ENTRYPOINT [ "/main-script" ]
- Bash 脚本:
#!/bin/bash
mkdir -p /test
export TEST1=1
export TEST2=2
export TEST3=3
for I in {1..300} ; do
echo '$TEST1 $TEST2 $TEST3' > /test/file-$I
done
for FILE in /test/file-* ; do
envsubst < $FILE | tee $FILE
done
for FILE in /test/file-* ; do
if [[ -z "$(cat $FILE)" ]]; then
echo "$FILE is empty!"
FAIL=1
fi
done
if [[ -n "$FAIL" ]]; then
exit 2
fi
输出看起来像这样:
...
/test/file-11 is empty!
/test/file-180 is empty!
/test/file-183 is empty!
/test/file-295 is empty!
管道是异步的,您引入了竞争条件。您无法预测 envsubst
是在 tee
截断之前还是之后从 $FILE
读取。
正确的做法是将修改写入一个临时文件,然后在成功后用临时文件替换原来的。
tmp=$(mktemp)
envsubst < "$FILE" > "$tmp" && mv "$tmp" "$FILE"