【问题标题】:Python SIGTERM not killing subprocessPython SIGTERM 不会杀死子进程
【发布时间】:2015-05-15 02:47:58
【问题描述】:

我有一个可以启动和关闭进程的类。但是它似乎没有关闭该过程。

我的 python 代码,还有其他方法,但它们工作正常。:

class KismetInstance:
    """Creates a kismet_server instance"""

    def __init__(self, value=False):
        logging.basicConfig(format='%(asctime)-15s::: %(message)s')
        self.logger = logging.getLogger('kismet_instance')
        self.example = value

    def __create_kismet_instance__(self):
        """
        Create a kismet_server subprocess.
        :return:
        """
        shell = ['sudo', '/usr/local/bin/kismet_server']
        self.logger.debug('Attempting to run: %s', " ".join(shell))
        self.kismet = Popen(shell, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=r'./logs', preexec_fn=os.setsid)


    def __destroy_kismet_instance__(self):
        """
        Kill the subprocess
        :return:
        """
        os.killpg(os.getpgid(self.kismet.pid), 15)

它可以很好地创建子流程。但是当我尝试杀死时出现此错误(没有 sudo)

OSError: [Errno 1] Operation not permitted

如果我使用 sudo 运行,之后进程仍在运行。

pi@raspberrypi ~/project $ ps -A | grep 'kismet'
 2912 ?        00:00:00 kismet_server

【问题讨论】:

  • 因为子进程是用“sudo”创建的,当你试图杀死它时,它不是从“sudo”或“root”用户发送的。尝试从“root”用户运行程序,它应该可以工作。或者如果你可以在非root帐户下运行/usr/local/bin/kismet_server,那么它也可以工作。
  • 如果kismet 正在拦截SIGTERM,您也可以尝试os.killpg(os.getpgid(self.kismet.pid), 2) for SIGINT
  • @NipunTalukdar 如果您阅读后半部分,我尝试以sudo 运行该程序,但它并没有杀死它。
  • @MartinKonecny 我试过 SIGINT 也没有关闭。
  • 您可以尝试进程无法拦截的信号9 SIGKILL,但这会导致程序不干净地关闭,并可能导致数据损坏。您应该这样做只是为了测试您的信号是否被正确发送。

标签: python subprocess kill


【解决方案1】:

我设法解决了这个问题。原来子进程正在重生,创造了一些奇怪的东西,阻止了 python 跟踪它。

所以我不得不这样做来修复它,但这不是最优雅的解决方案,而且相当危险

如果你使用这个要小心,因为如果你输入一个比我更宽泛的术语 ('kismet'),那么你可能会杀死系统上的很多进程。

def __destroy_kismet_instance__(self):
        """
        Kill the subprocess
        :return:
        """
        sig = signal.SIGKILL # What signal to send
        os.killpg(os.getpgid(self.kismet.pid), sig) # Kill one of them
        p_list = subprocess.Popen(['ps', '-A'], stdout=subprocess.PIPE) # Get All processes on system
        out, err = p_list.communicate()
        for line in out.splitlines(): # For each line (or process)
            if 'kismet' in line: # if 'kismet' appears in its name
                pid = int(line.split(None, 1)[0]) # Get the process ID
                self.logger.debug("Found: %d", pid)
                os.killpg(os.getpgid(pid), sig) # Kill the process

【讨论】:

  • 不要核对包含可执行名称包含'kismet'(您可以use psutil)的进程的任何进程组,而是考虑阅读kismet_server docs/source 以了解它是否有命令-line 参数,强制它在前台运行(没有守护进程和/或生成主管进程),因此可以简单地使用self.kismet.terminate()os.pgkill(self.kismet.pid, SIGTERM) 终止。另一种选择:也许检查您的代码在每个实例中调用 .__create_kismet_instance__() 方法一次。
猜你喜欢
  • 2013-08-05
  • 2016-01-24
  • 2019-01-18
  • 2022-01-03
  • 2010-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多