A GUI for ps(1) Built with Mozilla
One of the more powerful features of Linux is the simple way that new commands can be constructed using aliases, shell scripts and other textual tricks. These techniques rely on a command-line interface, but what if you need a tool with a GUI interface? Few techniques exist that are both easy to use and professional looking. This article discusses a promising technique that uses the Mozilla platform. It focuses on a rather hard but standard problem: how to display the hierarchical information delivered by the ps(1) command usefully. A recent version of Mozilla (at least 1.4) is required.
Numerous GUI toolkits are available for Linux, from Xt to Tcl/Tk. Tutorials for these kits usually start with a button example. That's very routine, so let's see it and move on. In Mozilla, GUIs are described using XML syntax. A document named button.xul that specifies a button looks like this:
<?xml version="1.0"?> <window xmlns="http://www.mozilla.org/keymaster/ ↪gatekeeper/there.is.only.xul"> <button label="Press Me"/> </window>
The unmanageably long string, http://www.mozilla.org/keymaster/gatekeeper/etc..., tells Mozilla this file isn't HTML. It's instead XUL, a GUI description language that is Mozilla-specific and a dialect of XML. Make the button's window appear with this command:
mozilla -chrome button.xul
This example is simple and not worth dwelling on, although there's a lot going on even for a simple button. A ps(1) display is a far more ambitious goal, so let's leap forward.
Instead of the simple <button> widget, one of Mozilla and XUL's bigger guns is required, the <tree> widget. Some coding also is required and a lot more XML. Here, the focus is on fast development, not on seamless perfection. The coding part comes first.
To begin, ps(1) does the initial data gathering. Listing 1 shows the file psdata.ksh, with mode 777.
Listing 1. A Command-Line Wrapper for ps(1)
#!/bin/ksh export COLUMNS=300 ps h -ew -o '%p,%P,%C,%x,%z,%G,%n,%U,%a' \ > /tmp/psdata
The output holds all the interesting fields, comma-separated with no header line. Mandatory components are PID and PPID; the rest are optional but informative fields, such as COMMAND. That's all traditional Linux requires.
cd mozilla ./configure --disable-debug make make install
Debug versions are slow and have messy diagnostics; although harmless, they're avoided here. The build takes an hour-plus to finish and requires up to 1GB of space. The resulting binaries are located in mozilla/dist/bin. They can be run from that directory or from anywhere if the MOZILLA_FIVE_HOME and LD_LIBRARY_PATH environment variables are set and exported to that directory's absolute path. Now all the required binaries and shell scripts are available.
XPCOM is an implementation of Microsoft's COM, and it works portably on Linux/UNIX, Windows and Macintosh. It's restricted to a single process at the moment; there's no DCOM. XPCOM/COM is the fastest way to add new functionality to a scripting environment. It hooks up a compiled (say C or C++) object to an object reference in the scripting language. The nearest Perl equivalent is XM, but XPCOM does not require the re-linking that XM demands. Mozilla includes thousands of XPCOM objects by default. XPCOM is not some Java-like virtual machine at work, however. XPCOM objects usually are compiled code that runs efficiently on the bare metal.
It might seem strange to use Microsoft ideas on Linux, but XPCOM is fully open source and occupies a UNIX niche that has long been unaddressed: Linux/UNIX lacks a useful intermediate-sized component model. There have been CORBA and dynamic link libraries in the past, but those things are, respectively, very heavyweight and very lightweight. XPCOM is suited perfectly to middle-sized jobs, to application development of large binaries and to performance-critical work. Here it's simply extremely handy.
Use of XPCOM or COM typically includes many calls to the Windows QueryInterface() method. For the sake of Linux programmer sensibilities, this article uses createInstance() and getService() instead. QueryInterface() is available too.
Back to the code. Let's suck up the output of the ps(1) wrapper. Listing 2 shows how.
Getting Started with DevOps - Including New Data on IT Performance from Puppet Labs 2015 State of DevOps Report
August 27, 2015
12:00 PM CDT
DevOps represents a profound change from the way most IT departments have traditionally worked: from siloed teams and high-anxiety releases to everyone collaborating on uneventful and more frequent releases of higher-quality code. It doesn't matter how large or small an organization is, or even whether it's historically slow moving or risk averse — there are ways to adopt DevOps sanely, and get measurable results in just weeks.
Free to Linux Journal readers.Register Now!
- Django Models and Migrations
- Hacking a Safe with Bash
- Secure Server Deployments in Hostile Territory, Part II
- Huge Package Overhaul for Debian and Ubuntu
- The Controversy Behind Canonical's Intellectual Property Policy
- Home Automation with Raspberry Pi
- Shashlik - a Tasty New Android Simulator
- Embed Linux in Monitoring and Control Systems
- KDE Reveals Plasma Mobile
- diff -u: What's New in Kernel Development