mun*_*ish 5 linux process-substitution variable
如果我正在做类似的事情
创建临时文件
some process generating output > temp_file
cat temp_file
Run Code Online (Sandbox Code Playgroud)过程替换:
cat <(some process generating output)
Run Code Online (Sandbox Code Playgroud)其它的办法 :
cat <<<(some process generating output)
Run Code Online (Sandbox Code Playgroud)我对这些有一些疑问:
<() >()或变量扩展的
数据输出大小是否有限制<<<() 我的 ulimit 命令输出是:
bash-3.00$ ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
open files (-n) 256
pipe size (512 bytes, -p) 10
stack size (kbytes, -s) 8480
cpu time (seconds, -t) unlimited
max user processes (-u) 8053
virtual memory (kbytes, -v) unlimited
Run Code Online (Sandbox Code Playgroud)
<(cmd)是ksh现在也发现的一个特性zsh,bash称为进程替换。
在支持/dev/fd/nor 的系统上/proc/self/fd/n,它是用管道实现的,而不是用临时命名管道实现的。无论如何,它是一种管道形式,是一种进程间通信机制。
cmd1 <(cmd2)
Run Code Online (Sandbox Code Playgroud)
可以写(使用普通管道):
{ cmd2 4<&- | 3<&0 <&4 4<&- cmd1 /dev/fd/3; } 4<&0
Run Code Online (Sandbox Code Playgroud)
或者(使用命名管道):
mkfifo /tmp/named_pipe
cmd2 > /tmp/named_pipe & cmd1 /tmp/named_pipe
Run Code Online (Sandbox Code Playgroud)
也就是说,两个命令同时启动并与管道通信。您通常会使用cmd2 | cmd1它,但过程替换通常用于那些cmd1只能从文件名而不是从标准输入中获取输入的情况,或者需要多个输入的情况,例如 in diff <(cmd1) <(cmd2)。
除了进程数、cpu 时间或内存等一般限制外,没有影响它的限制。
所述PIPEBUF报道的一些实施ulimit像bash和一些实施方式中的ksh是不是一个而是RLIMIT针对其的配管的写入被保证是原子所以在这里无关紧要的最大大小。管道本身的大小(@dsmsk80 报告的 Linux 上为 64kB)本身并不是一个真正的限制。它只是说cmd2即使在cmd1停止读取管道后也可以写入管道。
但是有一个限制,它cmd1只能从该文件中读取。因为它是一个管道,它不能写入该文件或在文件中来回查找。
zsh 具有使用常规临时文件的第三种命令替换形式:
cmd1 =(cmd2)
Run Code Online (Sandbox Code Playgroud)
cmd1使用包含输出的临时文件调用cmd2。在这种情况下cmd1,在cmd2之后运行而不是同时运行。在那里可能会达到文件大小的限制。
我不知道任何实现<<<(...)运算符的外壳。然而,<<<在and 的最新版本中也发现了一个操作符 in zsh(灵感来自 Unix 端口中的同一操作符rc)。这是heredoc 运算符的变体,称为herestring。ksh93bash<<
在:
cmd <<< something
Run Code Online (Sandbox Code Playgroud)
与标准相同的是:
cmd << EOF
something
EOF
Run Code Online (Sandbox Code Playgroud)
shell 创建一个临时文件something\n作为内容并将其作为标准输入提供给新进程,取消该文件的链接并cmd在该新进程中执行。同样,这是一个常规文件,因此可能会达到文件最大大小的 rlimit。
现在您可以将<<<运算符与$(...)(命令替换)结合起来以某种方式模拟和 中zsh的=(...)运算符:bashksh93
cmd1 <<<"$(cmd2)"
Run Code Online (Sandbox Code Playgroud)
将cmd2与它一起运行stdout 重定向到管道。在管道的另一端,shell 读取输出cmd2并存储它减去尾随的换行符,并将一个换行符添加到临时文件中,并调用cmd1打开的临时文件以作为标准输入读取(注意还有另一个限制)如果cmd2输出包含 NUL 字符,它将不起作用)。
就像=(...),你必须这样写:
cmd1 /dev/fd/3 3<<<"$(cmd3)"
Run Code Online (Sandbox Code Playgroud)
请注意,shell 必须在将 cmd3 写入临时文件之前读取内存中的整个输出,因此除了最大文件大小外,您还可能达到内存使用限制。
另请注意,从版本 5 开始,bash在调用 之前删除临时文件的写权限cmd1,因此如果您需要cmd1能够修改该文件,则需要使用以下方法解决它:
{
chmod u+w /dev/fd/3 && # only needed in bash 5+
cmd1 /dev/fd/3
} 3<<<"$(cmd3)"
Run Code Online (Sandbox Code Playgroud)
小智 5
如果系统支持命名管道,则以<(cmd)和形式的 Bash 进程替换>(cmd)使用命名管道实现。该命令cmd在其输入/输出连接到管道的情况下运行。当您运行 eg 时,cat <(sleep 10; ls)您可以在目录下找到创建的管道/proc/pid_of_cat/fd。然后将此命名管道作为参数传递给当前命令 ( cat)。
管道的缓冲区容量可以通过使用dd命令的巧妙用法来估计,该命令将零数据发送到sleep命令的标准输入(它什么都不做)。显然,该进程将休眠一段时间,因此缓冲区将变满:
(dd if=/dev/zero bs=1 | sleep 999) &
Run Code Online (Sandbox Code Playgroud)
稍等片刻,然后向进程发送USR1信号dd:
pkill -USR1 dd
Run Code Online (Sandbox Code Playgroud)
这使得打印出 I/O 统计信息的过程:
65537+0 records in
65536+0 records out
65536 bytes (66 kB) copied, 8.62622 s, 7.6 kB/s
Run Code Online (Sandbox Code Playgroud)
在我的测试用例中,缓冲区大小是64kB( 65536B)。
你如何使用<<<(cmd)扩展?我知道这是 here 文档的一种变体,它被扩展并传递给其标准输入上的命令。
希望我对有关尺寸的问题有所了解。关于速度,我不太确定,但我认为这两种方法都可以提供相似的吞吐量。
| 归档时间: |
|
| 查看次数: |
2022 次 |
| 最近记录: |