isometry

SSH with smart hostname autocompletion

67 posts in this topic

This one has been at the top of my Alfred wishlist since I downloaded my first Alfred v0.whatever beta: a workflow to open an ssh session (using the default ssh: protocol handler) with "smart" hostname autocompletion (based on ~/.ssh/config, ~/.ssh/known_hosts, /etc/hosts and Bonjour).

 

NB: for Bonjour discovery to work, you'll need to install the pybonjour module, e.g. `sudo /usr/bin/easy_install pybonjour`. 

 

Comments and suggestions welcome.

 

Download (v1.3)

 

Source on github

 

Robin

 

Updates

2013-03-14 00:00, v0.4: rudimentary fuzzy matching, to pull entries from /etc/hosts as well as ~/.ssh/known_hosts, and to deal with usernames properly.

2013-03-14 09:00, v0.5: smart host matching.

2013-03-14 22:45, v0.6: ~/.ssh/config and Bonjour discovery (including full BTMM support), and improved error handling.

2013-03-14 23:00, v0.61: explicitly removed 'broadcasthost' from the list of possible matches.

2013-03-15 00:30, v0.7: match '.' as '.'

2013-03-16 10:45, v0.8: refactored code and add tab autocompletion.

2013-03-16 13:30, v0.9: oops - the last update broke the workflow if you didn't have pybonjour installed; fixed. Continued refactoring: now using nikipore's alfred-python module.

2013-03-16 14:15, v0.10: further refactoring to break core functionality out into a dedicated module (enabling module compilation). Combined with caching of file parsing results this should deliver significantly enhanced performance (not that it was slow before).

2013-03-16 23:00, v1.0: complete refactoring and move release to github. New feature: display the source(s) of each suggested completion. This ought to be the last update for a while.

2013-03-16 08:40, v1.1: fixed breakage when either of ~/.ssh/config or ~/.ssh/known_hosts didn't exist.

2016-06-02 21:00, v1.3: fixed path to Alfred cache (thanks @okapi!).

Edited by isometry

Share this post


Link to post

This is wonderful.  I wonder if there could also be a way to specify a user... for example if I had an IP ending in .123 to which I want to connect, if I could type

 

ssh another-user 123  to generate   ssh another-user@192.122.122.123   or ssh 192.122.122.123 -l another-user ?

Share this post


Link to post

 

For your iTerm2 ssh: protocol handler profile, you can set the Name to $$HOST$$ and the Command to $$ to have it automatically set the window/tab title to the name of the host you're connecting to (including username, if specified) and save it spawning a copy of your default shell to simply run ssh.

 

 

Update 2013-08-12: Changed the recommended Command to simply $$ from ssh $$HOST$$. The latter incorrectly threw away the username if specified.

Edited by isometry

Share this post


Link to post

This is wonderful.  I wonder if there could also be a way to specify a user... for example if I had an IP ending in .123 to which I want to connect, if I could type

 

ssh another-user 123  to generate   ssh another-user@192.122.122.123   or ssh 192.122.122.123 -l another-user ?

 

Simply include the username in your host specification: it does "the right thing". I.e. `ssh user@host` or `ssh user@123`

Share this post


Link to post

Simply include the username in your host specification: it does "the right thing". I.e. `ssh user@host` or `ssh user@123`

Works like a champ - can't believe I didn't just try it...  Thanks!

Share this post


Link to post

I added support for reading user-defined hosts from ~/.ssh/config: http://paste.ubuntu.com/5614867/

 

(can't believe I didn't think to write this workflow, thanks very much!)

 

I had considered adding parsing of .ssh/config, but mine contains a lot of wildcards and other such cruft. Once you've connected to a host once, it's in your .ssh/known_hosts and good-to-go evermore. Does this addition make your workflow noticeably better?

 

NB: I've already added Bonjour autocompletion to my development version, including full Back to My Mac support. Will post soon.

Share this post


Link to post

I had considered adding parsing of .ssh/config, but mine contains a lot of wildcards and other such cruft. Once you've connected to a host once, it's in your .ssh/known_hosts and good-to-go evermore. Does this addition make your workflow noticeably better?

 

NB: I've already added Bonjour autocompletion to my development version, including full Back to My Mac support. Will post soon.

 

