将输出从脚本内部重定向到 less

将输出从脚本内部重定向到 less

我可以使用以下命令将脚本的输出从脚本内部重定向到日志文件exec

#!/bin/bash
exec > stdout.log 2>&1
echo hello world

是否可以将输出重定向到less而不是文件?我试过

#!/bin/bash
exec > >(less) 2>&1

# output some text
for (( i=1; i <= 500; i++ )); do echo "hello world $i"; done

但这以一种奇怪的方式失败了......可见的提示较少,但您最终回到了终端。

我想将其设置为脚本的开头(因此它可以是有条件的,具体取决于参数、tty 等)。

答案1

您应该让脚本等待less子进程,否则您的脚本将在其之前终止,并且less会突然发现自己位于前台进程组之外,无法再从终端读取命令或恢复终端设置。

另外,为了防止less永远等待输入结束,您的脚本应该关闭它的管道。

把所有这些放在一起:

exec > >(less) 2>&1
trap 'exec >&- 2>&-; wait' EXIT
# >&- 2>&- => close stdout and stderr => cause EOF on less' stdin

seq 1 50000
# the rest of your script

但这不是很好,不能移植到大多数其他 shell,并且依赖于 bash 的未记录(且不可靠)行为:wait如果您的脚本中有多个exec > >(...),则它将无法正常工作,并且它还会等待其他背景进程以 开始&


更好的想法是让脚本调用自身,使用环境变量来避免无限递归:

if [ ! "$CALLED_MYSELF" ]; then
    set -o pipefail # supported in bash, but not in all the shells  
    CALLED_MYSELF=1 "$0" "$@" 2>&1 | less
    exit
fi

seq 1 50000
# the rest of your script

答案2

试试这个(不带线exec):

for (( i=1; i <= 500; i++ )); do echo "hello world $i"; done | less

(更新)

如果您想包含整个脚本,可以将脚本包装为{ ... }

#!/bin/bash
{
# output some text
for (( i=1; i <= 500; i++)) do echo "hello world $i"; done

# whatever output you want...

} | less

相关内容