子进程可以向父母发出信号吗?

时间:2014-10-23 16:11:48

标签: bash

考虑这种情况,当我想生成一个打算在后台运行的子进程时,但需要花一点时间进行设置,比如launch-git-daemon。如何通知调用脚本脚本已准备好开始服务?

调用(父)脚本:

#!/bin/bash

./launch-git-daemon /srv/git-repos &
pid=$!

wait-until-launch-git-daemon-notifies-us

#do stuff that involves access to the git server

launch-git-daemon

#!/bin/bash
repopath="$1"

sudo dpkg -s git>/dev/null
if [ $? -eq 0 ]; then
    echo "git already installed!"
else
    sudo apt-get --yes install git
fi

signal-to-parent-that-we-are-ready-to-serve

git daemon --verbose --base-path="$repopath" --export-all --informative-errors --enable=receive-pack

我知道孩子总是可以触摸一些tmp文件,父母可以测试它的存在,但它看起来很笨拙和效率低下。我希望在bash中建立某种进程间通信机制!

3 个答案:

答案 0 :(得分:2)

您可以将命名管道用于此类目的。

$ mknod testpipe p

$ ls -la
total 20
drwxr-xr-x  2 gp         users 4096 Oct 23 12:31 .
drwxr-xr-x 11 gp         users 4096 Oct 23 12:29 ..
prw-r--r--  1 gp         users    0 Oct 23 12:31 testpipe


$ ( read line <testpipe ; echo "We read this: $line"; ) &
[1] 17065

$ echo "This is a test" >testpipe

$ We read this: This is a test
[1]+  Done                    ( read line < testpipe; echo "We read this: $line" )

因此,只要孩子在命名管道中写入,父母就会得到满意的“读取”语句。 (如果你在循环中读取,你可以读取多行。)

如果你想一想,你可以意识到孩子可以做的不仅仅是写任何东西。它可以将信息传递给父母,告诉它事情进展顺利,或失败等等。而且你不仅限于一个孩子。父节点可以创建一个命名管道,并生成多个子节点,每个子节点使用相同的管道告诉父节点何时准备好。

请记住,通常您应该只从管道中读取一个任务。如果有多个读者,则无法预测哪个读者会得到孩子所写的行。

答案 1 :(得分:1)

在一个终端中运行此脚本:

#! /bin/bash

sigusr1_received=false

catch_sigusr1 () { sigusr1_received=true ;}

trap catch_sigusr1 USR1

echo "My PID is $$"
echo "Waiting for SIGUSR1 ..."

while ! $sigusr1_received ; do sleep 1 ; done

echo "SIGUSR1 received."

exit 0

现在kill -USR1另一个终端中正在运行的脚本,它会在第二个终端中检测到信号接收。

答案 2 :(得分:1)

这是两种方法的公平比较。

命名管道

<强> parent.sh:

#!/bin/bash

#Spawn the child process
pipe=/tmp/mypipe
if [[ ! -p $pipe ]]; then
    mkfifo $pipe
fi
bash -x ./child.sh &
childpid=$!

sleep 10 #Do some work, we will need a child soon after it.

read ans <$pipe
if [[ "$ans" != "ready to serve" ]]; then
    echo "Unknown answer from child!"
    exit 1
fi

#Here we can do stuff that require readiness from the client

sleep 5

#Kill the child

kill $childpid

<强> child.sh:

#!/bin/bash

if [ -n "$1" ]; then
    sleep 20 #Sometimes it takes long to start serving.
fi

pipe=/tmp/mypipe

if [[ ! -p $pipe ]]; then
    echo "Cannot find a parent process. This script is not intended to be run alone."
    exit 1
fi

echo "ready to serve" >$pipe

sleep 10000

信号

<强> parent.sh:

#!/bin/bash

#Spawn the child process

sigusr1_received=false
catch_sigusr1 () { sigusr1_received=true ;}
trap catch_sigusr1 USR1
bash -x ./child.sh &
childpid=$!

sleep 10 #Do some work, we will need a child soon after it.

while ! $sigusr1_received ; do sleep 1 ; done

#Here we can do stuff that require readiness from the client

sleep 5

#Kill the child

kill $childpid

<强> child.sh:

#!/bin/bash

if [ -n "$1" ]; then
    sleep 20 #Sometimes it takes long to start serving.
fi

kill -USR1 $PPID

sleep 10000

我会选择信号。命名管道为简洁和简单的成本提供了太多的灵活性。