即使第一个命令的子进程仍在后台运行,也要关闭管道

时间:2012-10-02 11:22:51

标签: bash pipe sh background-process

假设我有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,e。 G。 ./test.sh | cat

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

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


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

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

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

3 个答案:

答案 0 :(得分:3)

看看这是否符合您的目的: (我假设你对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

答案 1 :(得分:2)

如果要显式关闭文件描述符,例如标准输出1,可以使用:

exec 1<&-

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

答案 2 :(得分:0)

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

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