加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

在bash中,通常使用流程替换或管道更好

发布时间:2020-12-15 17:00:18 所属栏目:安全 来源:网络整理
导读:在使用单个命令的输出仅被另一个消耗的用例中,使用|更好( pipelines)或()( process substitution)? 当然,更好是主观的.对于我的具体用例,我是以性能为主要驱动因素,但也对稳健性感兴趣. while read read do (cmd)我已经知道并已切换到的好处. 我有几个var =
在使用单个命令的输出仅被另一个消耗的用例中,使用|更好( pipelines)或<()( process substitution)?

当然,更好是主观的.对于我的具体用例,我是以性能为主要驱动因素,但也对稳健性感兴趣.

while read read do< <(cmd)我已经知道并已切换到的好处. 我有几个var = $(cmd1 | cmd2)个实例我怀疑可能更好地替换为var = $(cmd2<<(cmd1)). 我想知道后一种情况对前者带来哪些具体好处.

tl; dr:使用烟斗,除非你有令人信服的理由不这样做.

从进程替换中管道和重定向stdin基本上是相同的:两者都将导致由匿名管道连接的两个进程.

有三个实际差异:

1. Bash默认为管道中的每个阶段创建一个分支.

这就是为什么你首先开始研究这个问题:

#!/bin/bash
cat "$1" | while IFS= read -r last; do true; done
echo "Last line of $1 is $last"

默认情况下,此脚本不会使用管道,因为与ksh和zsh不同,bash将为每个阶段分叉子shell.

如果你在bash 4.2中设置shopt -s lastpipe,bash会模仿ksh和zsh行为并且工作得很好.

2. Bash不等待进程替换完成.

POSIX只需要一个shell来等待管道中的最后一个进程,但是包括bash在内的大多数shell都会等待所有这些进程.

当你有一个慢生产者时,这会产生一个显着的差异,就像在/ dev / random密码生成器中一样:

tr -cd 'a-zA-Z0-9' < /dev/random | head -c 10     # Slow?
head -c 10 < <(tr -cd 'a-zA-Z0-9' < /dev/random)  # Fast?

第一个例子不会有利地进行基准测试.一旦头部满足并退出,tr将等待其下一次write()调用以发现管道损坏.

由于bash等待head和tr完成,它看起来似乎更慢.

在procsub版本中,bash只等待head,并让tr在后台完成.

3. Bash目前没有针对流程替换中的单个简单命令优化离开.

如果调用sleep 1之类的外部命令,那么Unix进程模型需要bash forks并执行命令.

由于叉子价格昂贵,bash优化了它可以的情况.例如,命令:

bash -c 'sleep 1'

天真地会产生两个叉子:一个用于运行bash,一个用于运行睡眠.但是,bash可以对它进行优化,因为在完成睡眠后不需要使用bash来保持它,所以它可以用sleep替换它自己(execve没有fork).这与尾调用优化非常相似.

(睡眠1)被类似地优化,但是<(睡眠1)不是. source code没有提供特殊原因,所以它可能没有出现.

$strace -f bash -c '/bin/true | /bin/true'     2>&1 | grep -c clone
2
$strace -f bash -c '/bin/true < <(/bin/true)'  2>&1 | grep -c clone
3

鉴于上述情况,您可以创建一个支持您想要的任何位置的基准,但由于叉的数量通常更相关,因此管道将是最佳默认值.

显然,管道是POSIX标准,连接两个进程的stdin / stdout的规范方式,并且在所有平台上同样运行良好,这并没有什么坏处.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读