【问题标题】:Bash command substitution ( $(...) ) forcing process to foregroundBash 命令替换( $(...) )强制进程到前台
【发布时间】:2013-05-28 06:20:27
【问题描述】:

总结: 我有一个 bash 脚本,它在后台运行一个进程,并且应该作为普通命令在命令替换块内工作,例如 $(...)。脚本本身会产生一个分叉到后台的进程。可以简化为这个测试用例:

#!/bin/sh
echo something
sleep 5 &

在 shell 中运行此脚本将立即返回(并打印“某物”),在 $(...) 中运行它会挂起 5 秒,等待后台“睡眠”完成。

适用于在命令替换 shell 内启动并在后台生成进程的任何内容,显然包括该进程树中的任何子进程。好像对bash和zsh都有影响,其他的没试过。


原始问题:我有一个 bash 脚本,它应该将一个值打印到标准输出,并在每次运行时将其复制到 X 剪贴板。

#!/bin/sh
echo something
echo something | xclip -selection clipboard

这个脚本(我们称之为“某物”)旨在用于获取这个词(实际上是另一个命令的输出)并以不同的方式使用,例如:

$ something
something
$ xclip -o -selection clipboard
something
$ echo $(something)
^C

打印到普通标准输出,将输出复制到剪贴板以在普通 X 应用程序中使用,并且还应该能够使用带有 bash 命令替换的标准输出,在任何命令的中间插入这个词。

但是 bash 命令替换似乎强制 xclip 在前台保持活动状态。 xclip 通常会自行守护,因为 X 剪贴板要求客户端提供剪贴板内容,并且默认行为是在替换剪贴板内容后使其退出。

在 xclip 遇到这个问题后,我制作了我在这个问题开头写的最小测试用例,所以它似乎适用于 $(...) shell 内的任何守护进程

谁能解释这种行为?有什么办法可以避免吗?

【问题讨论】:

    标签: bash shell fork command-substitution xclip


    【解决方案1】:

    如果您希望后台进程不干扰命令替换,则必须断开其标准输出。这将立即返回:

    $ cat bg.sh 
    #!/bin/sh
    echo before
    sleep 5 >/dev/null &
    echo after
    $ date; x=$(./bg.sh); date; echo "$x"
    Sat Jun  1 13:02:26 EDT 2013
    Sat Jun  1 13:02:26 EDT 2013
    before
    after
    

    您将失去捕获后台进程的标准输出的能力,但如果您在后台运行它,您可能不在乎。 bg.sh 进程始终可以写入磁盘。

    【讨论】:

    • 哇!完美且极其简单的解决方案。谢谢!
    • 顺便说一句,重定向到文件而不是 /dev/null 似乎可以捕获输出,但至少在这里,输出文件似乎只有在后台进程退出后才会更新。 (不过,我不需要它)
    猜你喜欢
    • 2012-11-20
    • 1970-01-01
    • 1970-01-01
    • 2016-11-04
    • 2017-11-22
    • 2012-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多