Overvåk ledig diskplass med WMI
- Thursday, June 4th, 2009
- Skriv en kommentar
Med gjevne mellomrom går en eller annen disk på en eller annen server full, enten det er på grunn av ivrige logger, akkumulerende backups, voksende databaser eller noe helt annet. Uansett hva det er skaper det alltid problemer og tapt arbeidstid. Og med like gjevne mellomrom kan man høre meg klage, og si at nå må vi få på plass en løsning som kan overvåke diskene våre.
I dag bestemte jeg meg derimot for å ikke klage lengre, og 20 minutter senere hadde jeg laget en liten app som viste meg hvor mye ledig diskplass det var på serverne våre. Jeg ante ikke at det skulle være så enkelt.
Jeg begynte med å lage en liten dataklasse for å holde på informasjonen om en disk. Med hjelp av CodeRush tok det ikke mange sekunder eller tastetrykk. Her er DiskInfo-klassen:
8 public class DiskInfo
9 {
10 public string DriveLetter { get; set; }
11 public string VolumeName { get; set; }
12 public double Size { get; set; }
13 public double Free { get; set; }
14 public double PercentFree { get { return Free / Size; } }
15
16 public override string ToString()
17 {
18 return string.Format(“{0}{1}{2}{3}{4}”,
19 DriveLetter.PadRight(5),
20 VolumeName.PadRight(30),
21 Size.ToString(“###,###,###,###”).PadLeft(15),
22 Free.ToString(“###,###,###,###”).PadLeft(15),
23 PercentFree.ToString(“#0%”).PadLeft(10));
24 }
25 }
Og så trengte jeg noe som kunne hente ut informasjonen. Jeg har hørt mye om Windows Management Instrumentation (WMI), men aldri brukt det. Men en liten titt på System.Management namespacet avslørte at dette var akkurat det jeg behøvde:
Provides access to a rich set of management information and management events about the system, devices, and applications instrumented to the WMI infrastructure. Applications and services can query for interesting management information (such as how much free space is left on the disk, what is the current CPU utilization, which database a certain application is connected to, and much more)…
Jeg laget en kjapp liten command-klasse jeg valgte å kalle DiskInfoRetriever, som gitt navnet på en server henter ut informasjon om alle diskene på den maskinen:
9 using System.Management;
10
11 public class DiskInfoRetriever
12 {
13 private string _Server;
14
15 public List<DiskInfo> Items { get; set; }
16
17 public DiskInfoRetriever(string server)
18 {
19 _Server = FixServerName(server);
20 Items = new List<DiskInfo>();
21 }
22
23 private string FixServerName(string server)
24 {
25 return server.StartsWith(@”\\”)
26 ? server
27 : @”\\” + server + @”\root\cimv2″;
28 }
29
30 public void Execute()
31 {
32 var scope = new ManagementScope(_Server);
33 var query = new ObjectQuery(
34 “select FreeSpace, VolumeName, Size, Name “
35 + “from Win32_LogicalDisk where DriveType=3″);
36
37 var searcher = new ManagementObjectSearcher(scope, query);
38 var results = searcher.Get();
39
40 Items.Clear();
41
42 const int MEGABYTE = 1048576;
43 foreach (ManagementObject result in results)
44 {
45 Items.Add(new DiskInfo
46 {
47 DriveLetter = result[“Name”].ToString(),
48 VolumeName = result[“VolumeName”].ToString(),
49 Size = (double.Parse(result[“Size”].ToString()) / MEGABYTE),
50 Free = (double.Parse(result[“FreeSpace”].ToString()) / MEGABYTE),
51 });
52 }
53 }
54 }
Legg merke til den SQL-lignende spørringen på linje 34/35.
Nå gjenstod det bare å definere en liste med servere, initialisere en bunch med command-objekter, eksekvere dem, og loope gjennom resultatet for å skrive objektene til konsollet. Det gjorde jeg i Main:
10 static void Main(string[] args)
11 {
12 string[] servers = { “s1dev02″, “s1dev03″, “s1dev04″, “s1dev05″, “s1hvsql01″ };
13
14 try
15 {
16 foreach (var server in servers)
17 {
18 Console.WriteLine(server + “:”);
19
20 var diskInfoRetriever = new DiskInfoRetriever(server);
21 diskInfoRetriever.Execute();
22 diskInfoRetriever.Items.ForEach((disk) => Console.WriteLine(disk));
23
24 Console.WriteLine();
25 }
26 }
27 catch (Exception ex)
28 {
29 Console.ForegroundColor = ConsoleColor.Red;
30 Console.WriteLine(ex.ToString());
31 }
32
33 Console.WriteLine();
34 Console.WriteLine(“press ENTER to exit..”);
35 Console.ReadLine();
36 }
20 minutter tidligere hadde jeg ingen anelse om at jeg kom til å lage dette her, eller at det var så enkelt. For fremtiden skal jeg tenke meg om en ekstra gang før jeg klager over en manglende, teknisk løsning. Det meste lar seg løse, og mye er enklere enn man tror.
Neste steg blir å lage en ny modul til ContikiCenter som kan informere oss om når disker nærmer seg smertegrensen. Her er forresten resultatet av dagens kjøring:
Obs, det ser ut som om vi må foreta en liten opprydning på s1dev04. Jaja, det får vente til i morgen..
Kategorier: Jobb, Software/verktøy, Diverse prosjekter.
RSS feed for kommentarene.
Tilbaketråkk.



June 5th, 2009 at 12:41 am
Også lagrer du data fra kjøring til kjøring, og holder øye med hvor raskt disken fylles opp, ifall noen går bananas med logging eller lignende.
Cool løsning, må mekke
June 5th, 2009 at 9:51 am
Veldig bra eksempel!
Forslag til forbedring:
Installer som en service som går “ofte nok” + legg til varslig på epost / sms eller noe.
Eller kommer man nok til å glemme å sjekke ofte nok.
mvh
Sølve
June 5th, 2009 at 10:35 am
Bra forslag. Det vi derimot kommer til å gjøre er å legge til en liten modul på den applikasjonen vi har kjørende på skjermen alle går forbi hver morgen når de kommer på jobb. Om det er lite diskplass på en server vil den blinke rødt, og da skal det bli lagt merke til.
June 5th, 2009 at 12:53 pm
Et par kjekke linker for å komme igang med WMI programmering:
MSDN: WMI Reference
WMI Code Creator 1.0