我对bash脚本中的进程控制有点困惑。
我想要的是运行特定的函数/例程,并在10:00停止它们,然后运行一些其他函数。当"其他功能"结束时,我希望第一个功能从停止时的位置继续。
例如,假设我在09:50运行main.sh。我希望function_one在时间为10:00时停止,运行function_two,然后在它的确切状态下继续使用function_one。不用说,这个函数_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
}
你能告诉我以上是否可行吗?"也许"我在狂欢节上错过了什么。也许有更好的方法来做这件事,而不是像我想的那样。
谢谢大家!
我认为这是可行的。一些注意事项:
-
即使您停止了一个进程,它的子进程也将继续愉快地运行。如果你也想停止这些,那么你需要在父级中捕获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
与其运行一个不断检查是否是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
派生了自己的子级,则必须确保它是以这样的方式编写的,以便在它自己停止时停止它们。
要捕获所有子进程,我想它们将属于同一进程组,由启动它们的程序启动。杀死该团体将杀死所有儿童、孙子女等。
可以这么简单:
#!/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.
感谢大家的即时回复,我对延误表示歉意。我有一个系统磁盘驱动器故障(!!)
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