Tento článek popisuje, jak lze získat co nejvíce informací o stavu systému z Java aplikace. Jsou zde zmíněny dva způsoby – závislé a nezávislé na operačním systému.

SIGAR API

Sigar (System Information Gatherer And Reporter) je knihovna od Hyperic, která poskytuje platformě nezávislé získávání informací o stavu systému jako např. informace o využití paměti, procesoru, disků, ale i síťových rozhraní. Přestože má každý operační systém rozdílný způsob získávání těchto informací, Sigar poskytuje jednotné API pro většinu OS. Jedinou podmínkou je přitomnost dll knihovny pro daný OS v adresáři, kde se nachází knihovna Sigar. Kompletní seznam podporovaných OS a distribucí naleznete na domovské stránce projektu http://support.hyperic.com/display/SIGAR/Home. Po stažení knihovny si můžeme vyzkoušet všechny implementované přikazy pomocí jakéhosi Shellu, který tato knihovna nabízí. Spustíme jar soubor s knihovnou (java –jar sigar-bin/lib/sigar.jar) a zobrazí se přikazová řádka shellu, kde po zadání přikazu help uvidíme všechny nabízené příkazy a jejich jednoduchý popis.

Práce s knihovnou SIGAR uvnitř Java aplikace

V aplikaci stačí pouze vytvořit instanci třídy Sigar a poté z ní získat informace, které požadujeme. To, jak získat informace reprezentující jednotlivé přikazy, zjistíme z ukázkových příkladů přiložených k balíku s knihovnou v adresáři bindings/java/examples. Každý příkaz, který knihovna podporuje, je zde zastoupen samostatnou třídou. Jako příklad zde uvedu získání informací o využití paměti ve formátu podobnému linuxovému příkazu free. Výstup je naformátován do HTML tabulky.


public class SystemInformations {

    private Sigar sigar;

    public SystemInformations() {
        sigar = new Sigar();
    }
    
    /**
     * Vrati hodnotu v MB.
     */
    private static Long format(long value) {
        return new Long(value / 1048576);
    }
    
    /**
     * Ziska informace o vyuziti pameti systemu.
     */
    public String getMemoryInfo() throws SigarException {
        StringBuffer result = new StringBuffer();
        Mem mem = sigar.getMem();
        Swap swap = sigar.getSwap();
        result.append("<table>");
        result.append("<tr><td></td><td>total</td><td>used</td><td>free</td></tr>");
        Object[] memRow = new Object[] {
            format(mem.getTotal()),
            format(mem.getUsed()),
            format(mem.getFree())
        };
        Object[] actualRow = new Object[] {
            format(mem.getActualUsed()),
            format(mem.getActualFree())
        };        
        Object[] swapRow = new Object[] {
            format(swap.getTotal()),
            format(swap.getUsed()),
            format(swap.getFree())
        };
        result.append("<tr><td>Mem:</td><td>" + memRow[0] + "MB&nbsp;</td><td>" + memRow[1]
            + "MB&nbsp;</td><td>" + memRow[2] + "MB&nbsp;</td></tr>");        
        //e.g. linux
        if ((mem.getUsed() != mem.getActualUsed()) || (mem.getFree() != mem.getActualFree())) {
            result.append("<tr><td>-/+ buffers/cache:</td><td>" + actualRow[0] + "MB&nbsp;</td><td>"
                + actualRow[1] + "MB&nbsp;</td><td></td></tr>");
        }
        result.append("<tr><td>Swap:</td><td>" + swapRow[0] + "MB&nbsp;</td><td>" + swapRow[1]
            + "MB&nbsp;</td><td>" + swapRow[2] + "MB&nbsp;</td></tr>");
        result.append("<tr><td>RAM:</td><td>" + mem.getRam() + "MB&nbsp;</td><td></td><td></td></tr>");
        result.append("</table>");
        return result.toString();
    }
}    


Logování specifických příkazů pro daný operační systém

Knihovna SIGAR poskytuje pouze omezené množství systémových informací. Pokud potřebujeme logovat některé specifické příkazy a předem víme, že naše aplikace poběží pouze na daném operačním systému, kde máme daný příkaz ověřený, můžeme tento příkaz spustit v dalším procesu a pomocí bufferovaného čtení zpracovat podle naší potřeby. Jako přiklad uvedu linuxový příkaz dstat pro zjištění využití systémových prostředků. Výstupem je seznam řádků, kde jeden řádek reprezentuje řádek na standardním výstupu, kdyby byl příkaz spuštěn klasicky z příkazové řádky.


/**
 * Ziska informace o vyuziti systemovych prostredku z prikazu dstat -C total -D sda -scdglmp.
 */
public List<string> getDstatCommand() {
    List</string><string> result = new ArrayList</string><string>();
    String s = null;
    try {
        Process p = Runtime.getRuntime().exec("dstat -C total -D sda -scdglmp 1 10");            
        BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
        while ((s = stdInput.readLine()) != null) {
            result.add(s);
        }

    } catch (IOException e) {
        logger.error("Pri zjistovani informaci z prikazu dstat -C total -D sda -scdglmp nastala chyba.");
    }
    return result;
}