本文目录导读:

- 目录导读
- 为什么需要自动获取软件安装列表?
- 主流系统脚本方案对比
- 实战:PowerShell脚本获取Windows已安装软件
- 实战:Bash脚本获取Linux软件列表
- 实战:macOS终端命令导出应用清单
- 脚本输出格式优化与远程采集
- 常见问题与解决方案(Q&A)
- 自动化脚本的进阶技巧
脚本自动化采集与导出全攻略
目录导读
- 为什么需要自动获取软件安装列表?
- 主流系统脚本方案对比(Windows/macOS/Linux)
- 实战:PowerShell脚本获取Windows已安装软件
- 实战:Bash脚本获取Linux软件列表
- 实战:macOS终端命令导出应用清单
- 脚本输出格式优化与远程采集
- 常见问题与解决方案(Q&A)
- 自动化脚本的进阶技巧
为什么需要自动获取软件安装列表?
在日常系统运维、安全审计、软件资产盘点或迁移前,手动记录几百台电脑的软件列表不仅低效,而且容易遗漏,脚本化采集能实现:
- 批量审计:快速检查未授权软件或过时版本
- 环境复现:迁移系统时一键导出依赖列表
- 自动化报告:结合定时任务生成合规报表
你可能面临的问题:Windows注册表路径不同、macOS签名的限制、Linux包管理器的差异——这些都可以通过特定脚本解决。
主流系统脚本方案对比
| 系统类型 | 推荐脚本语言 | 核心命令/接口 | 输出示例 |
|---|---|---|---|
| Windows | PowerShell | Get-WmiObject,Get-ItemProperty |
名称、版本、安装路径 |
| Linux (APT) | Bash | dpkg -l |
包名、版本、架构 |
| Linux (RPM) | Bash (YUM/DNF) | rpm -qa |
同上 |
| macOS | Bash + system_profiler | system_profiler SPApplicationsDataType |
名称、版本、来源 |
兼容性警示:Windows旧版系统(如Win7)需改用WMI查询;macOS Big Sur后部分应用签名变更。
实战:PowerShell脚本获取Windows已安装软件
核心代码(建议管理员身份运行)
# 方法一:通过注册表(可靠度高)
$software = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |
Where-Object { $_.DisplayName -ne $null } |
Select-Object DisplayName, DisplayVersion, Publisher, InstallDate
$software | Export-Csv -Path "Windows_Software_List.csv" -NoTypeInformation -Encoding UTF8
# 方法二:通过Win32_Product(慢但含更多元数据)
# Get-WmiObject Win32_Product | Select-Object Name, Version, Vendor
优化要点
- 过滤系统组件:添加
Where-Object {$_.DisplayName -notlike "KB*"}排除Windows更新 - 识别64位软件:同时扫描
HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* - 远程批量执行:在Invoke-Command中嵌套脚本,指定多台计算机名称
注意:Win32_Product类会触发软件配置检查,生产环境慎用(可能引发MSI重新配置)。
实战:Bash脚本获取Linux软件列表
Debian/Ubuntu系列
#!/bin/bash
dpkg-query -f '${Package}\t${Version}\t${Architecture}\n' -W > linux_apt_software.txt
# 或更详细:dpkg -l | grep '^ii' | awk '{print $2, $3}'
Red Hat/CentOS/Fedora系列
#!/bin/bash
rpm -qa --queryformat '%{NAME}\t%{VERSION}\t%{ARCH}\n' > linux_rpm_software.txt
# 若需含安装日期:rpm -qa --last
跨发行版谨慎方案
使用 which 检测常见包管理器,动态切换:
if command -v dpkg &> /dev/null; then
dpkg -l > list.txt
elif command -v rpm &> /dev/null; then
rpm -qa > list.txt
fi
高级功能:结合 grep -vE "^(lib|perl)" 过滤库文件,只保留用户可见应用。
实战:macOS终端命令导出应用清单
macOS因沙箱机制,应用信息分为三类:
获取系统记录的应用
system_profiler SPApplicationsDataType -xml | plutil -convert json -o - | jq '.SPApplicationsDataType[] | {appName: ._name, version: .version, path: .path}'
# 若未安装jq,可改用:system_profiler SPApplicationsDataType | grep -E "Location:|Version:"
获取用户级应用
find /Applications -maxdepth 2 -name "*.app" -exec sh -c 'echo "{}: $(mdls -name kMDItemVersion {} | cut -d= -f2)"' \;
基于Homebrew的管理包
brew list --versions > homebrew_software.csv # 注意:只记录通过brew安装的命令行工具
常见误区:system_profiler 不会列出所有自主安装的免签名应用(如从网上下载的未签名dmg文件)。
脚本输出格式优化与远程采集
标准化CSV生成(以Windows为例)
$out = @()
$regPaths = @(
"HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*",
"HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
)
foreach ($path in $regPaths) {
$out += Get-ItemProperty $path -ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName } |
Select-Object @{N='System';E={'Windows'}}, DisplayName, DisplayVersion, Publisher
}
$out | Export-Csv -Path "unified.csv" -NoTypeInformation
远程批量采集(Linux示例)
for host in server1 server2 server3; do
ssh $host "dpkg -l | grep '^ii'" > "$host.txt"
done
# 若要并行加速,加入:& 背景进程
常见问题与解决方案(Q&A)
Q1:为什么Windows脚本有时会漏掉软件?
A:某些软件使用非标准注册路径(如 HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall),需补充扫描当前用户配置单元。
Q2:获取的版本号与实际不符怎么办?
A:注册表中的 DisplayVersion 可能缺失,可尝试 Get-WmiObject Win32_Product(注意性能影响),Linux用户可执行 apt-cache policy 包名 做二次验证。
Q3:如何禁止脚本输出系统自带组件?
A:增加过滤词库,Where-Object {$_.DisplayName -notmatch "Microsoft Visual C\+\+|DirectX|Windows"}
Q4:macOS导出的列表包含Adobe全家桶,但路径不一致?
A:Adobe应用常位于 /Applications/Adobe* 或 /Library/Application Support/Adobe,建议配合 find 命令全面扫描。
Q5:脚本能否导出安装日期?
A:Windows注册表含 InstallDate 键,但格式为YYYYMMDD字符串;Linux可使用 rpm -qi 包名 | grep Install Date;macOS应用日期隐藏在 com.apple.quarantine 扩展属性中。
Q6:如何保护导出的密码或密钥?
A:脚本不应采集敏感数据,若需认证,考虑使用SSH密钥登录远程主机,并确保CSV文件权限为 600(仅所有者读写)。
自动化脚本的进阶技巧
长期监控与变更日志
使用以下策略捕捉软件变动:
- Windows:注册表监控
WMI Event Subscription,当Uninstall子键变化时触发脚本 - Linux:
inotifywait监控/var/lib/dpkg/info或/var/lib/rpm - 统一方案:每日生成快照,用
diff对比前后文件
企业级集成
- 将脚本嵌入 Microsoft Intune 或 SCCM 的合规策略
- Linux:通过 Ansible 的
package_facts模块直接获取 - 输出JSON格式,方便对接 ELK 或 Splunk:
$software | ConvertTo-Json | Out-File "sw.json"
安全注意事项
- 避免在非信任网络中执行未经签名的PowerShell脚本(可启用
-ExecutionPolicy RemoteSigned) - Linux脚本避免使用裸
eval或$(命令)处理用户输入 - 导出文件定期清理,防止信息泄露
通过以上脚本方案,你可以实现从单机到集群、从手动到自动的软件资产采集。记住:脚本的核心价值在于减少重复劳动,但务必验证输出数据的完整性,建议先在测试环境运行,并对比系统自带工具(如“添加/删除程序”)的结果,当采集规模超过100台时,考虑引入诸如 saltstack 或 ansible 的集中管理平台。
(参考来源:Microsoft Docs关于Uninstall注册表路径的说明;Linux Foundation的dpkg/rpm手册;Apple Developer的system_profiler文档)