与“exec”等效并撤消

与“exec”等效并撤消

我已经阅读了 man on exec,但仍然不明白我正在研究的脚本中以下两行的后果:

exec >> >(tee -a $logfile)
exec 2>&1

我读了这个答案,但仍存疑虑。

我的理解是,第一行>>还使输出(追加)到脚本文件中进一步$logfile右侧的任何内容。>>

第二行将使脚本中的 2 (stderr) 输出重定向到 1 (stdout)。

  1. 我的理解正确吗?
  2. 如何撤消上述命令,以便撤消后的行为与执行这两行之前的行为相同?
  3. 让我们在脚本中进一步说,我们在后台启动一些应用程序,例如someapp &。我想在终端中运行此命令 - 与脚本分开且独立 - 其效果与在脚本中运行相同。我应该如何修改someapp &以使用上面的 s 设置重定向exec

答案1

exec >> >(tee -a $logfile)

短缺:

exec 1>> >(tee -a $logfile)

相当于:

exec 1>> /dev/fd/x

其中x是指向管道写入端的文件描述符。

在此之前,bash已启动一个子进程,其 fd 0 (stdin) 连接到管道的另一端,同时正忙于执行tee

exec 1>> file,使用 O_APPEND 且不使用 O_TRUNC 打开文件,并将结果 fd 移至 1。

打开/dev/fd/x,取决于系统,就像执行dup(x)(大多数)或打开与 fd x 上打开相同的文件(仅限 Linux 和 cygwin)。在这里,当 fd x 在管道上打开时,没有什么区别,并且 O_APPEND 和 O_TRUNCATE 标志是不相关的,因此它与exec > >(...).

这有点离题,但tee -a $logfile不正确,tee -a -- "$logfile"如果意图是打开路径存储在$logfileO_APPEND 中的文件,则应该是这样。

因此,在该命令之后,shell 中的 fd 1 将指向一个管道。在管道的另一端,tee读取即将到来的内容,并将tee其发送到$logfile重定向之前 stdout 所指向的内容(如果脚本的输出以某种方式重定向,则可能是终端设备或其他设备) 。

exec 2>&1

使 fd 2 指向与 fd 1 相同的东西,因此是同一个管道。

为了能够做到这一点,你必须保存打开文件描述在进行重定向之前,fds 1 和 2 在单独的 fds 上打开:

exec 3>&1 4>&2 > >(tee -a -- "$logfile") 2>&1

3>&1so fd 3 现在在哪里dup2(1, 3)指向与 fd 1 相同的打开文件描述。

并撤消,

exec >&3 2>&4 3>&- 4>&-

someapp或者以其 stdout 和 stderr 作为原始 stdout 和 stderr运行:

someapp >&3 2>&4 3>&- 4>&- &

相关内容