Ubuntu 12.04 ^
Given the recent release of Ubuntu 12.04, I thought it was about time that I upgraded one of my machines to it so that I could make sure I could still work with it effectively.
You see, both my laptop and my desktop were on the previous long term support release, 10.04. These days I don’t have a lot of patience for upgrading things every 6 months so I’m glad that the LTS releases are supported for many years. But after 10.04 Ubuntu made a bold departure away from the GNOME desktop and onto Unity. Knowing that I would be forced to change the way I did many things I have been putting off trying Unity. No more putting it off.
Terminals, Terminals, Terminals, Terminals, Terminals, Terminals ^
Given what I do for a living it’s fair to say that the predominant applications running on any of my desktop machines are many instances of terminals running SSH to remote hosts. I try to automate and configuration manage the hell out of everything, but it’s hard to avoid having connections open to a bunch of different machines at any one time.
In 10.04 what I used to do was have a .desktop file for each host that I commonly log in to, something like:
Exec=urxvtc -T specialbrew -e ssh specialbrew.localnet
I’d then have a menu called “SSH” added to my top menu bar, with an entry for each of those files. This was quite nice as I could also have multiple levels of menu, thus segregating different classes of host, hosts I administer with different hats on, customers I do consulting work for, etc.
Unity’s Launchers ^
Sadly that all goes out of the window with Unity. For a start there is no top menu bar. You’ve got the launcher down the side where you can add the launcher for gnome-terminal, but if you click that launcher more than once all that happens is you get your first terminal window brought back to focus.
There’s an open bug report asking for ways to set different properties on launchers, but judging by the age it doesn’t seem to be much of a priority.
I haven’t got a clue about launchers in Unity but I had a quick read of some documentation and worked out how to add a launcher for urxvt (my preferred terminal as opposed to gnome-terminal), and how to put different options on it. For example:
$ cat ~/.local/share/applications/rxvt.desktop
Comment=Use the command line
[Desktop Action New]
Name=New Terminal (localhost)
Exec=/home/andy/bin/urxvtc -T stoli
[Desktop Action specialbrew]
Name=New Terminal (specialbrew)
Exec=/home/andy/bin/urxvtc -T specialbrew -e ssh specialbrew.localnet
[Desktop Action backup1]
Name=New Terminal (backup1)
Exec=/home/andy/bin/urxvtc -T backup1.bitfolk.com -e ssh backup1.bitfolk.com
Once you do something like that and get the icon locked on the Launcher, you can right click on it and be offered “localhost”, “specialbrew”, “backup1”, etc.
Okay that is workable, but it kind of sucks. That list will get huge, and it’s a flat list.
Lenses seem like a very powerful feature of Unity. When I was asking on IRC about how people handled this use case, someone suggested (sarcastically, I think!) that I needed to create a lens to view all my hosts.
I actually did have a look into it, and was initially rather put off by the task. Fortunately it seems that someone already had the idea of a lens that scrapes SSH hosts out of ~/.ssh/config and ~/.ssh/known_hosts.
The SSH Search Lens ^
After installing this, it worked pretty much as advertised. As noted in the README you do have to use “HashKnownHosts no” to take advantage of it being able to read ~/.ssh/known_hosts — some would consider that a security flaw. Rather than disabling known host hashing for all users, you can disable it just for yourself:
$ cat ~/.ssh/config
Note that it only re-parses the SSH configuration files when it starts, which means that if you SSH to somewhere new then it won’t be found in Dash Home until after you’ve logged out and in again (officially). I found that looking for the /usr/bin/python /opt/extras.ubuntu.com/unity-lens-sshsearch/unity-lens-sshsearch.py process and killing it would cause it to be restarted next time I went to Dash Home. That saves a logout/in (but might be Bad).
The current version is hardcoded to call gnome-terminal, and I wanted to change that. I edited /opt/extras.ubuntu.com/unity-lens-sshsearch/unity-lens-sshsearch.py and changed the following line:
TERMINAL_APP = 'gnome-terminal'
TERMINAL_APP = '/home/andy/bin/urxvtc'
(Yes, I compile rxvt-unicode from source and keep it in ~/bin. What of it? Wanna fight about it?)
After restarting the lens it failed to work. Nothing happened when clicking on the icons it found. It wasn’t sending anything to ~/.xsession-errors either.
In the end I had to strace it, only to find it was getting “permission denied” when trying to execute my TERMINAL_APP. What? I can execute it myself.
FFFFFUUUUUUUUUUUUUUUUU AppArmor ^
Yeah, unity-lens-sshsearch ships an AppArmor profile, /etc/apparmor.d/opt.extras.ubuntu.com.unity-lens-sshsearch.unity-lens-sshsearch.py to be exact. That specifies what it can execute, and it’s limited to gnome-terminal.
After adding the paths to my rxvt-unicode there (it’s pretty obvious how, if you look in the file) it was happy.
Deficiencies of the SSH Search Lens ^
So, obvious deficiences here:
- Have to log out or risk killing the process to get it to index newly-added entries.
- Hard-coded to gnome-terminal.
- Still limited in terms of configurability to <command>, <user>, <host> and <port>
- Still has a flat hierarchy — you’ve got a list of hosts that your search term will be matched against. Possibly greater knowledge of Lenses/Scopes could improve this.
- My rxvt-unicode doesn’t have a nice icon like gnome-terminal does! I’m guessing I will be able to fix this by reading up more about the Launcher.
- Would be nice if the stderr output of the lens went to ~/.xsession-errors like every other X application, instead of /dev/null that I note it is redirected to. I realise that ~/.xsession-errors tends to be known as “that multi-gigabyte file of garbage that no one ever looks at” but it’s marginally more useful than /dev/null!
But on the whole this is a fairly natural way for me to launch these SSH sessions — I can press the “super” key and start typing the host name and I’ll get a list of matching icons to click on.
Also even though I don’t know Python, the source of this lens seems quite readable so I may be able to improve it and/or make my own lenses in future.