如何用脚本获取所有运行服务(全平台实战解析)
目录导读
- 为什么需要自动化获取运行服务? – 手动排查的痛点与脚本化优势
- 核心脚本原理 – 不同操作系统下的服务管理命令与底层逻辑
- Linux环境实战脚本 – systemd/init.d 全兼容方案
- Windows环境实战脚本 – PowerShell与CMD双写法
- 跨平台脚本(Python) – 统一实现,一处部署到处运行
- 常见问题与问答精选 – 解决运行报错、权限不足等高频问题
- SEO优化与安全提醒 – 脚本发布前必须检查的3个要点
为什么需要自动化获取所有运行服务?
在运维工作中,快速掌握服务器上所有活跃服务(如Web服务器、数据库、定时任务等)的状态,是诊断问题、合规审计、资源优化的基础,手动执行 service --status-all(Linux)或打开“服务”管理器(Windows)存在三大痛点:

- 效率低:多台服务器逐一登录,耗时以小时计。
- 易遗漏:隐蔽服务(如自启动的恶意进程)不易被肉眼发现。
- 难统一:跨平台环境(混用Windows/Linux/macOS)需要记忆不同命令。
通过脚本实现自动化采集,可一次性输出服务名称、状态、PID、依赖关系等关键信息,为后续的监控、告警或报表生成打下基础。
核心脚本原理
脚本获取运行服务的本质,是调用操作系统提供的进程/服务管理接口,不同平台的核心差异如下:
| 操作系统 | 默认服务管理器 | 关键命令/接口 |
|---|---|---|
| Linux | systemd(主流)或 init.d | systemctl list-units --type=service --state=running 或 service --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:修改脚本末尾,将结构化数据导出为文件:
Linux:systemctl 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回答。
安全实践(脚本发布前必检)
- 避免硬编码密码:脚本中不应出现任何账号密码,应通过环境变量或密钥管理服务获取。
- 限制执行范围:生产环境请设置脚本可执行权限最小化(如
chmod 700),防止非授权执行。 - 日志脱敏:输出中如果包含敏感服务名(如内部API),应过滤或哈希处理。
延伸阅读
- 微软官方:使用PowerShell管理Windows服务
- Linux文档:systemd服务管理命令参考
- Python psutil库:官方文档及案例
最后建议:将上述脚本保存为 .sh/.ps1/.py 文件,并加入定时任务(如cron、Task Scheduler),即可实现服务状态自动巡检,结合邮件或Webhook通知,就能构建轻量级的服务监控系统,实际部署前,请在测试环境验证路径和用户权限。