Dash等效于脚本输出的自我重定向


9

在Bash中,您可以重定向当前正在运行的脚本的所有将来的 stdout输出。例如,使用此脚本,

exec > >(logger -t my-awesome-script)
echo 1
echo 2
echo 3

这将以syslog结尾:

Oct 26 01:03:16 mybox my-awesome-script[72754]: 1
Oct 26 01:03:16 mybox my-awesome-script[72754]: 2
Oct 26 01:03:16 mybox my-awesome-script[72754]: 3

但这是特定于Bash的,具有重定向的裸露的exec在Dash中似乎不起作用。

Syntax error: redirection unexpected

如何在Dash中或在两个Shell中使其工作?


您能确切说明您需要什么吗?您可以使用>破折号来重定向。我意识到您似乎在要求其他事项,但我无法完全说出它是什么。
terdon

@terdon我已经扩展了解释。
Alex B

Answers:


6

您可以这样做:

{ commands
....
} | logger -t my_awesome_script

您可以使用任何外壳来做到这一点。

如果您不喜欢它的外观,则可以使脚本将自身包装在一个函数中。

#!/bin/sh
run() if     [ "$run" != "$$" ] || return
      then   sh -c 'run=$$ exec "$0" "$@"' "$0" "$@" |
             logger -t my-awesome-script
      fi
#script-body
run "$@" || do stuff

最后一行应该是run ${1+"$@"} || do stuff这样,以便保留参数。
亚当·卡兹

@AdamKatz-好点,execpt ${1+"$@"}不会执行任何操作"$@" 。无论如何,它还有其他问题。
mikeserv '16

"$@"将通过""时没有参数,而${1+"$@"}在没有参数将传递一个空字符串。这对于许多程序来说非常重要,因为它们解析""为一个空参数,而一个(未加引号的)空字符串根本不会被解释为一个参数。
亚当·卡兹

@AdamKatz-一个非常旧的Bourne外壳可能(而且我不希望dash在这样的系统上找到),但否则"$@"是唯一的,因为零参数的情况不能替代POSIX外壳的空参数。
mikeserv '16

1
@AdamKatz-即使在旧的bsh中,它实际上也是一个bug,应该永远不会那样工作。它最终得到修复,但是我不知道例如在Solaris 10中是否仍然需要它。您对$ *的看法是正确的-它没有展现出相同的expabsion整洁特性-它的唯一性onky与其扩展的可变内容有关,尽管它始终是某物。在我看来, "${@+is especially cool $@}" 。但${1+”$@"}毕竟与旧的解决方法几乎没有太大不同。如果您有ksh93:"${1+quoted" not quoted "quoted again}"
mikeserv '16

5

使用命名管道可以轻松模拟流程替换。

mkfifo logger_input
logger -t my_awesome_script < logger_input &
exec > logger_input
echo 1
echo 2
echo 3

实际上,命名管道是/dev/fd可以在中实现进程替换的一种机制(另一种是)bash


我认为最通用的功能:我可以使用tee无缝重定向到多个流。只是一件事:不要忘记在脚本末尾删除创建的logger_input。
lauhub,2015年

2

我认为这不可能dash。据我从man页面上可以看出,它不支持流程替换。

解决方法是,您可以尝试使用mikserv的建议,或者将所有内容重定向到文件,然后在脚本完成后(大概是在脚本中)将文件的内容添加到logger中:

$ exec > ~/foo/foo.txt
$ ls
$ echo something
$ cat foo/foo.txt | sudo logger -t my-awesome-script

实际上,在其他shell中,进程替换(或其他shell称为进程替换)更容易dash。进程替换仅相当于一个/dev/fd/[num]指向匿名管道链接的参数。dash在这里使用匿名管道进行文档处理,而不是像大多数其他Shell一样生成临时文件。因此cat /dev/fd/3 3<<HEREDOC\n$(get output)\nHEREDOC\n,不仅功能上等效,而且您甚至可以自己命名fd。尽管如此,您对其他方法的论点还是很清楚的-您需要使用打开一个新的fd exec并后台读取它的进程。
mikeserv 2014年

2
@mikeserv:在什么意义上,cat /dev/fd/3 3<<HEREDOC\n$(get output)\nHEREDOC\n“比”更容易cat <(get output)
鲁阿赫2014年

@mikeserv:需要记住很多规则;也许您只是对他们已经习惯了,以至于没有注意到。
ruakh 2014年

@ruakh-好吧,当然。< >外壳重定向。基本上,如果您只执行其中的两个,则也可以在以下几行中进行堆放。但是,是的,您有意思-我喜欢这里的文档。尽管如此,我认为,尽可能多的事情需要记住,当它们普遍工作时会更容易。再者,很多人对其他外壳没有太多用处,因此对它们没有影响。我只是不在他们中间。
mikeserv

1
@mikeserv:不仅是heredocs,而且/dev/fd/3(以这种精确形式),以及关于空白发生的细节。。。因此,当Dash不能在具有所有组件的其他Shell中运行时,整个方法完全可以在Dash中使用,这意味着要记住整个方法是一个特殊的规则。(这让我想起了用较少的词汇量来创建简体英语的尝试;它们切掉了诸如persist之类的单词,但忽略了诸如keep on一样困难的习语。)
ruakh 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.