bash - 为什么`cd`会破坏`exec`的重定向?
问题描述
我正在尝试将部分输出从脚本重定向到文件并这样做:
#!/usr/bin/bash
cleanup() {
echo "Lines in $tmpfile:"
cat $tmpfile
rm $tmpfile
}
tmpfile=$(mktemp .tmp.`basename $0`.XXXXXX)
trap cleanup EXIT
for var in one two; do
echo "$var: Before redirect"
exec 6>&1 # Save stdout to descriptor #6
exec >> "$tmpfile" # Send output to file
if [ 'a' == 'b' ]; then
echo "this never happens"
else
echo "$var: line in file"
fi
exec 1>&6 # Restore stdout
exec 6>&- # Close descriptor 6
echo "$var: After redirect"
done
这会产生预期的输出:
$ ./test-working.sh
one: Before redirect
one: After redirect
two: Before redirect
two: After redirect
Lines in .tmp.test-working.sh.c3noO3:
one: line in file
two: line in file
但是,如果我像这样做一个小调整:
$ diff -u test-working.sh test-broken.sh
--- test-working.sh 2021-06-16 12:48:35.852500568 +0200
+++ test-broken.sh 2021-06-16 12:48:35.205483749 +0200
@@ -7,6 +7,7 @@
tmpfile=$(mktemp .tmp.`basename $0`.XXXXXX)
trap cleanup EXIT
+cd
for var in one two; do
echo "$var: Before redirect"
exec 6>&1 # Save stdout to descriptor #6
@@ -20,3 +21,4 @@
exec 6>&- # Close descriptor 6
echo "$var: After redirect"
done
+cd -
然后它打破:
$ ./test-broken.sh
one: Before redirect
one: After redirect
two: Before redirect
two: After redirect
/script/run/path
Lines in .tmp.test-broken.sh.HSgMrS:
使用set -x
你可以清楚地看到在echo
某处写了一些东西:
$ bash -x test-broken.sh
+++ basename test-broken.sh
++ mktemp .tmp.test-broken.sh.XXXXXX
+ tmpfile=.tmp.test-broken.sh.c6mf6c
+ trap cleanup EXIT
+ cd
+ for var in one two
+ echo 'one: Before redirect'
one: Before redirect
+ exec
+ exec
+ '[' a == b ']'
+ echo 'one: line in file'
+ exec
+ exec
+ echo 'one: After redirect'
one: After redirect
+ for var in one two
+ echo 'two: Before redirect'
two: Before redirect
+ exec
+ exec
+ '[' a == b ']'
+ echo 'two: line in file'
+ exec
+ exec
+ echo 'two: After redirect'
two: After redirect
+ cd -
/script/run/path
+ cleanup
+ echo 'Lines in .tmp.test-broken.sh.c6mf6c:'
Lines in .tmp.test-broken.sh.c6mf6c:
+ cat .tmp.test-broken.sh.c6mf6c
+ rm .tmp.test-broken.sh.c6mf6c
但它并没有出现在预期的文件中。我正在努力看看我做错了什么。为什么要cd
打破重定向?
解决方案
正如评论中所指出的,我的代码读取和写入相同的文件名,但在不同的相对路径中。绝对路径修复它:
$ diff -u test-broken.sh test-broken-fixed.sh
--- test-broken.sh 2021-06-16 13:21:30.301815257 +0200
+++ test-broken-fixed.sh 2021-06-16 13:22:03.222670969 +0200
@@ -5,7 +5,7 @@
rm $tmpfile
}
-tmpfile="$(mktemp .tmp.`basename $0`.XXXXXX)"
+tmpfile="$PWD/$(mktemp .tmp.`basename $0`.XXXXXX)"
trap cleanup EXIT
cd
for var in one two; do
使用mktemp -p '' filename
也可以,然后文件将落在/tmp
.
推荐阅读
- powershell - 在 PowerShell 中使用 NLog ${callsite} 和 ${callsite-linenumber}
- flutter - 如何使用 Navigator.push 更改页面,使正文和页眉动画不同,而页脚保持不变
- python - 单个预测图像不需要重新缩放?
- java - ClassCastException:使用带有标题标题的 ContextMenu 时,无法在 Android 中将 HeaderViewListAdapter 强制转换为 MenuAdapter
- python - 如何确定 Airflow PostgresOperator 中身份验证失败的原因?
- node.js - RP - 发布表单数据未正确传递给服务
- json - 在 Microsoft SQL 中解析 JSON
- swiper - 我看不到按钮导航和分页分数
- java - 从 dockerfile 运行 mvn package 命令时出错。在 spring 项目中无法从我的依赖模块中找到依赖项
- c# - ASP.NET Core Entity Framework 代码到数据库的脚手架无法识别 Id 属性或 [Key] 注释