我对bash脚本中的进程控制感到有点困惑。
我想要的是运行特定的功能/例程,并在10:00停止它们然后运行其他一些功能。当“其他功能”结束时,我希望第一个功能完全从它们停止时的位置继续。
例如,假设我在09:50运行main.sh。我希望function_one在时间为10:00时停止,运行function_two然后继续使用function_one处于准确状态。毋庸置疑,function_one可能非常复杂,并且本身也有后台子进程。
$ cat main.sh
#!/bin/bash
source functions.sh
function_one &
echo $! > function_one_running_in_background_PID.txt
while true; do
sleep 10s
if [[ $(date +%H%M) = 1000 ]]; then
kill -SIGSTOP $(<function_one_running_in_background_PID.txt)
echo Time is 10
function_two
kill -SIGCONT $(<function_one_running_in_background_PID.txt)
fi
done
$ cat functions.sh
#!/bin/bash
function function_one {
for i in {1..100000}; do echo 1st function: $i; sleep 1; done
}
function function_two {
for i in {1..100}; do echo 2nd function: $i; sleep 1; done
}
如果上述情况可以,请告诉我吗? “也许”我在bash中遗漏了一些东西。也许有更好的方法来做到这一点,而不是我的想法。
谢谢大家!
答案 0 :(得分:1)
我认为这可行。一些说明:
即使您停止某个流程,其子流程也会继续愉快地运行。如果你想要阻止那些,那么你需要在父母中捕获STOP和CONT信号以停止和恢复孩子。
而是将PID保存在文件中,为什么不保存在变量中?
您可以将kill -SIGSTOP
缩短为kill -STOP
,同样适用于CONT
以下是一个示例代码:
#!/bin/sh -e
f1() { for i in {1..1000}; do echo f1 $i; sleep 1; done; }
f2() { for i in {1..1000}; do echo f2 $i; sleep 1; done; }
f1 &
PID1=$!
f2 &
PID2=$!
kill -STOP $PID2
turn=1
while :; do
if test $turn = 1; then
kill -STOP $PID1
kill -CONT $PID2
turn=2
elif test $turn = 2; then
kill -STOP $PID2
kill -CONT $PID1
turn=1
fi
sleep 5
done
答案 1 :(得分:1)
不是运行一个不断检查是否为10:00的繁忙循环,而是计算出直到10:00的多少秒,并在停止第一个过程之前停留很长时间。不需要临时文件,因为您可以将进程ID存储在另一个参数中,直到需要为止。
t=$(( $(date +%s --date 1000) - $(date +%s) ))
function_one & f1_pid=$!
sleep $t
kill -STOP $f1_pid
function_two
kill -CONT $f1_pid
如果function_one
分拣自己的孩子,你必须确保它是以这样的方式写的,以便在它自己停止时停止它们。
答案 2 :(得分:1)
为了捕获所有的孩子,我想他们将属于同一个进程组,由启动它们的程序启动。杀死所有儿童,大孩子等等。
可能就是这么简单:
#!/bin/bash
#set the 'at' timer on 22:00 to give self a signal (see 'man at' )
at 22:00 <<<"/usr/bin/kill -SIGCONT $$"
#gentlemen...start your engines..ehrm..programs!
"/path/firstset/member1.sh" &
"/path/firstset/member2.sh" &
"/path/firstset/member3.sh" &
"/path/firstset/member4.sh" &
while :
do
kill -SIGSTOP "$$" #<--now we halt this script.
# wait for SIGCONT given by 'at'
# Very nicely scheduled on 22:00
#when waking up:
PLIST=$(pgrep -g "$$") # list PIDs of group (= self + subtree)
PLIST=${PLIST/"$$"/} # but not self, please
kill -SIGSTOP $PLIST #OK it is 22:00, halt the old bunch
"/path/secondset/member1.sh" & # start the new bunch
"/path/secondset/member2.sh" &
"/path/secondset/member3.sh" &
"/path/secondset/member4.sh" &
wait # wait till they are finished
kill -SIGCONT $PLIST #old bunch can continue now,
done #until next scheduled event.
答案 3 :(得分:0)
谢谢大家的即时答复,我为延误道歉。我的系统磁盘驱动器出现故障(!!)
Janos,如果f1中有后台进程,会发生什么?我怎么能阻止所有这些?
#!/bin/sh -e
f1() {
f3 &
f4 &
}
f2() { for i in {1..1000}; do echo f2 $i; sleep 1; done; }
f3() { for i in {1..1000}; do echo f3 $i; sleep 1; done; }
f4() { for i in {1..1000}; do echo f4 $i; sleep 1; done; }
f1 &
PID1=$!
f2 &
PID2=$!
kill -STOP $PID2
while :; do
if [[ $(date +%S) = *0 ]]; then
kill -STOP $PID1
kill -CONT $PID2
elif [[ $(date +%S) = *5 ]]; then
kill -STOP $PID2
kill -CONT $PID1
fi
sleep 1
done