如何用脚本获取所有运行服务

wen 实用脚本 4

如何用脚本获取所有运行服务(全平台实战解析)

目录导读

  1. 为什么需要自动化获取运行服务? – 手动排查的痛点与脚本化优势
  2. 核心脚本原理 – 不同操作系统下的服务管理命令与底层逻辑
  3. Linux环境实战脚本 – systemd/init.d 全兼容方案
  4. Windows环境实战脚本 – PowerShell与CMD双写法
  5. 跨平台脚本(Python) – 统一实现,一处部署到处运行
  6. 常见问题与问答精选 – 解决运行报错、权限不足等高频问题
  7. SEO优化与安全提醒 – 脚本发布前必须检查的3个要点

为什么需要自动化获取所有运行服务?

在运维工作中,快速掌握服务器上所有活跃服务(如Web服务器、数据库、定时任务等)的状态,是诊断问题、合规审计、资源优化的基础,手动执行 service --status-all(Linux)或打开“服务”管理器(Windows)存在三大痛点:

如何用脚本获取所有运行服务

  • 效率低:多台服务器逐一登录,耗时以小时计。
  • 易遗漏:隐蔽服务(如自启动的恶意进程)不易被肉眼发现。
  • 难统一:跨平台环境(混用Windows/Linux/macOS)需要记忆不同命令。

通过脚本实现自动化采集,可一次性输出服务名称、状态、PID、依赖关系等关键信息,为后续的监控、告警或报表生成打下基础。


核心脚本原理

脚本获取运行服务的本质,是调用操作系统提供的进程/服务管理接口,不同平台的核心差异如下:

操作系统 默认服务管理器 关键命令/接口
Linux systemd(主流)或 init.d systemctl list-units --type=service --state=runningservice --status-all
Windows 服务控制管理器(SCM) Get-Service(PowerShell)或 sc query(CMD)
macOS launchd launchctl list

脚本的核心逻辑:解析上述命令的输出,提取服务名、状态、PID,并以结构化格式(JSON/CSV/表格)呈现。


Linux环境实战脚本

1 针对systemd(CentOS 7+/Ubuntu 16+)

#!/bin/bash
# 文件名: get_linux_services.sh
# 功能:获取所有运行中的systemd服务,含PID和描述
echo "Current running services (systemd) - $(date)"
echo "PID  | Service Name          | Status     | Description"
echo "-----------------------------+------------+-------------------------"
systemctl list-units --type=service --state=running --no-pager --plain | \
    awk 'NR>1 {print $1, $3}' | while read servicename status; do
        # 提取PID(通过主进程)
        pid=$(systemctl show -p MainPID "$servicename" 2>/dev/null | cut -d= -f2)
        desc=$(systemctl show -p Description "$servicename" 2>/dev/null | cut -d= -f2)
        printf "%-5s | %-20s | %-10s | %s\n" "$pid" "$servicename" "$status" "$desc"
    done

输出示例

PID  | Service Name          | Status     | Description
1    | systemd-journald      | running    | Journal Service
1234 | nginx                 | running    | A high performance web server

2 兼容init.d的旧版系统(如CentOS 6)

#!/bin/bash
# 针对SysVinit
service --status-all 2>/dev/null | grep 'running' | awk '{print $1, "running"}'

注意:该命令在部分发行版已废弃,建议优先检测systemd是否存在。


Windows环境实战脚本

1 PowerShell脚本(推荐,输出详细)

# 文件名: Get-WinServices.ps1
# 功能:获取所有运行中的服务,含PID、启动类型、账户
Get-Service | Where-Object {$_.Status -eq 'Running'} | ForEach-Object {
    $svc = $_
    $pid = (Get-WmiObject Win32_Service -Filter "Name='$($svc.Name)'" | Select-Object -ExpandProperty ProcessId)
    [PSCustomObject]@{
        ServiceName = $svc.Name
        DisplayName = $svc.DisplayName
        PID = $pid
        StartType = $svc.StartType
        Account = (Get-WmiObject Win32_Service -Filter "Name='$($svc.Name)'").StartName
    }
} | Format-Table -AutoSize

2 CMD脚本(保留兼容性)

