【问题标题】:Close pipe even if subprocesses of first command is still running in background即使第一个命令的子进程仍在后台运行,也要关闭管道
【发布时间】:2012-10-02 11:22:50
【问题描述】:

假设我有test.sh,如下所示。目的是通过这个脚本运行一些后台任务,不断更新一些文件。如果后台任务因某种原因被终止,应该重新启动。

#!/bin/sh

if [ -f pidfile ] && kill -0 $(cat pidfile); then
    cat somewhere
    exit
fi

while true; do
    echo "something" >> somewhere
    sleep 1
done &
echo $! > pidfile

并想将其称为./test.sh | otherprogram,例如。 G。 ./test.sh | cat.

管道没有被关闭,因为后台进程仍然存在并且可能会产生一些输出。如何告诉管道在test.sh 结束时关闭?有没有比在调用管道命令之前检查 pidfile 是否存在更好的方法?

作为一种变体,我尝试在test.sh 的末尾使用#!/bin/bashdisown,但它仍在等待管道关闭。


我实际尝试实现的目标:我有一个“状态”脚本,它收集各种脚本的输出(uptimefreedateget-xy-from-dbus 等),类似于 @987654334 @ 这里。脚本的输出被传递给我的窗口管理器,它会显示它。它也用于我的 GNU 屏幕底线。

由于使用的某些脚本可能需要一些时间来创建输出,我想将它们从输出集合中分离出来。所以我把它们放在一个while true; do script; sleep 1; done 循环中,如果它还没有运行,它就会启动。

现在的问题是我不知道如何告诉调用脚本“真正”分离守护进程。

【问题讨论】:

  • 能否告诉我们,脚本的终止条件是什么?我的意思是,“等待”过程预计何时结束?
  • 脚本应该在结束后终止。如果它的输出没有通过管道传输,它会正确终止,即。 e.只是打电话给./test.sh
  • 我想我理解了你的问题。我会努力寻找答案。

标签: bash pipe sh background-process


【解决方案1】:

看看这是否符合您的目的: (我假设您对 while 循环中的任何 stderr 命令都不感兴趣。如果您愿意,您可以调整代码。:-))

#!/bin/bash

if [ -f pidfile ] && kill -0 $(cat pidfile); then
    cat somewhere
    exit
fi

while true; do
    echo "something" >> somewhere
    sleep 1
done >/dev/null 2>&1 &
echo $! > pidfile

【讨论】:

  • 就是这样! >/dev/null 是解决部分。不需要子shell(用大括号括起来),但& 必须放在2>&1 之后。然后最后一行也可以工作(这段代码没有,因为外壳不知道后台进程的PID)。
  • 我已经编辑了它(等待同行评审),以防其他人遇到这个问题。我可以在一小时内给你赏金。谢谢!
【解决方案2】:

如果你想显式关闭一个文件描述符,例如标准输出 1,你可以这样做:

exec 1<&-

这对 POSIX shell 有效,请参阅:here

【讨论】:

  • 建议一直运行,如果不运行则启动,因此杀死子进程或不幸等待无济于事。
  • 好的。很抱歉不明白你的问题。我认为我还没有完全理解它,但我想我已经开始理解了。我将其编辑为另一个答案。我不是 100% 确定这是你想要的,但希望它会有所帮助 =)
  • 感谢您给 exec 的提示。但是,我似乎无法让它工作。我尝试将exec 1&lt;&amp;- 放在脚本的末尾,据我所知,它应该已经关闭了标准输出 fd。但是,以./test.sh | cat 运行脚本,它仍然没有返回。添加exec 2&lt;&amp;- 以关闭stderr 也没有这样做。
【解决方案3】:

当您将 while 循环放在显式子 shell 中并在后台运行子 shell 时,它会提供所需的行为。

(while true; do
    echo "something" >> somewhere
    sleep 1
done)&

【讨论】:

  • 请解释一下。你说的是bash?祝大家好运。
  • 对不起,像./test.sh | cat 一样运行它仍然没有返回,而是永远等待。
猜你喜欢
  • 2015-08-20
  • 1970-01-01
  • 2021-04-06
  • 2020-03-03
  • 1970-01-01
  • 2021-04-20
  • 2016-05-21
  • 2018-12-26
  • 1970-01-01
相关资源
最近更新 更多