bash脚本中的进程控制



我对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 
}

你能告诉我以上是否可行吗?"也许"我在狂欢节上错过了什么。也许有更好的方法来做这件事,而不是像我想的那样。

谢谢大家!

我认为这是可行的。一些注意事项:

  1. 即使您停止了一个进程,它的子进程也将继续愉快地运行。如果你也想停止这些,那么你需要在父级中捕获stop和CONT信号,以停止并恢复子级。

  2. 为什么不将PID保存在变量中呢?

  3. 您可以将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

最新更新