使用标准错误/标准输出重定向的eval命令存在问题

4
我正在尝试编写一个bash脚本,其中每个命令都通过一个函数进行传递,该函数使用以下行评估命令:
eval $1 2>&1 >>~/max.log | tee --append ~/max.log

一个不起作用的例子是尝试评估cd命令:

eval cd /usr/local/src 2>&1 >>~/max.log | tee --append ~/max.log

引起问题的部分是 | tee --append ~/max.log 部分。有任何想法为什么我会遇到问题?

什么不起作用?它不能进入目录吗? - edi9999
1
cd 命令与管道不兼容,例如 cd folder | ls 并不能将您切换到 "folder" 目录。 - edi9999
你能把主函数移动到一个函数中并使用 tee 来输出函数吗?就像这样 function mymain { ... }mymain 2>&1 | tee -append ~/max.log?或者使用类似 script 的东西? - Walter A
@edi9999 当附加 | tee --append ~/max.log 时,它不会更改目录。 - ProfessorManhattan
要将stdout和stderr都重定向并追加到文件中,请参见https://dev59.com/enNA5IYBdhLWcg3wpvtg。 - dave_thompson_085
1个回答

6

根据bash(1)手册:

管道中的每个命令都作为单独的进程执行(即在子shell中执行)。

因此,当在管道中使用时,cd 无法更改当前shell的工作目录。为了解决这个限制,通常的做法是将cd与其他命令分组,并重定向组命令的输出:

{
    cd /usr/local/src
    command1
    command2
} | tee --append ~/max.log

在不破坏现有设计的情况下,您可以在过滤函数中特殊处理cd

# eval all commands (will catch any cd output, but will not change directory):
eval $1 2>&1 >>~/max.log | tee --append ~/max.log
# if command starts with "cd ", execute it once more, but in the current shell:
[[ "$1" == cd\ * ]] && $1

根据您的情况,这可能不够:您可能需要处理其他命令来修改环境或shell变量,比如sethistoryulimitreadpushdpopd。在这种情况下,重新考虑程序的设计可能是一个好主意。


+1 支持这个事业。如果设置或声明了环境变量或shell变量,并且使用了这些设置,则需要特殊处理。包括read等命令和$*set以及shell选项。或更改ulimit设置。或history。还可能有其他我忽略的内容。正确重定向更容易。 - dave_thompson_085
@dave_thompson_085:谢谢,我已经将相应的语句更改为更通用的形式,包括所有修改环境或shell变量的内容。 - Michael Jaros

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接