Good point about the wildcards, my patch is not doing enough to exclude them. Should be sufficient to skip any line with * or ? in it.

 

For me the killer feature of entries in the ssh config is that I can fake the name to combine various settings and then set the real host with the Hostname option. In that situation, the Host does not end up in known_hosts.

 

Love the sound of Bonjour and BTMM support :)

Share this post


Link to post

Good point about the wildcards, my patch is not doing enough to exclude them. Should be sufficient to skip any line with * or ? in it.

 

For me the killer feature of entries in the ssh config is that I can fake the name to combine various settings and then set the real host with the Hostname option. In that situation, the Host does not end up in known_hosts.

 

Love the sound of Bonjour and BTMM support :)

 

I like it.

 

I've just posted v0.6 which includes a variant of your patch (deals with all the ssh_config pattern characters) and Bonjour discovery, along with much better error handling (e.g. complete failure if you didn't actually have a ~/.ssh/known_hosts or ~/.ssh/config file). Enjoy!

Share this post


Link to post

I like it.

 

I've just posted v0.6 which includes a variant of your patch (deals with all the ssh_config pattern characters) and Bonjour discovery, along with much better error handling (e.g. complete failure if you didn't actually have a ~/.ssh/known_hosts or ~/.ssh/config file). Enjoy!

 

Very nice. I noticed that "broadcasthost" shows up if I happen to type any of its characters. I'd not come across this before in OSX, but it appears to be an alias to 255.255.255.255, so is probably worth filtering out at some point :)

Share this post


Link to post

Very nice. I noticed that "broadcasthost" shows up if I happen to type any of its characters. I'd not come across this before in OSX, but it appears to be an alias to 255.255.255.255, so is probably worth filtering out at some point :)

 

Indeed. I was trying to avoid the need to special case, but it is ugly… I've updated to v0.61.

Share this post


Link to post

