【问题标题】:Python script checking if a particular Linux command is still running检查特定 Linux 命令是否仍在运行的 Python 脚本
【发布时间】:2019-02-11 14:15:33
【问题描述】:

我想编写一个 Python 脚本,它会每分钟检查一些预定义的进程是否仍在 Linux 机器上运行,以及它是否在崩溃的时间不打印时​​间戳。我编写了一个脚本,它正是这样做的,但不幸的是,它只适用于一个进程。

这是我的代码:

import subprocess
import shlex
import time
from datetime import datetime

proc_def = "top"
grep_cmd = "pgrep -a " + proc_def
try:
    proc_run = subprocess.check_output(shlex.split(grep_cmd)).decode('utf-8')
    proc_run = proc_run.strip().split('\n')
    '''
    Creating a dictionary with key the PID of the process and value
    the command line
    '''
    proc_dict = dict(zip([i.split(' ', 1)[0] for i in proc_run],
                         [i.split(' ', 1)[1] for i in proc_run]))

    check_run = "ps -o pid= -p "

    for key, value in proc_dict.items():
        check_run_cmd = check_run + key
        try:
            # While the output of check_run_cmd isn't empty line do
            while subprocess.check_output(
                                          shlex.split(check_run_cmd)
                                          ).decode('utf-8').strip():
                # This print statement is for debugging purposes only
                print("Running")
                time.sleep(3)
        '''
        If the check_run_cmd is returning an error, it shows us the time
        and date of the crash as well as the PID and the command line
        '''
        except subprocess.CalledProcessError as e:
            print(f"PID: {key} of command: \"{value}\" stopped
                  at {datetime.now().strftime('%d-%m-%Y %T')}")
            exit(1)
# Check if the proc_def is actually running on the machine
except subprocess.CalledProcessError as e:
    print(f"The \"{proc_def}\" command isn't running on this machine")

例如,如果有两个top 进程,它将仅向我显示有关其中一个进程的崩溃时间的信息,然后它将退出。只要有另一个进程正在运行,我就想保持活动状态,并且只有在两个进程都被杀死时才退出。它应该在每个进程崩溃时显示信息。

它也不应该仅限于两个proc,并且支持使用相同的proc_def命令启动的多个进程。

【问题讨论】:

  • 您最好使用其他一些模块来实现此目的,例如psutil 或类似的:)。这是链接psutil.readthedocs.io/en/latest
  • 所以我优化了我的脚本,用if psutil.pid_exists(int(key)):else 替换了第二个try/except 循环。完美运行。感谢您的提示。

标签: python linux subprocess


【解决方案1】:

必须稍微改变逻辑,但基本上你想要一个无限循环交替检查所有进程 - 而不是一遍又一遍地检查同一个:

import subprocess
import shlex
import time
from datetime import datetime

proc_def = "top"
grep_cmd = "pgrep -a " + proc_def
try:
    proc_run = subprocess.check_output(shlex.split(grep_cmd)).decode('utf-8')
    proc_run = proc_run.strip().split('\n')
    '''
    Creating a dictionary with key the PID of the process and value
    the command line
    '''
    proc_dict = dict(zip([i.split(' ', 1)[0] for i in proc_run],
                         [i.split(' ', 1)[1] for i in proc_run]))

    check_run = "ps -o pid= -p "
    while proc_dict:
        for key, value in proc_dict.items():
            check_run_cmd = check_run + key
            try:
                # While the output of check_run_cmd isn't empty line do
                subprocess.check_output(shlex.split(check_run_cmd)).decode('utf-8').strip()
                # This print statement is for debugging purposes only
                print("Running")
                time.sleep(3)
            except subprocess.CalledProcessError as e:
                print(f"PID: {key} of command: \"{value}\" stopped at {datetime.now().strftime('%d-%m-%Y %T')}")
                del proc_dict[key]
                break
# Check if the proc_def is actually running on the machine
except subprocess.CalledProcessError as e:
    print(f"The \"{proc_def}\" command isn't running on this machine")

这在原始代码中存在相同的问题,即时间分辨率为 3 秒,如果在此脚本期间运行了一个新进程,您将不会 ping 它(尽管这可能是需要的)。

第一个问题可以通过减少睡眠时间来解决,具体取决于您的需要,第二个问题是通过运行在while True 中创建proc_dict 的初始行。

【讨论】:

  • 如果我并行运行两个进程并且如果我在不同的时间杀死这两个进程,它只会显示其中一个进程崩溃的时间戳。
  • @GeorgеStoyanov 首先,我忘了提,但是您需要删除内部除外中的exit。其次,依赖于进程运行的顺序——如果你先杀掉第一个进程,然后杀掉第二个进程,这会起作用。我会看看是否有一个简单的解决方法,就目前而言,你是对的,这并不适用于所有情况。
  • 啊,是的,我忽略了它,但实际上,现在如果我先用更高的PID 杀死第二个进程,我会得到相同的崩溃时间戳。如果我先杀死第一个然后杀死第二个,它确实可以完美地工作。我希望在每次迭代时脚本检查两个进程是否都处于活动状态。
  • @GeorgеStoyanov 对逻辑进行了细微修改,因此您可以在键之间交替,而不是 ping 同一个键 - 这就是缺少的。
猜你喜欢
  • 1970-01-01
  • 2017-10-05
  • 1970-01-01
  • 2020-09-23
  • 2015-07-12
  • 1970-01-01
  • 2010-09-12
  • 2019-03-10
  • 2010-10-21
相关资源
最近更新 更多