Bash 子进程能否向父进程发送事件信号?
考虑一下这个场景,当我想要生成一个子进程,该子进程打算在后台运行,但需要一些时间来设置,比如Bash 子进程能否向父进程发送事件信号?,bash,Bash,考虑一下这个场景,当我想要生成一个子进程,该子进程打算在后台运行,但需要一些时间来设置,比如启动git守护进程。如何通知调用脚本脚本脚本已准备好开始服务 调用(父)脚本: 启动git守护进程: #!/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
启动git守护进程
。如何通知调用脚本脚本脚本已准备好开始服务
调用(父)脚本:
启动git守护进程
:
#!/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中内置了某种进程间通信机制 您可以将命名管道用于此类目的
$ 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" )
$mknod测试管道p
$ls-la
总数20
drwxr-xr-x 2 gp用户4096 10月23日12:31。
drwxr-xr-x 11 gp用户4096 10月23日12:29。。
prw-r--r--1 gp用户0 10月23日12:31测试管道
$(读线测试管)
$我们读到:这是一个测试
[1] +完成(读取行
因此,只要子级在命名管道中写入,父级就会满足“read”语句。(如果在循环中读取,则可以读取多行。)
如果你仔细想想,你会意识到孩子可以做的不仅仅是写任何东西。它可以将信息传递回家长,告诉家长事情进展顺利还是失败,等等。你不局限于一个孩子。家长可以创建一个命名管道,并产生多个孩子,每个孩子都使用同一个管道告诉家长当他们准备好的时候
请记住,通常情况下,您应该只有一个任务从管道中读取。如果有多个读取器,则无法预测哪个读取器将获得孩子们所写的行。在一个终端中运行此脚本:
#! /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
在另一个终端中运行脚本,它将在第二个终端中检测信号接收。这里是两种方法的公平比较
命名管道
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
#!/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
#!/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
#!/bin/bash
if [ -n "$1" ]; then
sleep 20 #Sometimes it takes long to start serving.
fi
kill -USR1 $PPID
sleep 10000
信号
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
#!/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
#!/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
#!/bin/bash
if [ -n "$1" ]; then
sleep 20 #Sometimes it takes long to start serving.
fi
kill -USR1 $PPID
sleep 10000
child.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
#!/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
#!/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
#!/bin/bash
if [ -n "$1" ]; then
sleep 20 #Sometimes it takes long to start serving.
fi
kill -USR1 $PPID
sleep 10000
我将使用信号。命名管道以简洁和简单为代价提供了太多的灵活性。使用
$PPID
变量?解决方案您需要向家长发出信号,表示孩子已经准备好了,对吗?因此,从孩子向家长发送一个信号,并将其困在家长中。陷阱
并不等待,这是正确的,但你可以很容易地在一个小的休眠循环中等待陷阱设置一个变量,或者从陷阱处理程序中运行第二个脚本,然后退出,等等。在我看来,signals方法更简洁、更简单。回答很好。Foe me管道提供了一点太多的功能,代价是多了一点失败点和要键入的字母-这就是我接受它的原因信号版本。