Cool! I've got a suggestion: When you're a heavy SSH user, it may become difficult to tell local Terminal windows and the various remote Terminal windows apart because they all have the same color theme. Plus, one sometimes wants to tunnel a port or three, or the target port isn't 22. For that reason, I establish my SSH sessions via .terminal files which I can also find via Alfred. These are basically .plist files with another file extension (this one I use to tunnel VNC access):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>BackgroundColor</key>
	<data>
	YnBsaXN0MDDUAQIDBAUGFRZYJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3AS
	AAGGoKMHCA9VJG51bGzTCQoLDA0OViRjbGFzc1xOU0NvbG9yU3BhY2VVTlNSR0KAAhAB
	RjAgMCAwANIQERITWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNDb2xvcqISFFhOU09iamVj
	dF8QD05TS2V5ZWRBcmNoaXZlctEXGFRyb290gAEIERojLTI3O0FIT1xiZGZtcn2GjpGa
	rK+0AAAAAAAAAQEAAAAAAAAAGQAAAAAAAAAAAAAAAAAAALY=
	</data>
	<key>CommandString</key>
        <string>ssh me@somewhere.net -L5900:localhost:5900</string> 
	<key>CursorBlink</key>
	<true/>
	<key>CursorColor</key>
	<data>
	YnBsaXN0MDDUAQIDBAUGICFYJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3AS
	AAGGoKYHCBMUFRpVJG51bGzVCQoLDA0ODxAREl1OU0NhdGFsb2dOYW1lViRjbGFzc1tO
	U0NvbG9yTmFtZVxOU0NvbG9yU3BhY2VXTlNDb2xvcoACgAWAAxAGgARWU3lzdGVtXxAY
	ZGlzYWJsZWRDb250cm9sVGV4dENvbG9y0woMFg8YGVdOU1doaXRlgAUQA00wLjMzMzMz
	MzMzMzMA0hscHR5aJGNsYXNzbmFtZVgkY2xhc3Nlc1dOU0NvbG9yoh0fWE5TT2JqZWN0
	XxAPTlNLZXllZEFyY2hpdmVy0SIjVHJvb3SAAQAIABEAGgAjAC0AMgA3AD4ARABPAF0A
	ZABwAH0AhQCHAIkAiwCNAI8AlgCxALgAwADCAMQA0gDXAOIA6wDzAPYA/wERARQBGQAA
	AAAAAAIBAAAAAAAAACQAAAAAAAAAAAAAAAAAAAEb
	</data>
	<key>CursorType</key>
	<integer>1</integer>
	<key>Font</key>
	<data>
	YnBsaXN0MDDUAQIDBAUGGBlYJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3AS
	AAGGoKQHCBESVSRudWxs1AkKCwwNDg8QViRjbGFzc1ZOU05hbWVWTlNTaXplWE5TZkZs
	YWdzgAOAAiNAKAAAAAAAABAQXU1lbmxvLVJlZ3VsYXLSExQVFlokY2xhc3NuYW1lWCRj
	bGFzc2VzVk5TRm9udKIVF1hOU09iamVjdF8QD05TS2V5ZWRBcmNoaXZlctEaG1Ryb290
	gAEIERojLTI3PEJLUllgaWttdniGi5afpqmyxMfMAAAAAAAAAQEAAAAAAAAAHAAAAAAA
	AAAAAAAAAAAAAM4=
	</data>
	<key>FontAntialias</key>
	<true/>
	<key>FontWidthSpacing</key>
	<real>1.004032258064516</real>
	<key>ProfileCurrentVersion</key>
	<real>2.0099999999999998</real>
	<key>RunCommandAsShell</key>
	<true/>
	<key>SelectionColor</key>
	<data>
	YnBsaXN0MDDUAQIDBAUGICFYJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3AS
	AAGGoKYHCBMUFRpVJG51bGzVCQoLDA0ODxAREl1OU0NhdGFsb2dOYW1lViRjbGFzc1tO
	U0NvbG9yTmFtZVxOU0NvbG9yU3BhY2VXTlNDb2xvcoACgAWAAxAGgARWU3lzdGVtXxAY
	ZGlzYWJsZWRDb250cm9sVGV4dENvbG9y0woMFg8YGVdOU1doaXRlgAUQA00wLjMzMzMz
	MzMzMzMA0hscHR5aJGNsYXNzbmFtZVgkY2xhc3Nlc1dOU0NvbG9yoh0fWE5TT2JqZWN0
	XxAPTlNLZXllZEFyY2hpdmVy0SIjVHJvb3SAAQAIABEAGgAjAC0AMgA3AD4ARABPAF0A
	ZABwAH0AhQCHAIkAiwCNAI8AlgCxALgAwADCAMQA0gDXAOIA6wDzAPYA/wERARQBGQAA
	AAAAAAIBAAAAAAAAACQAAAAAAAAAAAAAAAAAAAEb
	</data>
	<key>ShowActiveProcessInTitle</key>
	<false/>
	<key>ShowCommandKeyInTitle</key>
	<false/>
	<key>ShowShellCommandInTitle</key>
	<false/>
	<key>ShowTTYNameInTitle</key>
	<false/>
	<key>ShowWindowSettingsNameInTitle</key>
	<true/>
	<key>TextBoldColor</key>
	<data>
	YnBsaXN0MDDUAQIDBAUGICFYJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3AS
	AAGGoKYHCBMUFRpVJG51bGzVCQoLDA0ODxAREl1OU0NhdGFsb2dOYW1lViRjbGFzc1tO
	U0NvbG9yTmFtZVxOU0NvbG9yU3BhY2VXTlNDb2xvcoACgAWAAxAGgARWU3lzdGVtXxAa
	Y29udHJvbExpZ2h0SGlnaGxpZ2h0Q29sb3LTCgwWDxgZV05TV2hpdGWABRADQjEA0hsc
	HR5aJGNsYXNzbmFtZVgkY2xhc3Nlc1dOU0NvbG9yoh0fWE5TT2JqZWN0XxAPTlNLZXll
	ZEFyY2hpdmVy0SIjVHJvb3SAAQAIABEAGgAjAC0AMgA3AD4ARABPAF0AZABwAH0AhQCH
	AIkAiwCNAI8AlgCzALoAwgDEAMYAyQDOANkA4gDqAO0A9gEIAQsBEAAAAAAAAAIBAAAA
	AAAAACQAAAAAAAAAAAAAAAAAAAES
	</data>
	<key>TextColor</key>
	<data>
	YnBsaXN0MDDUAQIDBAUGICFYJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3AS
	AAGGoKYHCBMUFRpVJG51bGzVCQoLDA0ODxAREl1OU0NhdGFsb2dOYW1lViRjbGFzc1tO
	U0NvbG9yTmFtZVxOU0NvbG9yU3BhY2VXTlNDb2xvcoACgAWAAxAGgARWU3lzdGVtWWdy
	aWRDb2xvctMKDBYPGBlXTlNXaGl0ZYAFEANEMC41ANIbHB0eWiRjbGFzc25hbWVYJGNs
	YXNzZXNXTlNDb2xvcqIdH1hOU09iamVjdF8QD05TS2V5ZWRBcmNoaXZlctEiI1Ryb290
	gAEACAARABoAIwAtADIANwA+AEQATwBdAGQAcAB9AIUAhwCJAIsAjQCPAJYAoACnAK8A
	sQCzALgAvQDIANEA2QDcAOUA9wD6AP8AAAAAAAACAQAAAAAAAAAkAAAAAAAAAAAAAAAA
	AAABAQ==
	</data>
	<key>UseBoldFonts</key>
	<false/>
	<key>UseBrightBold</key>
	<true/>
	<key>columnCount</key>
	<integer>140</integer>
	<key>name</key>
	<string>Terminal Settings</string>
	<key>rowCount</key>
	<integer>40</integer>
	<key>shellExitAction</key>
	<integer>0</integer>
	<key>type</key>
	<string>Window Settings</string>
