基于Python(v3.6)实现TeamCity代理远程已安装软件检测与看板
Hey there! Let's break down how you can build this TeamCity agent software inventory dashboard with Python 3.6—since you're learning as you go, I'll keep things clear, actionable, and focused on small, testable steps.
First, we need to tackle pulling installed software info from each of your agent environments. Each has its own approach, so let's go one by one:
Windows Agents
Windows stores most installed software details in the registry, but the easiest remote-friendly method is using the wmic command. To run this remotely from Python, use the pywinrm library (it handles Windows Remote Management connections):
- Install the library:
pip install pywinrm - Example code to fetch software:
Note: Make sure the target Windows agent has WinRM enabled, and your user account has admin privileges.import winrm def get_windows_software(host, username, password): session = winrm.Session(host, auth=(username, password)) result = session.run_cmd('wmic product get name,version /format:csv') # Parse the CSV output (skip header row, clean up whitespace) output = result.std_out.decode('utf-8').strip().split('\n')[1:] software = [] for line in output: if line.strip(): parts = line.split(',') if len(parts) >=2: software.append({"name": parts[0].strip(), "version": parts[1].strip()}) return software
Linux Agents
Linux uses different package managers depending on the distro, but we can handle the common ones (Debian/Ubuntu, RHEL/CentOS) with SSH. Use the paramiko library for remote SSH execution:
- Install the library:
pip install paramiko - Example code to detect distro and fetch software:
import paramiko def get_linux_software(host, username, password): ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(host, username=username, password=password) # First detect the distro stdin, stdout, stderr = ssh.exec_command('lsb_release -is') distro = stdout.read().decode('utf-8').strip().lower() # Run the appropriate package command if distro in ['debian', 'ubuntu']: command = "dpkg-query --showformat='${Package}\t${Version}\n' -W" elif distro in ['redhat', 'centos', 'rhel']: command = "rpm -qa --queryformat '%{NAME}\t%{VERSION}\n'" else: # Fallback for other distros (e.g., Alpine uses apk) command = "apk info -v" stdin, stdout, stderr = ssh.exec_command(command) output = stdout.read().decode('utf-8').strip().split('\n') software = [] for line in output: if line.strip(): parts = line.split('\t') software.append({"name": parts[0].strip(), "version": parts[1].strip() if len(parts)>1 else "N/A"}) ssh.close() return software
AWS EC2 Agents
EC2 agents are just Windows/Linux instances, so reuse the above methods. But you can automate fetching instance IPs using the boto3 AWS SDK:
- Install the library:
pip install boto3 - Example to get EC2 instance details:
Note: You'll need AWS credentials set up (viaimport boto3 def get_ec2_instances(region): ec2 = boto3.client('ec2', region_name=region) instances = ec2.describe_instances(Filters=[{'Name': 'tag:Role', 'Values': ['TeamCityAgent']}]) # Adjust the filter to match your agent tags instance_list = [] for reservation in instances['Reservations']: for instance in reservation['Instances']: instance_list.append({ "id": instance['InstanceId'], "ip": instance['PublicIpAddress'] if 'PublicIpAddress' in instance else instance['PrivateIpAddress'], "os": instance['Platform'] if 'Platform' in instance else "Linux" }) return instance_list~/.aws/credentialsor environment variables) with permissions to describe EC2 instances.
OpenShift Container Agents
For containerized TeamCity agents in OpenShift, you can run commands inside the pod using either the oc CLI or the openshift Python library:
- Install the library:
pip install openshift - Example to fetch software from a pod:
from openshift import client, config def get_openshift_pod_software(pod_name, namespace): config.load_kube_config() # Or use load_incluster_config() if running in-cluster v1 = client.CoreV1Api() # Run package command inside the pod (adjust based on container OS) exec_command = ["/bin/sh", "-c", "dpkg-query --showformat='${Package}\t${Version}\n' -W || rpm -qa --queryformat '%{NAME}\t%{VERSION}\n'"] resp = v1.connect_get_namespaced_pod_exec( pod_name, namespace, command=exec_command, stderr=True, stdin=False, stdout=True, tty=False ) output = resp.strip().split('\n') software = [] for line in output: if line.strip() and not line.startswith('bash:'): parts = line.split('\t') software.append({"name": parts[0].strip(), "version": parts[1].strip() if len(parts)>1 else "N/A"}) return software
Once you can pull software data from all agents, you need to display it in a readable dashboard. For a beginner-friendly option, use streamlit (make sure to install a version compatible with Python 3.6):
- Install streamlit:
pip install streamlit==1.19.0 - Example dashboard code:
Run the dashboard with:import streamlit as st # Import your detection functions here st.title("TeamCity Agent Software Inventory") # Fetch data (you can add caching with @st.cache to avoid repeated remote calls) @st.cache(ttl=3600) # Refresh every hour def fetch_all_agents(): # Add code to fetch data from all your agents here agents = [ {"name": "Windows-Agent-01", "os": "Windows", "software": get_windows_software("10.0.0.1", "admin", "password")}, {"name": "Linux-Agent-01", "os": "Linux", "software": get_linux_software("10.0.0.2", "ubuntu", "password")}, # Add other agents... ] return agents agents = fetch_all_agents() # Display each agent's software for agent in agents: with st.expander(f"📦 {agent['name']} ({agent['os']})"): st.table(agent['software']) # Optional: Add a section to highlight version mismatches st.subheader("⚠️ Version Mismatches") # Logic to compare software versions across agents and flag inconsistencies # Example: Group software by name, check if all versions are the same software_map = {} for agent in agents: for sw in agent['software']: key = sw['name'] if key not in software_map: software_map[key] = {} software_map[key][agent['name']] = sw['version'] # Display mismatches for sw_name, versions in software_map.items(): if len(set(versions.values())) > 1: st.write(f"**{sw_name}**: {versions}")streamlit run your_dashboard.py
- Start small: Pick one environment (e.g., Linux) and get its detection working first, then add others. This avoids overwhelm.
- Add error handling: Wrap your remote calls in
try-exceptblocks to catch connection failures or permission errors, and log them for debugging. - Test locally first: Test your commands (like
wmicordpkg-query) directly on an agent machine before coding, to make sure they return the data you need. - Cache results: Use caching (like the
@st.cacheexample) to reduce the number of remote calls—this makes your dashboard faster and less likely to hit rate limits.
内容的提问来源于stack exchange,提问作者maverick

