我可以使用以下命令将脚本的输出从脚本内部重定向到日志文件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