</dict>
</plist>

So what I'm suggesting is the following: Why not put a default.terminal template in the workflow folder having a tag

 

<key>CommandString</key>
<string>ssh %(address)s</string>

 

Then write a copy of this file for each user and host to the non-volatile work folder and pass the file name to Alfred? Then, a user has various places to tweak the settings per connection.

 

I can also implement that if you like.

Share this post


Link to post

nikipore,

 

Your suggestion has its merits, though as described I believe it would be best implemented in a different workflow. This one attempts to be independent of the user's chosen terminal emulator by exploiting the ssh: protocol handler. As such, it supports not just Terminal.app but also iTerm.app, iTerm2.app and any others I don't have personal familiarity with.

 

Having said that, I do like the idea of a workflow to support management of background ssh tunnels, so I may look at that :-)


Robin

Share this post


Link to post

FYI - I'm geting the following error when trying to download from your droplr link.

AccessDeniedAccess denied

 

Peculiar - it's reporting 190 downloads of the latest version. Anyway, I've just updated to v0.8 with a refactoring of the code and the addition of tab autocompletion.

Share this post


Link to post

The workflow has been updated to v1.0: finalising(?) the code refactoring, moving the binary to github, and adding source attribution for each suggested hostname completion.

Share this post


Link to post

Thanks for the hard work, this looks like an awesome extension, and one of the reasons why I have the powerpack :) Unfortunately I can't get it to work on my macbook, with Iterm2. I already had Iterm2 as default Terminal, but when I type the name of a host I just get 'Please wait, matching host..' and no other output. Any thoughts how I can debug / fix this? 

Share this post


Link to post

Thanks for the hard work, this looks like an awesome extension, and one of the reasons why I have the powerpack :) Unfortunately I can't get it to work on my macbook, with Iterm2. I already had Iterm2 as default Terminal, but when I type the name of a host I just get 'Please wait, matching host..' and no other output. Any thoughts how I can debug / fix this? 

 

Are you running the latest version from GitHub? v0.9 was badly broken if you didn't have pybonjour installed (which you probably don't).

 

Is your ~/.ssh/known_hosts file hashed?

 

If you're comfortable running the workflow via the console, that would be most informative. Change to the workflow's directory (e.g. Alfred.alfredpreferences/workflows/user.workflow.E2B2A958-21D2-42ED-B6DF-06AF15C6A201 - the GUID may be different, find it via the "Open workflow folder" button when you double click the Script Filter object), and manually fire off the workflow: /usr/bin/python -c "from alfredssh import complete; complete('com')" (where 'com' is a sample hostname you'd expect to return something).  Assuming this raises an error, the output should pinpoint the problem.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now