是否有一种方法可以中止管道化的shell命令?

问题描述 投票:2回答:4

使用此命令:

$ tar -ztf /tmp/z.txz | grep -m 1 '/packagesite.txz$'
2.2.0/FreeBSD:11:amd64/latest/packagesite.txz

结果非常快(不到1秒),但是继续运行10到15秒钟再无用。 I found out about -m here,但没有帮助。如果能在找到匹配项后立即中止它,那将是非常好的。有什么办法吗?仅供参考,必须在-m中使用。

grep sh tar
4个回答
0
投票

您的问题与缓冲有关。这是一种更简单的复制方式。

/bin/sh

即使您可以通过删除perl -le 'for (1..1000) { print "$_"; sleep 1 }' | grep -m 1 4 验证输出的第四行是否匹配,似乎也没有发生。

通过Perl关闭缓冲解决了当前的问题:

grep

(并且输出会在4秒后到达,可预期)。

没有完全可移植的解决方案;看看是否具有perl -le '$| = 1; for (1..1000) { print "$_"; sleep 1 }' | grep -m 1 4 4 中描述的实用程序之一,或者确保https://mywiki.wooledge.org/BashFAQ/009产生足够的输出,可以依靠输出缓冲区填满。


0
投票

您的文件很大或存储设备很慢。 Grep将过滤结果并停止读取管道,但不会终止管道命令。

如果知道结果在1秒钟后显示,那么对于解决方法,您可以在该时间之后使用tar杀死shell命令。例如:

timeout

0
投票

到目前为止,发布的任何内容都没有效果,但是我注意到timeout 1 tar -ztf /tmp/z.txz | grep -m1 '/packagesite.txz$' 中有一些有趣的地方:

this post

以及find . ... -exec sh -c 'printf "%s\n" "$1"; kill "$PPID"' sh {} \;中有关管道和过程组的更多信息:

如果this post等于pid,则0被发送到调用进程的进程组中的每个进程。

所以我开始玩转,瞧瞧,它确实起作用了:

sig

起初我担心“ Terminated”文本会出来,但是它不在stdout上,所以不会妨碍您的操作:

$ time tar -ztf /tmp/z.txz | grep -m1 '/packagesite\.txz$'
2.2.0/FreeBSD:11:amd64/latest/packagesite.txz
53.866 real, 3.947 user, 5.119 sys
$
$ time tar -ztf /tmp/z.txz | ( grep -m1 '/packagesite\.txz$' ; kill 0 )
2.2.0/FreeBSD:11:amd64/latest/packagesite.txz
Terminated
0.008 real, 0.003 user, 0.004 sys

-1
投票

是,它没有按预期运行,根据我的发现,并引用了$ tar -ztf /tmp/z.txz | ( grep -m1 '/packagesite\.txz$' ; kill 0 ) > z.out Terminated $ cat z.out 2.2.0/FreeBSD:11:amd64/latest/packagesite.txz grep页面,该页面仅适用于文件。

下面是man页面的摘要:

-m NUM,--max-count = NUM​​

在NUM条匹配的行之后停止读取文件。如果输入是来自常规文件的标准输入,NUM条匹配的行是输出,grep确保将标准输入定位为退出前的最后一个匹配行之后,无论尾随上下文线的存在。这样可以进行呼叫过程恢复搜索。当grep在NUM条匹配行之后停止时,它会输出任何尾随的上下文行。当-c或--count还使用了option,grep不会输出大于NUM的计数。当还使用-v或--invert-match选项时,grep在之后停止输出NUM条不匹配的行。

© www.soinside.com 2019 - 2024. All rights reserved.