【问题标题】:bash script to kill a python script after starting another same python scriptbash 脚本在启动另一个相同的 python 脚本后杀死一个 python 脚本
【发布时间】:2019-06-22 15:11:06
【问题描述】:

我启动了一个 python 脚本,然后过了一段时间我想杀死它。但在杀死它之前,我想启动另一个相同脚本的副本,然后在启动新脚本后杀死前一个。我想循环执行此操作。

这是我的代码,我只需要一种干净的方式来杀死脚本。我不想使用超时。

#!/bin/bash 
while true
do
    echo "starting FIRST Consumer.py : $(date +"%T")"
    python3 /home/irum/Desktop/Marketsyc/Consumer.py &

    sleep 20
    echo "starting SECOND Consumer.py : $(date +"%T")"
    python3 /home/irum/Desktop/Marketsyc/Consumer.py &
    # Here I want to kill FIRST Consumer.py
    sleep 20
    # Here I want to kill SECOND Consumer.py

done

【问题讨论】:

  • 有什么理由不想使用 timeout 20 python3 ...? man7.org/linux/man-pages/man1/timeout.1.html
  • 是的,我正在使用超时,但有时它不会杀死我的脚本。但开始新的。一段时间后,我运行了 8 个脚本。
  • 您确定代码示例中的 cmets 吗? (你把 SECOND 和 FIRST 倒置了吗?)
  • 我已经编辑了 cmets :p
  • 清洁和杀戮是一种相互矛盾的要求。其中 kill 的意思是“不惜一切代价停止”,而 clean 的意思是“优雅地退出”。如果您的程序在SIGTERM 信号之后没有退出,那么它行为不端。在使用SIGKILL 之前修复你的python 脚本。使用SIGKILL 的缺点包括如果进程无法保存有关已消费内容的状态,则会丢失状态。

标签: python linux bash


【解决方案1】:

你可以获取第一个进程的 PID 来杀死它:

#!/bin/bash 

while true
do
    echo "starting FIRST Consumer.py : $(date +"%T")"
    python3 /home/irum/Desktop/Marketsyc/Consumer.py &
    pid=$!
    sleep 20

    echo "starting SECOND Consumer.py : $(date +"%T")"
    python3 /home/irum/Desktop/Marketsyc/Consumer.py &
    new_pid=$!

    # Here I want to kill FIRST Consumer.py
    kill "$pid"
    sleep 20

    # Here I want to kill SECOND Consumer.py
    kill "$new_pid"
done

【讨论】:

  • 这个答案对我有用,但是当我添加 -9 来杀死命令 kill -9 "$pid"
  • 这个细节取决于你想杀死什么。默认情况下,kill 发送一个SIGTERM 信号(15),这个信号可以被捕获和处理。它应该让应用程序有机会写下它的状态并优雅地退出。但是如果它不退出,你总是可以使用SIGKILL(9),它不能被捕获并强制系统杀死应用程序。
【解决方案2】:

bash 中有两个特殊的后台作业:+-。您可以在jobs 命令的输出中看到它们:

$ sleep 10 &
$ sleep 20 &
$ sleep 30 &
$ jobs
[1]   Running                 sleep 10 &
[2]-  Running                 sleep 20 &
[3]+  Running                 sleep 30 &

+ 是最近运行的作业。 -+ 之前的最新工作。如果您终止工作或开始新工作,两者都会更新。因此,您可以按如下方式完成您的脚本:

#!/bin/bash 
while true; do
    echo "starting FIRST Consumer.py : $(date +%T)"
    python3 /home/irum/Desktop/Marketsyc/Consumer.py &
    sleep 20
    echo "starting SECOND Consumer.py : $(date +%T)"
    python3 /home/irum/Desktop/Marketsyc/Consumer.py &
    kill %- # kill FIRST Consumer.py
    sleep 20
    kill %+ # kill SECOND Consumer.py
done

这只有在Consumer.py 的运行时间总是超过 20 秒时才能可靠地工作。如果Consumer.py 可以在 20 秒结束之前终止,那么我们可能会杀死错误的工作。要解决此问题,您可以使用(python3 .../Consumer.py; sleep inf) & 而不是python3 .../Consumer.py &sleep inf 将阻止作业自行终止。

【讨论】:

    【解决方案3】:

    每次启动后台进程时,bash 都会维护一个作业列表,id 从 1 开始。

    jobs 内置函数列出了后台作业。

    在您的情况下,您将添加 kill %1 以终止已启动的第一个后台作业,然后添加 kill %2

    == EDITED == 你的脚本变成:

    #!/bin/bash 
    while : ; do
       echo "starting FIRST Consumer.py : $(date +"%T")"
       python3 /home/irum/Desktop/Marketsyc/Consumer.py &
    
       sleep 20
       echo "starting SECOND Consumer.py : $(date +"%T")"
       python3 /home/irum/Desktop/Marketsyc/Consumer.py &
    
       kill %1
    
       sleep 20
    
       kill %2
    
       wait
     done
    

    【讨论】:

    • 作业 ID 总是增加。 %1%2 仅适用于第一次迭代。在第二次迭代中,您必须使用%3%4。您可以使用 $! 访问最后一个作业的 PID(不是作业 ID)。
    • @Socowi:由于循环在没有任何后台作业的情况下结束,因此 ID 始终为 1 和 2。我的测试证实了这一点。
    • 你确定吗?我在两个不同的系统上测试了我在 bash 4.4.19(1) 和 5.0.0(1) 中的声明。对我来说,下面的脚本会快速打印大于 2 的数字。while :; do sleep 10 & sleep 20 & kill %1; kill %2; jobs | wc -l; done
    • 也许你是对的。 sleep 1 & kill %1; sleep 2 & jobs 创建作业 ID %1 和 %2,但 sleep 1 & kill %1; sleep 0.5; sleep 2 & jobs 使用作业 ID %1 两次。似乎kill 是异步的,我们需要在终止旧作业和开始新作业之间稍作停顿,以便在新作业开始之前释放旧作业 ID。
    • 这个小怪癖是我更喜欢在脚本中使用 PID 的原因。交互式作业管理是另一种野兽。
    【解决方案4】:

    我会这样做

        #!/bin/bash 
    function check_pid() {
        if /bin/ps -p $1 > /dev/null
        then
            kill $1
        else
            echo "not running"
        fi
    }
    
    while true
    do
        echo "starting FIRST Consumer.py : $(date +"%T")"
        python3 /home/irum/Desktop/Marketsyc/Consumer.py &
        pid1=$!
        sleep 20
        echo "starting SECOND Consumer.py : $(date +"%T")"
        python3 /home/irum/Desktop/Marketsyc/Consumer.py &
        pid2=$!
        # Here I want to kill FIRST Consumer.py
        check_pid $pid1
        sleep 20
        # Here I want to kill SECOND Consumer.py
        check_pid $pid2
    done
    

    这样,进程只有在运行时才会被杀死。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-30
      • 2017-03-31
      • 1970-01-01
      • 2022-11-12
      • 1970-01-01
      • 2011-03-04
      • 1970-01-01
      • 2013-02-08
      相关资源
      最近更新 更多