Answers:
没有POSIX等效产品。您只能使用进行重定向exec
,而不能使用fork 进行重定向。管道需要叉子,并且外壳会等待孩子完成操作。
一种解决方案是将所有代码放入一个函数中。
all_my_code () {
…
}
{ all_my_code |
logger --priority user.notice --tag "$(basename "$0")"; } 2>&1 |
logger --priority user.error --tag "$(basename "$0")"
(这还将记录从logger的stdout实例到stderr实例的任何错误。您可以通过更多的文件描述符改组来避免这种情况。)
如果您希望父Shell即使logger
进程仍在运行也退出&
,请在logger
调用末尾放置。
{ all_my_code |
logger --priority user.notice --tag "$(basename "$0")" & } 2>&1 |
logger --priority user.error --tag "$(basename "$0")" &
或者,您可以使用命名管道。
pipe_dir=$(mktemp -d)
mkfifo "$pipe_dir/out" "$pipe_dir/err"
<"$pipe_dir/out" logger --priority user.notice --tag "$(basename "$0")" &
<"$pipe_dir/err" logger --priority user.error --tag "$(basename "$0")" &
exec >"$pipe_dir/out" 2>"$pipe_dir/err"
…
rm -r "$pipe_dir"
logger
并将相同的输入传递给每个实例。
_log()( x=0
while [ -e "${TMPDIR:=/tmp}/$$.$((x+=1))" ]
do continue; done &&
mkfifo -- "$TMPDIR/$$.$x" &&
printf %s\\n "$TMPDIR/$$.$x" || exit
exec >&- >/dev/null
{ rm -- "$TMPDIR/$$.$x"
logger --priority user."$1" --tag "${0##*/}"
} <"$TMPDIR/$$.$x" &
) <&- </dev/null
您应该能够像这样使用它:
exec >"$(_log notice)" 2>"$(_log error)"
这是一个使用mktemp
命令的版本:
_log()( p=
mkfifo "${p:=$(mktemp -u)}" &&
printf %s "$p" &&
exec <&- >&- <>/dev/null >&0 &&
{ rm "$p"
logger --priority user."$1" --tag "${0##*/}"
} <"$p" &
)
...的功能大致相同,不同之处在于它允许mktemp
您选择文件名。之所以能这样做是因为进程替换绝非神奇,且与命令替换的方式非常类似。代替用在其内运行的命令的值替换膨胀作为命令替换确实,进程替换与文件系统的链接,其中所述输出可以找到的名称替换它。
尽管POSIX shell并不能直接为此类事情提供推论,但模拟它非常简单。您要做的就是创建一个文件,用命令替换输出其名称为标准名称,并在相同的背景下运行命令,该命令将输出到该文件。现在,你可以重定向到该扩张的价值- 正是因为你进程替换做。因此,POSIX Shell当然提供了您需要的所有工具-所需要做的就是以适合您的方式使用它们。
以上两个版本均确保在使用它们之前销毁了它们创建/使用的管道的文件系统链接。这意味着事后不需要清理,更重要的是,它们的流仅可用于最初打开它们的进程-因此,它们的文件系统链接不能用作监听/劫持日志记录活动的手段。将其fs链接留在文件系统中是潜在的安全漏洞。
另一种方法是包装它。可以从脚本内部完成。
x=${x##*[!0-9]*}
_log(){
logger --priority user."$1" --tag "${0##*/}"
} 2>/dev/null >&2
cd ../"$PPID.$x" 2>/dev/null &&
trap 'rm -rf -- "${TMPDIR:-/tmp}/$PPID.$x"' 0 ||
{ until cd -- "${TMPDIR:=/tmp}/$$.$x"
do mkdir -- "$TMPDIR/$$.$((x+=1))"
done &&
x=$x "$0" "$@" | _log notice
exit
} 2>&1 | _log error
基本上,这将允许您的脚本自行调用(如果尚未调用),并为您提供一个临时启动的工作目录。
mktemp
和其他非标准命令,则可能是:_log()( p=; mkfifo "${p:=$(mktemp -u)}"; printf %s "$p"; exec <&- >&- <>/dev/null >&0; { rm "$p"; logger --priority user."$1" --tag "${0##*/}"; } <"$p" &)
。我以各种方式使用完全可移植的命令语言(除了您自己的语言)编写了它。而且,basename
它不是一个非常有用的实用程序。"${0##*/}"
既强大又快速。
.xprofile
有与执行sh
。
zsh
启用了w / multios。至于第一部分:{ this; can\'t; happen; before; } < this
。有帮助吗?