在Linux中,将命令附加到文本文件会在某一点中断脚本



学习Linux系统并使用ununtu,并尝试使用|&三通-一个选项。该文件追加得很好,脚本一直运行到第6行,在那里它得到一个"0";ls:无法访问";hos*’:没有这样的文件或目录"&第8行;wc:hostname:没有这样的文件或目录"。

#!/bin/bash
#Intro Script
cd /etc |& tee -a txt.
head -n 2 /etc/login.defs |& tee -a txt.
tail -n 2 /etc/login.defs |& tee -a txt.
ls -lh hos* |& tee -a txt.
hostname |& tee -a txt.
wc -l hostname |& tee -a txt.

管道生成子外壳。cd /etc是作为管道的一部分在子shell中执行的,所以它对当前的执行环境没有影响。换句话说:

$ pwd
/some/dir
$ cd /anything | anything
$ pwd
/some/dir   # same as above

要影响当前的执行环境,必须在当前shell中执行内置命令,而不是在子shell中。cd不输出任何内容,所以您无论如何都可以删除管道。

请勿使用|&。首选2>&1 |。看见https://wiki.bash-hackers.org/scripting/obsolete

请参阅http://mywiki.wooledge.org/BashFAQ/024

正如KamilCuk所说,在管道中使用cd会在子shell中运行,因此不会影响脚本的其余部分。看起来您想要将脚本中的所有输出和错误重定向到txt.文件(它的末尾真的应该有.吗?(;如果是,只需在脚本的开头添加以下内容:

exec > >(tee -a txt.) 2>&1

这重定向输出&从shell进程到(后台(CCD_ 8进程的错误。请注意,>( )构造("进程替换"(仅在bash中可用,而在大多数其他shell中都不可用(甚至在以"sh"名称运行的bash中也不可用(。

如果您只想重定向脚本的一部分的输出,您可以将该部分包含在{ }中,并重定向该块的输出:

{
cd /etc
...
wc -l hostname
} > >(tee -a txt.) 2>&1

顺便说一句,在脚本中的任何cd命令中添加错误检查也是一个好主意,这样,如果失败,脚本的其余部分就不会盲目地在错误的地方运行。类似这样的东西:

cd /etc || {
echo "Error in cd command, exiting..." >&2
exit 1
}

但请注意,如果出于任何原因在子shell中执行此操作,则只会退出子shell。