Apt

如何跨多個伺服器/容器跟踪 linux 軟體包更新(替換 apticron)

  • April 16, 2017

我執行多台伺服器,並且在每十幾個容器中執行(lxc)。我仍在使用 apticron 來獲取有關新軟體包更新的資訊,但我開始淹沒在來自每個容器的電子郵件中,並且通常它們報告相同的更新,因為它們都相似。

我真正需要知道的是:哪些包更新正在等待哪些節點(最好在一條消息中)

基本上我喜歡 apticron,但電子郵件的數量已經失控了。

(考慮過使用 icinga2,但它會缺少資訊並且還會單獨通知每個節點)

這不能回答我的問題,而且 ocsinventory 對這項工作來說太重了:How to monitor package versions across multiple (Linux) servers

所以我繼續建構了一個 python 腳本,

它是我的第一個 python,所以請憐憫

該腳本必須以 root 身份執行,這取決於安裝的 apt、apt-listchanges 並且僅在您執行 lxc 時才有意義,但我想可以切換 lxc-attach 以支持通過 ssh 執行命令。

它僅列出每個軟體包一次以及受影響的主機,還詳細列出了組合更改。

輸出:

apt-monitor on ***
2017-04-16 20:28:25.394625 UTC

----- packages -----

linux-image-4.9.0-0.bpo.2-amd64
   version old: 4.9.13-1~bpo8+1
   version new: 4.9.18-1~bpo8+1
   affected hosts:
    - master

tzdata
   version old: 2017a-0+deb8u1
   version new: 2017b-0+deb8u1
   affected hosts:
    - master
    - service-mysql
    - www-stage

----- changes -----
linux-signed (4.4~bpo8+1) jessie-backports; urgency=medium

 * Rebuild for jessie-backports
 * Update to linux version 4.9.18-1~bpo8+1

-- Ben Hutchings <ben@decadent.org.uk>  Wed, 12 Apr 2017 15:50:11 +0100

linux-signed (4.4) unstable; urgency=medium

 * Update to linux version 4.9.18-1

-- Ben Hutchings <ben@decadent.org.uk>  Thu, 30 Mar 2017 17:43:56 +0100

tzdata (2017b-0+deb8u1) stable; urgency=medium

 * New upstream version, affecting the following future timestamp:
   - Haiti resumed observance of DST in 2017.

-- Aurelien Jarno <aurel32@debian.org>  Thu, 06 Apr 2017 11:53:44 +0200

程式碼:

#!/usr/bin/python

import re
import string
import subprocess
import sys
import datetime
import socket

# extract updates from apt output
def collect_upgrades(host, changes, upgrades, is_lxc):
 changes = changes.split('\n')
 pattern = re.compile('^Inst ([\S]+) \[([^\]]+)\] \(([\S]+) [^\[]*\[([^\]]+)\]\)')
 for change in changes:
   if pattern.match(change):
     matches = pattern.search(change)    
     upgrade = {'name' : matches.group(1), 'version_old' : matches.group(2), 'version_new' : matches.group(3), 'suffix' : matches.group(4), 'hosts' : [], 'is_lxc' : is_lxc}
     key = upgrade['name']+'_'+upgrade['version_new']
     if not key in upgrades:
       upgrades[key] = upgrade
     upgrades[key]['hosts'] += [host]

# distinct package update lookup
upgrades = {}

# gather changes from host and containers
changes = subprocess.check_output(['apt-get', '--just-print', 'dist-upgrade'])
collect_upgrades('master', changes, upgrades, False)

containers = subprocess.check_output(['lxc-ls', '-1']).strip().split('\n')
for container in containers:
 changes = subprocess.check_output(['lxc-attach', '-n', container, '--', 'apt-get', '--just-print', 'dist-upgrade'])
 collect_upgrades(container, changes, upgrades, True)

# if upgrades is empty we can exit
if not bool(upgrades):
 sys.exit(0)

# collect details apt-listchanges output for each package update
# also print upgrades

# print header


print 'apt-monitor on '+socket.gethostname()
print str(datetime.datetime.utcnow())+' UTC'
print ''
print '----- packages -----'

apt_changes = ''
for key, upgrade in upgrades.iteritems():
 deb_file = '/var/cache/apt/archives/'+upgrade['name']+'_'+upgrade['version_new']+'_'+upgrade['suffix']+'.deb'
 if upgrade['is_lxc']:
   container = upgrade['hosts'][0]
   apt_changes += subprocess.check_output(['lxc-attach', '-n', container, '--', 'apt-listchanges', '-f', 'text', deb_file])
 else:
   apt_changes += subprocess.check_output(['apt-listchanges', '-f', 'text', deb_file])  
 print ''
 print upgrade['name']
 print '    version old: '+upgrade['version_old']
 print '    version new: '+upgrade['version_new']
 print '    affected hosts:'
 for host in upgrade['hosts']:
   print '     - '+host

print ''
print '----- changes -----'
print apt_changes

引用自:https://serverfault.com/questions/843999