Monday, May 25, 2009

Episode #40: Ed's Heresy

Ed opens up by speaking a bit of heresy:

Let me start by saying that I love the command line. I have stated publicly that I find it an incredibly powerful paradigm for interacting with computers. When I really get on a roll, I've even been known to say that the GUI was a mistake that humanity should have avoided.

That said, I'd like to utter a bit of heresy for this here command-line blog. Sometimes... just occasionally... every once and a while... I do something on my Windows box using a GUI. Some of the GUIs just make it easier to get things done. Others are useful so I can check to make sure a change I made at the command line had my desired effect.

So, what does this have to do with command-line kung fu? Well, I launch pretty much every GUI-based tool on my Windows box using the command line. The cmd.exe window is my main user interface, which I periodically use to launch ancillary GUI tools that act as helpers.

You see, launching Windows GUI tools from the command line helps to avoid the constant churn of Microsoft moving things from version to version. Rather than digging through Start-->Programs-->Accessories... or whatever, I just kick off the GUI from my command line.

Truth be told, my work flow is a synthesis of command-line and GUI, with cmd.exe doing about 70% of the work, assorted GUIs doing another 20%, and 10% for VBS or (increasingly) Powershell. I've memorized many of the most useful GUIs that can be launched from the command line. They essentially come in three forms: MSCs (Microsoft Controls), EXEs, and CPLs (Control Panel Tools). Here are my faves, each of which can be launched at the Windows command-line, so you won't have to dig through the Windows GUI ever again:

lusrmgr.msc = Local User Manager
eventvwr.msc = Event Viewer
services.msc = Services Controller
secpol.msc = Security Policy Editor - This one is really useful because it allows you to alter hundreds of registry key equivalents and other settings that would be a pain to do at the command-line.

taskmgr.exe = Task Manager
explorer.exe = Windows Explorer
regedit.exe = Registry Editor
mmc.exe = Generic "empty" Microsoft Management Console, into which I can Add/Remove Snap-ins to manage all kinds of other stuff
msconfig.exe = Microsoft Configuration, including autostart entries and services - Note that this one is not included in cmd.exe's PATH on Windows XP (it is in the PATH on Vista). You can invoke it on XP by running C:\windows\pchealth\helpctr\binaries\msconfig.exe
control.exe = Bring Up the overall Control Panel

wscui.cpl = Windows Security Center control
firewall.cpl = Windows Firewall Config GUI
wuaucpl.cpl
= Windows Automatic Update Configuration

If you'd like to see the other control panel piece parts, you can run:

C:\> dir c:\windows\system32\*.cpl


There are others beyond this list, but these are my trusty aids, extending my GUI. Of all of these, the ones I use most are secpol.msc (because of its access to hundreds of settings), msconfig.exe (as a quick configuration checker), eventvwr.msc (because Windows command-line tools for viewing events are kind of a pain), and good old regedit.exe (makes random adventures in the registry easier than with the reg command).

So, Hal and Paul... are there any GUI-based tools you find yourself launching from the command-line a lot? For Linux, Hal, is there a GUI tool you launch from the command-line because it's just easier to get a given task done in the GUI? And, surely Paul must launch GUIs from the Mac OS X command-line, given the platypus of an operating system he's saddled with. What say you, gentlemen?

Hal confesses:

Wow, I feel like this is an impromptu meeting of "GUI Users Anonymous" or something. As long as we're all testifying, I have to admit that I've always found both printer configuration and Samba configuration to be a huge hassle, and I will often end up using whatever GUIs happen to be available for configuring them.

Often I'll use the GUI to figure out a basic template for the configuration changes I need and then use command-line tools to replicate those configuration templates on other systems. While it's not always clear what configuration files the GUI might be tweaking, remember that you can use the trick from Episode #29 to find them: "touch /tmp/timestamp", make changes via the GUI, and then "find /etc -newer /tmp/timestamp" to find the changed files.

Similarly, there are a few GUIs in the Unix universe that actually try and teach you the command-line equivalents of tasks you're currently doing with the GUI. AIX enthusiasts will be familiar with SMIT-- a menu driven tool that also lets you see what it's actually doing under the covers. Another example would be the highly-useful NmapFE (now Zenmap) front-end for Nmap, which is a useful tool for driving Nmap from a GUI while simultaneously learning Nmap command-line flags.

These days a lot of new Linux users are experiencing Linux almost entirely via the GUI. While I think this is excellent from the perspective of driving new adoption, at some point it's helpful to start digging around "under the covers" and figure out what's happening in terms of the actual commands being executed. This turns out to be straightforward because typically the GUI configuration information is just stored in text files. If somebody shows you the basics of find and grep, you can actually do a huge amount of self-discovery.

For example, let's suppose you're a Ubuntu user like me and you're curious about what exactly is happening when you select the menu choice for "Home Folder" and the graphical file browser pops up. Way back in Episode #10 I showed you how to find the names of files that contain a particular string:

$ sudo find / -type f | sudo xargs grep -l 'Home Folder'
[...]
grep: /usr/share/acpi-support/NEC: No such file or directory
grep: Computers: No such file or directory
grep: International.config: No such file or directory
grep: /usr/share/acpi-support/Dell: No such file or directory
grep: Inc..config: No such file or directory
[...]

Huh? What's with all the error messages?

What's going on here is that the find command is emitting file names containing spaces-- "/usr/share/acpi-support/NEC Computers International.config" and ".../Dell Inc..config"-- which are being misinterpreted by xargs. The normal fix for this problem is to slightly adjust both commands:

$ sudo find / -type f -print0 | sudo xargs -0 grep -l 'Home Folder'

"find ... -print0" tells find to terminate its output with nulls (ASCII zero) instead of whitespace. Similarly, "xargs -0 ..." tells xargs to look for null-terminated input and don't treat white space in the incoming file names as special.

The above command is going to generate a ton of output and it may take a while to sort through everything and find the file that's actually relevant. On my Ubuntu system, the menu configuration files live in the /usr/share/applications directory:

$ less /usr/share/applications/nautilus-home.desktop
[Desktop Entry]
Encoding=UTF-8
Name=Home Folder
[...]
Exec=nautilus --no-desktop
Icon=user-home
Terminal=false
StartupNotify=true
Type=Application
Categories=GNOME;GTK;Core;
OnlyShowIn=GNOME;
[...]

The "Name=" parameter is the name that appears for the particular menu choice and the "Exec=" parameter shows you the command that's being invoked.

You could even put together a quick little bit of shell fu to output the value of "Exec=" for a given menu item:

$ awk -F= '/^Exec=/ {print $2}' \
`grep -l 'Name=Home Folder' /usr/share/applications/*`

nautilus --no-desktop

Here we're using "grep -l ..." to output the file name that matches the "Name=" parameter we're searching for. We then use backticks to make the file name output of the grep command be the argument that our awk statement works on. The awk specifies "-F=" to split lines on "=" instead of whitespace, then looks for the line that starts with "Exec=" and prints the stuff after the "=". You could easily turn this into a shell script or alias if you find yourself doing it frequently.