Shell 脚本和下标之间的标准输出竞争条件
我试图调用一个脚本deepScript并在另一个脚本shallowScript中处理其输出;它在示意图上类似于以下几段代码: shallowScript.shShell 脚本和下标之间的标准输出竞争条件,shell,stdout,zsh,race-condition,io-redirection,Shell,Stdout,Zsh,Race Condition,Io Redirection,我试图调用一个脚本deepScript并在另一个脚本shallowScript中处理其输出;它在示意图上类似于以下几段代码: shallowScript.sh #!/bin/zsh exec 1> >( tr "[a-z]" "[A-Z]" ) print "Hello - this is shallowScript" . ./deepScript.sh #!/bin/zsh print "Hello - this is deepScript" #!/bin/zsh print
#!/bin/zsh
exec 1> >( tr "[a-z]" "[A-Z]" )
print "Hello - this is shallowScript"
. ./deepScript.sh
#!/bin/zsh
print "Hello - this is deepScript"
#!/bin/zsh
print "Hello - this is shallowScript"
. ./deepScript.sh
#!/bin/zsh
function _process {
while read input; do
echo $input | tr "[a-z]" "[A-Z]"
done
}
. ./shallowScript.sh | _process
deepScript.sh
#!/bin/zsh
exec 1> >( tr "[a-z]" "[A-Z]" )
print "Hello - this is shallowScript"
. ./deepScript.sh
#!/bin/zsh
print "Hello - this is deepScript"
#!/bin/zsh
print "Hello - this is shallowScript"
. ./deepScript.sh
#!/bin/zsh
function _process {
while read input; do
echo $input | tr "[a-z]" "[A-Z]"
done
}
. ./shallowScript.sh | _process
现在,当我运行./shallowScript.sh时,结果是不稳定的:要么按预期工作(很少),要么打印一个空行,后跟两行预期的行(有时),要么打印这两行,然后挂起,直到我点击return并给它换行(大部分时间)。
到目前为止,我发现了以下几点:
- 这可能是一种竞争条件,因为两个“print”试图同时输出到stdout;在调用“./deepScript.sh”之前插入“sleep 1”可以一致地更正问题
- 问题来自进程替换“exec 1>>(tr…);对其进行注释也可以持续地纠正问题
zsh --version
zsh 5.0.5 (x86_64-apple-darwin14.0)
[编辑]
由于这一策略似乎注定会失败或导致可怕的变通语法,下面是另一个似乎适用于可承受语法的策略:我从shallowScript.sh中删除了所有重定向,并创建了第三个脚本,其中输出处理在函数中进行:
shallowScript.sh
#!/bin/zsh
exec 1> >( tr "[a-z]" "[A-Z]" )
print "Hello - this is shallowScript"
. ./deepScript.sh
#!/bin/zsh
print "Hello - this is deepScript"
#!/bin/zsh
print "Hello - this is shallowScript"
. ./deepScript.sh
#!/bin/zsh
function _process {
while read input; do
echo $input | tr "[a-z]" "[A-Z]"
done
}
. ./shallowScript.sh | _process
thirdScript.sh
#!/bin/zsh
exec 1> >( tr "[a-z]" "[A-Z]" )
print "Hello - this is shallowScript"
. ./deepScript.sh
#!/bin/zsh
print "Hello - this is deepScript"
#!/bin/zsh
print "Hello - this is shallowScript"
. ./deepScript.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
$
在这里,外壳将等待cat
过程完成,然后再打印下一个提示,cat
仅当其所有输入(例如tr
的输出)都得到处理时才会完成,正如您所期望的那样
更新:在以下zsh文档中找到相关报价:
>(过程)
还有一个问题;当此命令附加到外部命令时,父shell不会等待进程完成,因此紧跟其后的命令不能依赖于完成的结果。问题和解决方案与重定向中的MULTIOS
一节中描述的相同。因此,在上述示例的简化版本中:
paste <(cut -f1 file1) <(cut -f3 file2) > >(process)
在您的情况下,它将给出如下内容:
{
print "Hello - this is shallowScript"
. ./deepScript.sh
} 1> >( tr "[a-z]" "[A-Z]" )
这当然有效,但看起来比原来的更糟。谢谢,解释很有道理。只是一个问题,我应该考虑“猫”的伎俩,像解决方案还是像一个转身?它似乎不容易推广,每次我从交互式shell调用脚本时都要记住它,感觉有点尴尬。这绝对是一种解决方法,不能用于日常脚本编程。一般规则应该是,不要编写让孩子在父母去世后继续写作的脚本。在您的特定情况下,为什么不使用普通的
重定向(例如/shallowScript.sh | tr“[a-z]”“[a-z]”“
)将输出传递到tr呢?因为在我的实际脚本中,我的下标的处理比简单的re要长得多,这也是因为进程替换使得语法非常优雅。使用相关zsh文档的链接更新了答案。…>>(…)
只是一个简单的管道,相当于…|代码>。仅当需要对文件进行写访问时,才需要进行进程替换。与tee
一起使用是常见的:…|tee>(…)>(…)
,其中tee
需要文件名作为参数。不需要\u进程中的while循环<代码>_进程(){tr“[a-z]”“[a-z]”;}
tr
将已经处理其标准输入的每一行,因此无需为函数的标准输入的每一行调用它一次。True;我使用tr
制作了一个易于理解和测试的代码片段,但我的真实脚本尝试做的不仅仅是tr