這是今年1月寫的 script… 用來監控各大 FreeBSD CVSUP mirror 網站的檔案更新程度,
提供服務的網址是 http://ftp.giga.net.tw/cvsup.php
內容其實很簡單,下面把程式放出來,有興趣的人歡迎免費拿去修改使用
==
原理說明:
CVS 不像 Subversion 一樣可以很容易知道目前 repository 中的最新版本為何,
必須要把每個檔案檢查一遍才有辦法知道最新的版本是什麼…
不過在 FreeBSD Source CVS 下面,每次 commit 都會有 commit log 可經由 CVSUP 取得,
因此我們可以利用 CVSROOT-*/commitlogs/* 這幾個檔案來判斷目前 source tree 的狀態..
只要把這幾個檔案經由 CVSUP 取出來就可以大致知道該伺服器的目前保存的最新版本是哪一個了
==
第一個是一個 Perl script,主要是連結到各大 FreeBSD CVSUP 網站取得相關資訊存下來
後面則附上一個 PHP script,可以把這些資訊用 HTML 表格方式呈現出來
check-cvsup.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/usr/bin/perl
# Check the update status for CVSUP servers
# BSD license
# Shen Cheng-Da (cdsheen AT gmail.com)
use POSIX qw ( strftime) ;
use Net:: DNS ;
use Time:: HiRes qw ( gettimeofday tv_interval ) ;
@servers = qw ( cvsup. tw. freebsd. org cvsup1. tw. freebsd. org cvsup2. tw. freebsd. org
cvsup3. tw. freebsd. org cvsup4. tw. freebsd. org cvsup5. tw. freebsd. org
cvsup6. tw. freebsd. org cvsup7. tw. freebsd. org cvsup8. tw. freebsd. org
cvsup9. tw. freebsd. org cvsup10. tw. freebsd. org cvsup11. tw. freebsd. org
cvsup12. tw. freebsd. org cvsup13. tw. freebsd. org cvsup14. tw. freebsd. org ) ;
$dir = '/home/cvsup-monitor' ;
$cvsup = '/usr/local/bin/cvsup' ;
$base = $dir . '/base' ;
$log = $dir . '/check.log' ;
chdir ( $dir ) || die "ERROR: Can not change to directory [$dir]\n " ;
mkdir ( $base , 0755 ) unless - d $base ;
@files_src = qw ( CVSROOT- src/ commitlogs/ CVSROOT CVSROOT- src/ commitlogs/ bin
CVSROOT- src/ commitlogs/ etc CVSROOT- src/ commitlogs/ contrib
CVSROOT- src/ commitlogs/ gnu CVSROOT- src/ commitlogs/ games
CVSROOT- src/ commitlogs/ include CVSROOT- src/ commitlogs/ lib
CVSROOT- src/ commitlogs/ release CVSROOT- src/ commitlogs/ sys
CVSROOT- src/ commitlogs/ sbin CVSROOT- src/ commitlogs/ share
CVSROOT- src/ commitlogs/ tools CVSROOT- src/ commitlogs/ user
CVSROOT- src/ commitlogs/ usrbin CVSROOT- src/ commitlogs/ usrsbin ) ;
@files_ports = qw ( CVSROOT- ports/ commitlogs/ CVSROOT
CVSROOT- ports/ commitlogs/ ports ) ;
$includes = '' ;
foreach $f ( @files_src ) {
$includes .= " -i $f" ;
}
foreach $f ( @files_ports ) {
$includes .= " -i $f" ;
}
open ( LOG, ">$log" ) ;
my $resolver = Net:: DNS :: Resolver -> new ;
$resolver -> usevc ( 1 ) ;
$resolver -> udp_timeout ( 5 ) ;
$resolver -> tcp_timeout ( 5 ) ;
$resolver -> retrans ( 3 ) ;
$resolver -> retry ( 2 ) ;
$resolver -> persistent_tcp ( 1 ) ;
foreach $server ( @servers ) {
my $query = $resolver -> query ( $server , 'A' ) ;
@ipaddr = @cname = ( ) ;
if ( $query ) {
foreach $rr ( $query -> answer ) {
if ( $rr -> type eq 'A' ) {
print LOG "$server => [A] " . $rr -> address . "\n " ;
push ( @ipaddr , $rr -> address ) ;
}
elsif ( $rr -> type eq 'CNAME' ) {
print LOG "$server => [CNAME] " . $rr -> cname . "\n " ;
push ( @cname , $rr -> cname ) ;
}
}
}
$ip = $ipaddr [ 0 ] ;
$ipaddr = join ( '|' , @ipaddr ) ;
$cname = join ( '|' , @cname ) ;
$ibase = "$base/$server" ;
mkdir ( $ibase , 0755 ) unless - d $ibase ;
mkdir ( "$ibase/SRC" , 0755 ) unless - d "$ibase/SRC" ;
$cmd = "$cvsup -h $ip -L 0 -b $ibase -r 0 $includes supfile" ;
$time_start = [ gettimeofday] ;
system ( $cmd ) ;
$elapsed = tv_interval( $time_start ) ;
printf LOG ( "$server => cvsup on $ip elapsed %.2fs\n " , $time_elapsed ) ;
unless ( $? ) {
$mt_src = $mt_ports = 0 ;
foreach $f ( @files_src ) {
$t = ( stat ( "$ibase/SRC/$f" ) ) [ 9 ] ;
$mt_src = $t if $t > $mt_src ;
}
foreach $f ( @files_ports ) {
$t = ( stat ( "$ibase/SRC/$f" ) ) [ 9 ] ;
$mt_ports = $t if $t > $mt_ports ;
}
open ( REC, ">$ibase/last-commit.txt" ) ;
printf REC( "$mt_src,$mt_ports,%.2f,$ipaddr,$cname" , $elapsed ) ;
close ( REC) ;
printf LOG ( "$server => SRC: %s\n " ,
strftime( "%Y/%m/%d %H:%M:%S" , localtime ( $mt_src ) ) ) ;
printf LOG ( "$server => PORTS: %s\n " ,
strftime( "%Y/%m/%d %H:%M:%S" , localtime ( $mt_ports ) ) ) ;
}
}
close ( LOG) ;
#!/usr/bin/perl
# Check the update status for CVSUP servers
# BSD license
# Shen Cheng-Da (cdsheen AT gmail.com)
use POSIX qw(strftime);
use Net::DNS;
use Time::HiRes qw( gettimeofday tv_interval );
@servers = qw( cvsup.tw.freebsd.org cvsup1.tw.freebsd.org cvsup2.tw.freebsd.org
cvsup3.tw.freebsd.org cvsup4.tw.freebsd.org cvsup5.tw.freebsd.org
cvsup6.tw.freebsd.org cvsup7.tw.freebsd.org cvsup8.tw.freebsd.org
cvsup9.tw.freebsd.org cvsup10.tw.freebsd.org cvsup11.tw.freebsd.org
cvsup12.tw.freebsd.org cvsup13.tw.freebsd.org cvsup14.tw.freebsd.org );
$dir = '/home/cvsup-monitor';
$cvsup = '/usr/local/bin/cvsup';
$base = $dir . '/base';
$log = $dir . '/check.log';
chdir( $dir ) || die "ERROR: Can not change to directory [$dir]\n";
mkdir( $base, 0755 ) unless -d $base;
@files_src = qw( CVSROOT-src/commitlogs/CVSROOT CVSROOT-src/commitlogs/bin
CVSROOT-src/commitlogs/etc CVSROOT-src/commitlogs/contrib
CVSROOT-src/commitlogs/gnu CVSROOT-src/commitlogs/games
CVSROOT-src/commitlogs/include CVSROOT-src/commitlogs/lib
CVSROOT-src/commitlogs/release CVSROOT-src/commitlogs/sys
CVSROOT-src/commitlogs/sbin CVSROOT-src/commitlogs/share
CVSROOT-src/commitlogs/tools CVSROOT-src/commitlogs/user
CVSROOT-src/commitlogs/usrbin CVSROOT-src/commitlogs/usrsbin );
@files_ports = qw( CVSROOT-ports/commitlogs/CVSROOT
CVSROOT-ports/commitlogs/ports );
$includes = '';
foreach $f ( @files_src ) {
$includes .= " -i $f";
}
foreach $f ( @files_ports ) {
$includes .= " -i $f";
}
open( LOG, ">$log");
my $resolver = Net::DNS::Resolver->new;
$resolver->usevc(1);
$resolver->udp_timeout(5);
$resolver->tcp_timeout(5);
$resolver->retrans(3);
$resolver->retry(2);
$resolver->persistent_tcp(1);
foreach $server ( @servers ) {
my $query = $resolver->query($server, 'A');
@ipaddr = @cname = ();
if( $query ) {
foreach $rr ($query->answer) {
if( $rr->type eq 'A' ) {
print LOG "$server => [A] ".$rr->address."\n";
push( @ipaddr, $rr->address );
}
elsif( $rr->type eq 'CNAME' ) {
print LOG "$server => [CNAME] ".$rr->cname."\n";
push( @cname, $rr->cname );
}
}
}
$ip = $ipaddr[0];
$ipaddr = join( '|', @ipaddr );
$cname = join( '|', @cname );
$ibase = "$base/$server";
mkdir( $ibase, 0755 ) unless -d $ibase;
mkdir( "$ibase/SRC", 0755 ) unless -d "$ibase/SRC";
$cmd = "$cvsup -h $ip -L 0 -b $ibase -r 0 $includes supfile";
$time_start = [gettimeofday];
system($cmd);
$elapsed = tv_interval( $time_start );
printf LOG ("$server => cvsup on $ip elapsed %.2fs\n", $time_elapsed);
unless( $? ) {
$mt_src = $mt_ports = 0;
foreach $f ( @files_src ) {
$t = (stat( "$ibase/SRC/$f" ))[9];
$mt_src = $t if $t > $mt_src;
}
foreach $f ( @files_ports ) {
$t = (stat( "$ibase/SRC/$f" ))[9];
$mt_ports = $t if $t > $mt_ports;
}
open( REC, ">$ibase/last-commit.txt" );
printf REC("$mt_src,$mt_ports,%.2f,$ipaddr,$cname",$elapsed);
close(REC);
printf LOG ("$server => SRC: %s\n",
strftime("%Y/%m/%d %H:%M:%S", localtime($mt_src)) );
printf LOG ("$server => PORTS: %s\n",
strftime("%Y/%m/%d %H:%M:%S", localtime($mt_ports)) );
}
}
close(LOG);
supfile:
*default prefix=SRC
*default release=cvs delete use-rel-suffix
*default compress
cvsroot-src
cvsroot-ports
*default prefix=SRC
*default release=cvs delete use-rel-suffix
*default compress
cvsroot-src
cvsroot-ports
cvsup.php
<style type="text/css">
td { font-size: 12px; vertical-align: top }
td.head { background: #FFFFC0 }
td.c { background: #E0E0FF }
td.red { background: #FFE0E0 }
td.green { background: #E0FFE0 }
</style>
<table border=1 cellspacing=0 cellpadding=2>
<tr><td class=head>Server Name</td><td class=head>IP</td>
<td class=head>CNAME</td><td class=head>latest commit of src</td>
<td class=head>latest commit of ports</td>
</tr>
<?
$dir = '/home/cvsup-monitor' ;
$servers = array (
'cvsup.tw.freebsd.org' , 'cvsup1.tw.freebsd.org' , 'cvsup2.tw.freebsd.org' ,
'cvsup3.tw.freebsd.org' , 'cvsup4.tw.freebsd.org' , 'cvsup5.tw.freebsd.org' ,
'cvsup6.tw.freebsd.org' , 'cvsup7.tw.freebsd.org' , 'cvsup8.tw.freebsd.org' ,
'cvsup9.tw.freebsd.org' , 'cvsup10.tw.freebsd.org' , 'cvsup11.tw.freebsd.org' ,
'cvsup12.tw.freebsd.org' , 'cvsup13.tw.freebsd.org' , 'cvsup14.tw.freebsd.org' ) ;
$check = time ( ) - 86400 ;
$time_format = '%Y/%m/%d %H:%M:%S' ;
$latest_src = $latest_ports = 0 ;
foreach ( $servers as $server ) {
$data = file_get_contents ( "$dir /base/$server /last-commit.txt" ) ;
$data = trim ( $data ) ;
if ( $data != '' ) {
$SERVER [ $server ] = explode ( ',' , $data ) ;
if ( $SERVER [ $server ] [ 0 ] > $latest_src )
$latest_src = $SERVER [ $server ] [ 0 ] ;
if ( $SERVER [ $server ] [ 1 ] > $latest_ports )
$latest_ports = $SERVER [ $server ] [ 1 ] ;
}
}
foreach ( $servers as $server ) {
if ( is_array ( $SERVER [ $server ] ) ) {
list ( $src , $ports , $elapsed , $ipaddr , $aliases ) = $SERVER [ $server ] ;
$ipaddr = str_replace ( '|' , '<br />' , $ipaddr ) ;
$aliases = str_replace ( '|' , '<br />' , $aliases ) ;
if ( $aliases == '' )
$aliases = ' ' ;
print "<tr>\n " ;
print " <td class=c>$server </td>\n " ;
print " <td class=c>$ipaddr </td>\n " ;
print " <td class=c>$aliases </td>\n " ;
if ( $src == $latest_src )
print " <td class=green>" ;
elseif ( $src < $check )
print " <td class=red>" ;
else
print " <td class=c>" ;
print strftime ( $time_format , $src ) . "</td>\n " ;
if ( $ports == $latest_ports )
print " <td class=green>" ;
elseif ( $ports < $check )
print " <td class=red>" ;
else
print " <td class=c>" ;
print strftime ( $time_format , $ports ) . "</td>\n " ;
# print " <td align=right>$elapsed s</td>\n";
print "</tr>\n " ;
}
}
?>
</table>
<style type="text/css">
td { font-size: 12px; vertical-align: top }
td.head { background: #FFFFC0 }
td.c { background: #E0E0FF }
td.red { background: #FFE0E0 }
td.green { background: #E0FFE0 }
</style>
<table border=1 cellspacing=0 cellpadding=2>
<tr><td class=head>Server Name</td><td class=head>IP</td>
<td class=head>CNAME</td><td class=head>latest commit of src</td>
<td class=head>latest commit of ports</td>
</tr>
<?
$dir = '/home/cvsup-monitor';
$servers = array(
'cvsup.tw.freebsd.org', 'cvsup1.tw.freebsd.org', 'cvsup2.tw.freebsd.org',
'cvsup3.tw.freebsd.org', 'cvsup4.tw.freebsd.org', 'cvsup5.tw.freebsd.org',
'cvsup6.tw.freebsd.org', 'cvsup7.tw.freebsd.org', 'cvsup8.tw.freebsd.org',
'cvsup9.tw.freebsd.org', 'cvsup10.tw.freebsd.org', 'cvsup11.tw.freebsd.org',
'cvsup12.tw.freebsd.org', 'cvsup13.tw.freebsd.org', 'cvsup14.tw.freebsd.org' );
$check = time() - 86400;
$time_format = '%Y/%m/%d %H:%M:%S';
$latest_src = $latest_ports = 0;
foreach( $servers as $server ) {
$data = file_get_contents("$dir/base/$server/last-commit.txt");
$data = trim($data);
if( $data != '' ) {
$SERVER[$server] = explode(',', $data);
if( $SERVER[$server][0] > $latest_src )
$latest_src = $SERVER[$server][0];
if( $SERVER[$server][1] > $latest_ports )
$latest_ports = $SERVER[$server][1];
}
}
foreach( $servers as $server ) {
if( is_array($SERVER[$server]) ) {
list( $src, $ports, $elapsed, $ipaddr, $aliases ) = $SERVER[$server];
$ipaddr = str_replace( '|', '<br />', $ipaddr );
$aliases = str_replace( '|', '<br />', $aliases );
if( $aliases == '' )
$aliases = ' ';
print "<tr>\n";
print " <td class=c>$server</td>\n";
print " <td class=c>$ipaddr</td>\n";
print " <td class=c>$aliases</td>\n";
if( $src == $latest_src )
print " <td class=green>";
elseif( $src < $check )
print " <td class=red>";
else
print " <td class=c>";
print strftime( $time_format, $src ) . "</td>\n";
if( $ports == $latest_ports )
print " <td class=green>";
elseif( $ports < $check )
print " <td class=red>";
else
print " <td class=c>";
print strftime( $time_format, $ports ) . "</td>\n";
# print " <td align=right>$elapsed s</td>\n";
print "</tr>\n";
}
}
?>
</table>