Bash 如果进程产生了xclip的后台分支,则输出重定向将挂起
我有一个脚本,在里面调用Bash 如果进程产生了xclip的后台分支,则输出重定向将挂起,bash,pipe,zsh,pipeline,xclip,Bash,Pipe,Zsh,Pipeline,Xclip,我有一个脚本,在里面调用xclip。大概是这样的: #!/bin/bash RESULT="some data" echo $RESULT | xclip echo $RESULT xclip将数据从其stdin放入剪贴板,生成一个后台线程以保留该缓冲区(这就是剪贴板在X11中的工作方式),并将其与tty分离 如果我直接运行脚本,它将按预期工作: $ ./script.sh some data $ 但是,如果我尝试将其输出传递到管道中,它将一直挂起,直到xclip后台进程结束(基本上,直到其
xclip
。大概是这样的:
#!/bin/bash
RESULT="some data"
echo $RESULT | xclip
echo $RESULT
xclip
将数据从其stdin放入剪贴板,生成一个后台线程以保留该缓冲区(这就是剪贴板在X11中的工作方式),并将其与tty分离
如果我直接运行脚本,它将按预期工作:
$ ./script.sh
some data
$
但是,如果我尝试将其输出传递到管道中,它将一直挂起,直到xclip
后台进程结束(基本上,直到其他人将数据放入剪贴板)
我发现xclip
有一个-f
标志,似乎可以解决这个问题
从手册页:
在in模式下调用xclip时,输出级别设置为静默(默认设置),过滤器选项将导致xclip打印通过管道传输到标准in的文本
返回标准输出,未经修改
然而,我试图理解为什么它是这样工作的
我创建了另一个行为方式相同的示例:
echo$(睡眠5&)
另外,我被告知在fish
中,我的示例不带-f
标志
因此,问题是:1.这是shell(
bash
和zsh
)的错误还是预期的行为?2.
-f
标志如何影响该行为?从手册页上看,这似乎不是很相关。3.如何使其他脚本(例如
sleep
)按照xclip
使用-f
标志的方式工作?默认情况下
/script.sh |/other_script.sh
时,后台的xclip
将继承'script.sh'标准输出(它是/other_script.sh
的输入),此时,有两个进程(script.sh,xclip)连接到管道。只有当两者都将关闭STDOUT(或终止)时,/other_script.sh
才会看到管道上的EOF,并且能够退出(假设它正在等待输入上的EOF)
在这些情况下,解决方案是通过后接地过程关闭标准输出,从而完成管道。通常,如果需要输出,stdout将被重定向到stderr。最有可能的情况是,'-f'关闭标准输出
Per manxclip
,可以编写echo$RESULT|xclip-f
(不需要额外的echo)来避免问题,并允许脚本作为管道的一部分运行
manfork
和manpipe
提供了详细信息。特别是
男2叉:
- 子级继承父级打开的文件描述符集的副本。子文件中的每个文件描述符都引用相同的 打开文件描述(请参见打开(2))作为父级中相应的文件描述符。这意味着两个文件描述 TOR共享打开文件状态标志、文件偏移量和信号驱动I/O属性(参见F_SETOWN和 F_SETSIG 在fcntl(2)中
所以像
{echo$RESULT | xclip;}>/dev/null
这样的东西可以修复它吗?我无法验证这一点。根据手册页,看起来“xclip-f”执行了上述功能,使其可以作为管道的一部分使用。我会扩展答案。谢谢你的详细解释。如果您能从手册页中添加一些描述此行为的链接或引用,将不胜感激。$RESULT=“some data”
->RESULT=“some data”
$ ./script.sh | ./another_script.sh # it hangs