我试图调用脚本deepScript和处理其另一个脚本shallowScript内输出; 它看起来像示意图下面的代码片段:
shallowScript.sh
#!/bin/zsh
exec 1> >( tr "[a-z]" "[A-Z]" )
print "Hello - this is shallowScript"
. ./deepScript.sh
deepScript.sh
#!/bin/zsh
print "Hello - this is deepScript"
现在,当我运行./shallowScript.sh,结果是不稳定的:或者按预期工作(很少),或打印一个空行,随后由两个预期线(有时),或打印两行,然后挂起,直到我打回来,给它一个换行符(大部分时间)。 到目前为止,我发现了以下工作:
- 它可能是一个竞争条件,因为这两个“打印”试试输出到标准输出的同时, 该呼叫之前插入“休眠1”“ ./deepScript.sh”解决该问题始终
- 的问题来自于进程替换 “EXEC 1>>(TR ...)”; 注释掉它也可以解决该问题始终
我上过这么多的论坛和有关进程替换和重定向的职位,但无法找到如何保证我的脚本调用命令同步。 想法?
zsh --version
zsh 5.0.5 (x86_64-apple-darwin14.0)
[编辑]
因为它似乎是这一战略必将失败或导致可怕的解决方法的语法,这里是另一个,这似乎与可承受的语法的工作策略:我删除了从shallowScript.sh所有重定向并创建第三个脚本,输出处理发生在功能:
shallowScript.sh
#!/bin/zsh
print "Hello - this is shallowScript"
. ./deepScript.sh
thirdScript.sh
#!/bin/zsh
function _process {
while read input; do
echo $input | tr "[a-z]" "[A-Z]"
done
}
. ./shallowScript.sh | _process
我想,问题是,你没有看到在执行脚本之后的提示:
$ ./shallowScript.sh
$ HELLO - THIS IS SHALLOWSCRIPT
HELLO - THIS IS DEEPSCRIPT
(nothing here)
并认为它挂在这里,等待换行符。 其实这不和的行为非常期待。
取而代之的是换行,你可以输入任何shell命令如ls
,它会被执行。
$ ./shallowScript.sh
$ HELLO - THIS IS SHALLOWSCRIPT <--- note the prompt in this line
HELLO - THIS IS DEEPSCRIPT
echo test <--- my input
test <--- its result
$
这里发生的是:第一外壳(这是运行在一个shallowScript.sh
创建一个管道),执行dup2
调用转发其stdout
(FD 1)创建的管道写端,然后派生一个新的进程( tr
),这样家居父打印到stdout
发送到stdin
的tr
。
接下来发生的事情是,主壳(一个你在那里输入初始命令./shallowScript.sh
)不会有一个想法,它应该延迟打印下一个命令提示符,直至结束tr
过程。 它一无所知tr
,所以它只是等待shallowScript.sh
来执行,然后打印提示。 该tr
仍然是在那个时候运行,这就是为什么它来的提示后输出(两行)被打印出来,和你想的外壳正在等待换行。 它实际上不是,它已经准备好下一个命令。 你可以看到印有提示( $
字符或其他)以前在什么地方,内部或后脚本的输出,这取决于如何快速tr
过程结束。
你每次看到这样的行为的过程叉和孩子继续写它的stdout
时,父母已经死了。
长话短说,试试这个:
$ ./shallowScript.sh | cat
HELLO - THIS IS SHALLOWSCRIPT
HELLO - THIS IS DEEPSCRIPT
$
这里shell将等待cat
过程中打印下一个提示前完成,而cat
会结束,只有当所有的输入(例如,从输出tr
)进行处理,就像你期望的那样。
更新:发现的zsh文档相关报价这里: http://zsh.sourceforge.net/Doc/Release/Expansion.html#Process-Substitution
存在具有另外的问题>(process)
; 当该附连于外部命令,父壳不等待过程完成并且因此紧随其后的命令不能依靠结果是完整的。 问题和解决方案是如在部分中描述的相同MULTIOS
在重定向。 因此,在上面的例子的简化版本:
paste <(cut -f1 file1) <(cut -f3 file2) > >(process)
(注意没有MULTIOS
参与),进程将被异步至于母贝而言运行。 解决方法是:
{ paste <(cut -f1 file1) <(cut -f3 file2) } > >(process)
在你的情况下,它会给这样的事情:
{
print "Hello - this is shallowScript"
. ./deepScript.sh
} 1> >( tr "[a-z]" "[A-Z]" )
这当然作品,但看起来比原来更糟。