@echo off
setlocal enabledelayedexpansion
echo 正在获取所有运行服务...
for /f "tokens=2 delims=," %%a in ('wmic service where "state='Running'" get name /format:csv ^| findstr /v "Name"') do (
    echo %%a
)

注意:CMD版输出信息较少,仅获取服务名,适合快速探查。


跨平台Python脚本(一次编写,处处运行)

利用Python的跨平台特性,统一处理Windows/Linux/macOS:

#!/usr/bin/env python3
# 文件名: get_services.py
# 依赖:psutil库(pip install psutil)
import psutil
import platform
import datetime
def get_running_services():
    """获取所有运行中的服务(跨平台)"""
    services = []
    for proc in psutil.process_iter(['pid', 'name', 'create_time', 'username']):
        try:
            # 过滤掉非服务进程(可根据实际需求调整)
            if proc.info['pid'] > 0:  # 排除PID=0的内核线程
                services.append({
                    'pid': proc.info['pid'],
                    'name': proc.info['name'],
                    'created': datetime.datetime.fromtimestamp(proc.info['create_time']),
                    'user': proc.info['username']
                })
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            pass
    return services
# 主程序
if __name__ == '__main__':
    print(f"系统: {platform.system()} {platform.release()}")
    print("所有运行的服务(进程级别):")
    print("PID\t名称\t\t启动时间\t\t用户")
    print("-"*70)
    for svc in get_running_services():
        print(f"{svc['pid']}\t{svc['name']}\t{svc['created'].strftime('%Y-%m-%d %H:%M')}\t{svc['user']}")

优势:统一输出格式,可集成到Ansible、Zabbix等工具链,但需注意:psutil返回的是所有进程,而非仅“服务”(Windows中服务程序通常有独立进程),如需精确提取服务,应在Windows上调用win32serviceutil库。


常见问题与问答精选

Q1:脚本提示“Permission denied”怎么办?

A:获取其他用户的服务PID需要管理员/root权限,Linux下使用 sudo 运行脚本;Windows下以管理员身份运行PowerShell或CMD。
示例
Linux: sudo ./get_linux_services.sh
Windows: 右键点击PowerShell → “以管理员身份运行”

Q2:为什么Windows上脚本返回的服务PID为空?

A:部分Windows服务(如系统内置服务)可能没有独立进程,或运行在svchost.exe容器内,可通过 Get-WmiObject Win32_Service 查看 ProcessId,若为0表示无进程。
优化建议:在输出中添加ProcessId字段提示“无独立进程”。

Q3:如何将脚本输出保存为JSON用于自动化?

A:修改脚本末尾,将结构化数据导出为文件:
Linuxsystemctl list-units --type=service --state=running --output=json(systemd原生支持JSON输出)
Python:在上方脚本中添加 import json; print(json.dumps(services, default=str))

Q4:脚本在容器(Docker)中运行获取不到宿主服务?

A:容器内默认只有自己的进程空间,需通过--pid=host参数运行容器,如:docker run --pid=host 你的脚本镜像注意:这会暴露宿主进程,需确保安全。


SEO优化与安全提醒

搜索引擎排名关键点(必应/谷歌)含核心长尾词**:如“自动获取服务脚本”、“Linux Windows服务监控”。

  • 结构清晰:使用H2/H3标签分隔步骤,本文已遵循。
  • 内链与外链:合理引用微软官方文档(如 docs.microsoft.com 应改为 learn.microsoft.com)、Linux man手册。
  • 原创性:综合真实运维经验,避免直接复制StackOverflow回答。

安全实践(脚本发布前必检)

  1. 避免硬编码密码:脚本中不应出现任何账号密码,应通过环境变量或密钥管理服务获取。
  2. 限制执行范围:生产环境请设置脚本可执行权限最小化(如 chmod 700),防止非授权执行。
  3. 日志脱敏:输出中如果包含敏感服务名(如内部API),应过滤或哈希处理。

延伸阅读


最后建议:将上述脚本保存为 .sh/.ps1/.py 文件,并加入定时任务(如cron、Task Scheduler),即可实现服务状态自动巡检,结合邮件或Webhook通知,就能构建轻量级的服务监控系统,实际部署前,请在测试环境验证路径和用户权限。

抱歉,评论功能暂时关闭!