Bash 从长时间运行的流程到xargs的管道传输没有任何效果
在bash中,我想启动我的程序(gollum),并使用stderr的一部分(端口号)作为另一个程序的参数。我将stderr重定向到stdout,并使用grep和sed过滤输出。我在stdout中得到结果:Bash 从长时间运行的流程到xargs的管道传输没有任何效果,bash,xargs,gollum-wiki,Bash,Xargs,Gollum Wiki,在bash中,我想启动我的程序(gollum),并使用stderr的一部分(端口号)作为另一个程序的参数。我将stderr重定向到stdout,并使用grep和sed过滤输出。我在stdout中得到结果: gollum -p0 2>&1| sed -n -e "s/.*port=//p" 它返回'56343'并继续运行,因为咕噜是一台服务器 但是,如果我想将其用作另一个带有xargs的程序的参数(即echo,但我想稍后使用它来启动具有端口号的internet navigato
gollum -p0 2>&1| sed -n -e "s/.*port=//p"
它返回'56343'并继续运行,因为咕噜是一台服务器
但是,如果我想将其用作另一个带有xargs的程序的参数(即echo,但我想稍后使用它来启动具有端口号的internet navigator),它将不起作用
gollum -p0 2>&1| sed -n -e "s/.*port=//p" | xargs -n1 echo
什么也没发生。你知道为什么吗,或者你有没有其他想法来做同样的事情
谢谢您的帮助。如果您不想让服务器在后台继续运行,这很容易做到。如果需要,一种方法是使用流程替换:
#!/bin/bash
# ^^^^- not /bin/sh; needed for >(...) syntax
gollum -p0 > >(
while IFS= read -r line; do
# start a web browser here, etc.
[[ $line = *"port="* ]] && echo "${line##*port=}"
# ...for instance, could also be:
# open "http://localhost:${line##*port=}/"
done
) 2>&1 &
…如果您只想读取包含
端口=
的第一行,那么将从处理程序的循环中断开,并在stdin退出之前处理其余的stdin(这与使用cat>/dev/null
一样简单)。问题在于Bash等待管道中的所有子级死亡,而golum
不会死亡(一个戒指让他活下来)?事实上这是因为咕噜没有死。我从其他地方杀人,它就工作了。我怎样才能让我的第二个程序在端口号返回后立即工作?如果咕噜没有选择在“守护进程”模式下运行,那么(咕噜-p02>&1&)|sed…| xargs…
假设您必须使用xargs
。(…)
的子shell不会等待golum
死亡。但是,您可能仍然对sed
不死亡有问题;也许您会使用sed-n-e'/port=/{s/*port=//p;q;}“
在第一条端口线之后停止。我认为您需要两种诡计:运行gollum
的过程和分析输出的sed
。太好了。请查看可用的选项-您不可能是唯一需要端口号的人,因此可能有办法找到我注意到有一个--port=4567
选项(这是默认的端口号);如果指定-p4567
而不是-p0
,它可能会在该端口上启动。这样,您就可以绕过所有问题;您可以告诉它该做什么,而不是试图让它告诉您它在做什么。顺便说一句,如果这是Linux,您可以使用更多的选项来检测实例正在使用的端口,而不是读取其输出——例如,您可以直接在procfs中查看它的文件描述符列表(或者使用一个工具,例如lsof
),这样您就不会取消错误,也不会依赖于为人类消费而构建的日志格式(这可能会随新版本而改变,或者取决于当前的语言/本地化/语言环境设置!)。谢谢,它可能会起作用,但我希望更简单一些。就易读性而言,“简单”与“简单”之间的区别在于具有非常明确的行为。通常,在bash中,可以有一种形式的简单,也可以有另一种形式的简单,但不能两者兼而有之。