You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python跨平台获取服务状态:Linux下如何区分进程与服务?

Great question! The distinction between services and processes on Linux is definitely trickier than on Windows, where services are a clearly defined, managed system entity. Let's break down how to tackle this, and how you can adjust your code to get accurate service statuses on Linux.

First, a quick context check:

On Linux, "services" are typically processes managed by an init system (like systemd, the default on most modern distros, or the older sysvinit). Unlike Windows, there's no dedicated "service" object—services are just regular processes monitored, started, and stopped by the init system. That's why your current psutil code grabs all processes, not just managed services.


Option 1: Query the init system directly (most reliable)

The most accurate way to get service statuses is to ask the init system itself. For modern Linux (systemd-dominated), we can use systemctl with JSON output for easy parsing. For older sysvinit systems, we fall back to the service command.

Here's how to integrate this into your code:

import os
import psutil
import subprocess
import shlex
import json

def getServiceDict():
    service_dict = {}
    if os.name == "nt":
        for service in psutil.win_service_iter():
            service_dict[service.name()] = service.status()
    elif os.name == "posix":
        # Try systemd first (modern Linux distros)
        try:
            cmd = "systemctl list-units --type=service --all --no-pager --output=json"
            result = subprocess.run(
                shlex.split(cmd),
                capture_output=True,
                text=True,
                check=True
            )
            services = json.loads(result.stdout)
            for service in services:
                # Strip the .service suffix from the unit name
                service_name = service["unit"].replace(".service", "")
                service_state = service["active"]
                service_dict[service_name] = service_state
        except (subprocess.CalledProcessError, FileNotFoundError):
            # Fallback to sysvinit for older systems
            try:
                cmd = "service --status-all"
                result = subprocess.run(
                    shlex.split(cmd),
                    capture_output=True,
                    text=True
                )
                lines = result.stdout.splitlines()
                for line in lines:
                    if line.startswith("["):
                        # Parse sysvinit's status format
                        status_char = line[1]
                        service_name = line[4:].strip()
                        if status_char == "+":
                            service_dict[service_name] = "running"
                        elif status_char == "-":
                            service_dict[service_name] = "stopped"
                        else:
                            service_dict[service_name] = "unknown"
            except Exception as e:
                # Last resort: fall back to psutil processes (mark as non-service)
                for pid in psutil.pids():
                    try:
                        proc = psutil.Process(pid)
                        service_dict[proc.name()] = f"process ({proc.status()})"
                    except (psutil.NoSuchProcess, psutil.AccessDenied):
                        continue
    return service_dict

Option 2: Use psutil to detect managed processes

If you prefer not to rely on external commands, you can use psutil to check clues that a process is a managed service:

  • Most systemd services have a parent PID of 1 (the systemd process itself)
  • Their control group (cgroup) path will include references to systemd

Here's a helper function to identify systemd-managed processes:

def is_systemd_service(proc):
    try:
        # Check if parent process is systemd (PID 1)
        if proc.ppid() != 1:
            return False
        # Verify cgroup includes systemd reference
        cgroups = proc.cgroup()
        return any("systemd" in part for part in cgroups)
    except (psutil.NoSuchProcess, psutil.AccessDenied):
        return False

You can then modify your Linux code to only include these processes:

elif os.name == "posix":
    for pid in psutil.pids():
        try:
            proc = psutil.Process(pid)
            if is_systemd_service(proc):
                service_dict[proc.name()] = proc.status()
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            continue

Key Notes

  • Permissions: Some service details (like cgroup info or full systemctl output) may require root privileges. Test with sudo if you're missing expected services.
  • Edge Cases: Not all processes with PID 1 as parent are services (some user processes reparent to init). That's why the systemctl method is more reliable.
  • Legacy Systems: The sysvinit fallback works but has inconsistent output formats across distros, so it's less ideal than systemd.

内容的提问来源于stack exchange,提问作者Dean

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 16:02:45