我正在寻找一种优雅的方式让 bash 写入我执行的命令,然后从交互式提示符将该命令的输出写入文件。运行这样的命令:
$ls -alh > list_dir
会向 list_dir 写入类似以下内容:
$ls -alh > list_dir
total 12K
drwxr-xr-x 2 root root 4.0K Dec 21 13:30 .
drwx------ 5 root root 4.0K Dec 21 13:30 ..
-rw-r--r-- 1 root root 842 Dec 21 13:09 file
-rw-r--r-- 1 root root 0 Dec 21 13:29 file1
-rw-r--r-- 1 root root 0 Dec 21 13:29 file2
我发现许多文章中的解决方案声称可以在脚本中工作,但没有任何文章可以在交互式 shell 中工作。例如,许多人建议将其添加到脚本的顶部:
set -x
如果我在 shell 中输入此命令,命令将被打印(尽管不太好)到标准输出,但我还没有设法弄清楚如何将它们包含在输出重定向中。
我还看到很多人建议使用脚本来做到这一点。这是我最接近找到我要找的东西的一次,但我并不总是希望记录所有内容。我想控制哪些命令被重定向到文件。
有谁知道这个问题有一个好的解决方案吗?我愿意接受更多开箱即用的想法,只要它们对于日常使用来说不太笨重。
答案1
set -x 选项将脚本置于调试模式。实际命令回显到 stderr。因此,您需要将 stdout 和 stderr 重定向到某个文件。尝试这个
your_script.sh &> outputfile.txt
答案2
输出xtrace
将发送至 stderr前该命令的评估包括在执行重定向之前。
所以在:
set -x # or set -o xtrace
echo test 2> file
转到+ echo test
stderr 要去的地方,然后 shellfile
在 fd 2 上打开,然后运行echo test
。如果你想要+ echo test
去file
,你需要:
{ echo test; } 2> file
这次,对命令组执行重定向,然后对echo test
命令进行求值(并+ echo test
写入 stderr,此时将转到file
)。
请注意,某些 shell(例如 AT&T)ksh
也会输出+ 2> file
.在某些版本的mksh
.
这也意味着该命令组中运行的任何命令的 stderr 都将转到file
.要解决这个问题,您需要:
set -x
{
cmd 2>&3 3>&-
} 3>&2 2> file
即保留原始 stderr 的副本(在 fd 3 上)并为命令组内的命令恢复它。
对于bash
,另一种方法是使用$BASH_XTRACEFD
特殊变量:
exec 7> file
BASH_XTRACEFD=7
set -x
echo test
如果你想要一个好的 xtrace
输出,试试zsh
。另请注意,它可以使用$PS4
特殊变量进行自定义。
答案3
我认为最简单的解决方案是向您的.bashrc
文件添加一个函数,如下所示:
my_run(){ echo $@ eval $@ }
source .bashrc
添加该功能后务必。然后,使用您的示例,从命令行输入:
my_run ls -ahl >list_dir
。
如果您还想在屏幕上查看输出,请使用以下命令:
my_run ls -ahl | tee list_dir
如果您不想使用函数,可以通过以下几种方法从命令行执行此操作:
echo "ls -ahl" >list_dir; eval $@ >>list_dir
如果您还想在屏幕上看到输出,则其中任何一种都可以。
echo "ls -ahl" >list_dir; eval $@ | tee -a list_dir
echo "ls -ahl" | tee list_dir | bash >>list_dir