10 Jul 2008

Call for (Capistrano) Links

Posted by Jamis on Thursday, July 10

Tyler Bird, the director of the Capistrano documentation effort, has begun collecting links about Capistrano, to build a centralized de.licio.us account that people can use to find cap-related info around the web. You can read more about it on the capify.org/news site.

Posted in Redirect | 4 comments

07 Jul 2008

Online Capistrano Tutorial Session

Posted by Jamis on Monday, July 7

Today I’m pleased to announce the first online Capistrano tutorial session. It will be held via Campfire on July 15 at 7pm MDT, focusing on Capistrano basics for Rails deployment. The session will accomodate only ten people. For all details, read up at capify.org:

http://www.capify.org/2008/7/6/online-capistrano-tutorial-session

If this proves popular enough, and if the format works out well, I’ll consider hosting more of these on more advanced topics.

Posted in Announcements | 2 comments

28 Jun 2008

Capistrano 2.4.3

Posted by Jamis on Saturday, June 28

Capistrano 2.4.3 is now available!

gem install capistrano

This is a maintenance release. The changes since 2.4.0 include:

  • In 2.4.0 and earlier, port settings in ssh_config files were not honored by Capistrano. 2.4.3 will now honor those settings.
  • The capture() helper no longer raises an exception if stderr text is received, but instead emits a warning.

Please report bugs to the Capistrano bug tracker at Lighthouse:

http://capistrano.lighthouseapp.com/projects/8716/tickets

Patches should be generated against the latest version of the code at GitHub:

http://github.com/jamis/capistrano

You may submit patches via email, as submissions to the Capistrano bug tracker, or as GitHub pull-requests.

Posted in Announcements | 1 comment

Net::SSH 2.0.3

Posted by Jamis on Saturday, June 28

Net::SSH 2.0.3 is now available!

gem install net-ssh

This is a maintenance release that fixes the following issues:

  • Net::SSH 2.0.2 and earlier wouldn’t work with Mocana SSH and a few other esoteric SSH servers commonly used on routers and other hardware. (Net::SSH truncated the server’s identity string at the first space, rather than at the end of the line as required by the specification, causing subsequent algorithm negotiations to fail.) 2.0.3 now preserves the entire identity string as reported by the remote server.
  • Malformed entries in ssh_config files are silently ignored now.
  • Entries in ssh_config files that are delimited with equals-signs are now parsed correctly.
  • The NameError raised when a forwarded port request could not be satisfied now raises the correct exception.
  • Net::SSH::Version is now Comparable, so you can test two version objects using comparison operators.

Please report bugs to the bug tracker for net-ssh on rubyforge:

http://rubyforge.org/tracker/?atid=1123&group_id=274&func=browse

If you have a patch you want to submit, please make sure to create it against the latest version of the code in the Net::SSH repository on GitHub:

http://github.com/jamis/net-ssh/commits/master

Patches may be submitted via email, as GitHub pull-requests, or as posts to the net-ssh tracker on rubyforge.

Posted in Announcements | 1 comment

13 Jun 2008

Capistrano 2.4.0

Posted by Jamis on Friday, June 13

Capistrano 2.4.0 is now available.

gem install capistrano

Report bugs to Capistrano’s Lighthouse project. And if you have some ideas for patches, please patch against the code at Capistrano’s GitHub repository.

Here’s the skinny on 2.4.0:

death to “git fetch --tags“

You git users out there will be pleased to learn that this release will no longer do “git fetch --tags”, meaning your git-based deploys will finally work again. Sorry that took so long to fix. It was really ridiculously simple. :(

cap -d

Mark Imbriaco added a debug switch for enabling conditional execution of commands. This is fantastic for debugging and testing tasks, since you can basically step through your tasks and approve or deny each remote command as it is executed. Just give cap the “-d” switch to enable this.

New and improved sudo helper

No, really. This time I mean it. I pulled the version of sudo introduced in 2.3.0 (where each sudo command was wrapped in an explicit sh invocation), and put it back almost exactly as it was. However, if you call sudo without a command to execute, it will instead return the sudo command to use. On top of that, if the run() helper detects that you’re using sudo, it will listen for password prompts. So you can now do arbitrarily complex sudo commands like this:

1
run "if [ -d /some/directory ]; then #{sudo} chmod -R g+w /some/directory; fi"

In other words, just dump the sudo() call into your command as an interpolated value, and the real sudo command gets substituted. You can pass options to it as well:

1
run "#{sudo :as => "bob"} something"

And, naturally, the original sudo() syntax we all know and love remains as before:

sudo "something", :as => "bob" 

The deployment recipes themselves have been updated to use this new syntax, as needed.

:runner vs. :admin_runner

Some cappers have noted that having deploy:setup and deploy:cleanup run as the :runner user messed up their carefully crafted permissions. I agreed that this was a problem. With this release, deploy:start, deploy:stop, and deploy:restart all continue to use the :runner user when sudoing, but deploy:setup and deploy:cleanup will use the :admin_runner user. The :admin_runner variable is unset, by default, meaning those tasks will sudo as root, but if you want them to run as :runner, just do “set :admin_runner, runner”.

deploy:upload with globs

You can now specify glob patterns with deploy:upload:

1
$ cap deploy:upload FILES="config/apache/*.conf" 

As before, you can also specify entire folders to upload, but now the upload is being done via the upload() helper (introduced in 2.3.0) so the behavior is more standardized.

before/after hooks use well-defined server scope

Prior to this release, if you defined a before hook using a block, the block would be executed within the same server scope as the original task that invoked task that this hook was attached to. (whew!)

In other words:

1
2
3
4
5
6
7
8
9
10
11
12
task :first, :roles => :app do 
  # ... 
  second 
end 

task :second, :roles => :db do 
  # ... 
end 

before :second do 
  # ... 
end 

Prior to this release, when “first” calls “second”, the before hook at the bottom would get called, but it would get called with the :roles => :app server constraint active, instead of :roles => :db. This preview release makes those hooks use the server scope of the task they are attached to.

host reported correctly from SCM output

Prior to this release, when any output was processed by the :checkout, :export, or :remote_cache strategies, you’d not be able to tell what host the output was from (it’d just be prefixed [err] or [out]). With this release, that output is correctly tagged with the host that generated it, making it easier to troubleshoot issues with SCM command execution.

Disable asset timestamp normalization

Some SCM’s give you the option of forcing the modification times of files that are being checked out to be the time that they were last modified in the repository. If your SCM gives you that capability, and if you enable it (however that works in your SCM), then you don’t need the massive touch command that Capistrano’s default deployment tasks run on each deploy, which is cap’s way of forcing all assets on all of your servers to have the same timestamp.

To disable Capistrano’s default timestamp normalization step, just set the :normalize_asset_timestamps variable to false:

1
set :normalize_asset_timestamps, false

You could also do this if you are deploying to a single server only. Note, though, that if you do this when deploying to multiple servers, and you haven’t configured your SCM to set the timestamps on the files on checkout, then Rails may use inconsistent timestamps on the assets, causing caching of your assets to fail and resulting in longer load times for your users.

Other lesser fixes, straight from the CHANGELOG

  • Make git SCM honor the :scm_verbose option [Jamis Buck]
  • Don’t follow symlinks when using :copy_cache [Jamis Buck]
  • If :mode is given to upload() helper, do a chmod after to set the mode [Jamis Buck]
  • Fix load_from_file method for windows users [Neil Wilson]
  • Display a deprecation error if a remote git branch is specified [Tim Harper]
  • Make set(:default_shell, false) work for not using a shell on a per-command basis [Ryan McGeary]
  • Use upload() instead of put() with the copy strategy [Jamis Buck]
  • Improved test coverage [Ryan McGeary]
  • Fixed “coverage” take task [Ryan McGeary]
  • Fix deploy:pending when using git SCM [Ryan McGeary]
  • Make sure deploy:check works with :none scm (which has no default command) [Jamis Buck]

Posted in Announcements | 20 comments

02 May 2008

Capistrano 2.3.0

Posted by Jamis on Friday, May 2

On February 16 I set myself to travel a path that I hoped would eventually help me deal with the project overload I was feeling. Today I get to release Capistrano 2.3, which is very near to the end of that path!

gem install capistrano

Capistrano 2.3 is primarily significant in that it switches to the new Net::SSH v2 library, which is faster and slimmer than the older Net::SSH v1 library. It also pulls in Net::SFTP v2, and the new Net::SSH::Gateway and Net::SCP libraries.

In addition to that, cap 2.3 adds several exciting (if I do say so myself) new features, and a few bug fixes that had lingered for far too long.

FEATURE: The :copy strategy has been significantly improved. Instead of doing a blind checkout/export, archiving the result, and copying it over, you can specify that a local cached copy of your repository should be used. If the cached copy does not exist, it is created (via a checkout), otherwise it is simply updated (a much faster operation than a checkout, typically). This functions much like the :remote_cache strategy, but locally. To use this, simply set the :copy_cache variable to true:

1
2
set :deploy_via, :copy
set :copy_cache, true

By default, the cached copy will be in your machine’s temporary directory (/tmp, for example), but you can specify your own location by setting :copy_cache to the desired path:

1
2
set :deploy_via, :copy
set :copy_cache, "/u/caches/#{application}"

But wait! There’s more! Suppose you have certain files that you don’t want to deploy, like photoshop files or your .git directory. You can set the :copy_exclude variable to a file glob (or an array of globs):

1
2
3
set :deploy_via, :copy
set :copy_cache, true
set :copy_exclude, [".git", "materials"]

This should make your deploys faster than ever, especially using a tip I hope to share in the next day or two that uses this in conjunction with some vendor/rails symlinking.

FEATURE: Even though I strenuously believe it is a mistake to deploy anything that is not under source control, I’ve finally caved and added a dumb :none SCM module. It can be used to deploy a specific directory if used with the :copy strategy:

1
2
3
set :repository, "."
set :scm, :none
set :deploy_via, :copy

Again, there are very, very few cases when I think use of this technique is justified, but because I ran into one myself a month ago, I decided it was worth adding.

FEATURE: Support was added for “depend :remote, file” to test for the existence of a specific file:


depend :remote, "/etc/syslog.conf"

This is used in conjunction with the deploy:check task.

FEATURE: You can specify ssh_options per-server, now, simply by giving an :ssh_options key and corresponding hash with the server definition:


role "some.host", :ssh_options => { :keys => "/path/to/key" }

FEATURE: There are two new file transfer helpers, upload and download, which are much more powerful and resource-friendly than the old ‘put’ and ‘get’ helpers. You can use upload and download to transfer single files, or entire directory trees:

1
2
upload "/local/file", "/remote/file"
download "/remote/file", "/local/file"

This will transfer to or from all active servers, which is particular tricky when using the download helper, since it will download the file simultaneously from all active hosts. To make this work, you need to make sure each is downloaded to a different location:

1
2
Dir.mkdir("destination")
download "/remote/file", "destination/file-$CAPISTRANO:HOST$"

The above will download the file from each host to a file on the local host, where the local file includes the name of the source host. Tricky!

Also, you can now specify that you want to upload or download via SCP instead of SFTP:

1
2
upload "local", "remote", :via => :scp
download "remote", "local", :via => :scp

The default is :sftp.

The less exciting (but still mildly titillating) things are the bug fixes and pleasure-enhancing behavioral changes:

  • The default run options are now mixed into the command options when executing a command from the capistrano shell.
  • The git SCM now uses git-ls-remote instead of git-rev-parse to resolve the revision of the checkout.
  • A trivial export method has been added to the git SCM.
  • The git SCM will include tags when it fetches.`
  • The sudo() helper now works nicely with complex and chained commands.
  • The deploy:setup task will now use sudo if :use_sudo is true (the default)

So, have at it! Remember to report bugs to http://capistrano.lighthouseapp.com. And patches are always welcome via git—just fork the capistrano repository at git://github.com/jamis/capistrano.git (thanks GitHub!).

Cheers!

Posted in Announcements | 48 comments

Net::SSH 2.0 (and friends)

Posted by Jamis on Friday, May 2

At last! Net::SSH 2.0 is available! Also available are Net::SFTP 2.0, Net::SCP 1.0, Net::SSH::Gateway 1.0, and Net::SSH::Multi 1.0.

1
2
3
4
5
$ gem install net-ssh \
  net-sftp \
  net-scp \
  net-ssh-gateway \
  net-ssh-multi

All of these Ruby libraries are for communicating with remote servers via the SSH protocol in different ways.

Net::SSH and Net::SFTP are both significant upgrades from their previous incarnations; if you have used either library in the past, you’ll want to read the documentation (Net::SSH, Net::SFTP). The Net::SSH API is still fairly similar to the way it was before, but the Net::SFTP API is entirely different.

All have pretty complete RDoc documentation, so you should be able to employ “ri” to good effect to find your way around the libraries. (Try “ri Net::SSH”, for example, to get started.)

Per-library synopses follow.

Net::SSH 2.0

This is a significant upgrade from Net::SSH 1.x. Changes from 1.x include (but are not limited to):

  • Net::SSH 2.0 no longer requires the Needle dependency-injection library. This has made the library faster, lighter, and easier to understand.
  • The “sync” and “sync-shell” services have been removed and will not return. (If you need the functionality of those services, I strongly encourage you to port them to Net::SSH 2 and release them as separate extensions.)
  • Options in ~/.ssh/config files are (partially) supported, and are loaded by default now.
  • The Net::SSH::start method now requires both a host and a username as the first two parameters, rather than inferring the username.
  • There is now a Session#exec method that makes it easier than ever to just execute and interact with a command.
  • Channel now sports an #on_process method that you can send a block to, which will be executed on every pass of the event loop.
  • Channel#on_request now accepts a string to indicate which request you want to respond to.
  • Channel open failures may be captured via Channel#on_open_failure.
  • Lots, lots, LOTS, more—refer to the rdocs for all the gory details.
1
2
3
4
5
6
require 'net/ssh'

Net::SSH.start('localhost', 'jamis') do |ssh|
  ssh.exec('hostname') # prints the results to $stdout
  ssh.loop
end

Net::SFTP 2.0

This is a complete rewrite of the original Net::SFTP 1.x code, and shares very, very little in common with it. The new version has a much cleaner implementation and API, and provides some really handy methods for transferring files and directories.

1
2
3
4
5
6
7
8
9
10
require 'net/sftp'

Net::SFTP.start('localhost', 'jamis') do |sftp|
  sftp.upload! "/local/file", "/remote/file"
  sftp.download! "/remote/file", "/local/file"

  sftp.file.open("/remote/file", "w") do |file|
    file.puts "here is some data"
  end
end

Net::SCP 1.0

This provides a way to transfer files and directories via the SCP protocol, over Net::SSH.

1
2
3
4
5
6
require 'net/scp'

Net::SCP.start('localhost', 'jamis') do |scp|
  scp.upload! "/local/file", "/remote/file"
  scp.download! "/remote/file", "/local/file"
end

Net::SSH::Gateway 1.0

This library makes it easy to tunnel connections though firewalls. You simply connect to the gateway machine, and then specify which ports you want forwarded.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
require 'net/ssh/gateway'

gateway = Net::SSH::Gateway.new('host', 'user')

gateway.ssh("host.private", "user") do |ssh|
  puts ssh.exec!("hostname")
end

gateway.open("host.private", 80) do |port|
  require 'net/http'
  Net::HTTP.get_print("127.0.0.1", "/path", port)
end

gateway.shutdown!

Net::SSH::Multi 1.0

This library makes it simple to open multiple Net::SSH connections and tie them all together, running commands in parallel (much like Capistrano does).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
require 'net/ssh/multi'

Net::SSH::Multi.start do |session|
  # access servers via a gateway
  session.via 'gateway', 'gateway-user'

  # define the servers we want to use
  session.use 'user1@host1'
  session.use 'user2@host2'

  # define servers in groups for more granular access
  session.group :app do
    session.use 'user@app1'
    session.use 'user@app2'
  end

  # execute commands on all servers
  session.exec "uptime"

  # execute commands on a subset of servers
  session.with(:app).exec "hostname"

  # run the aggregated event loop
  session.loop
end

Enjoy!

Posted in Announcements | 17 comments

30 Apr 2008

Maintenance Releases: Capistrano, Net::SSH

Posted by Jamis on Wednesday, April 30

With the impending releases of the improved Net::SSH family of libraries, and the next Capistrano release that will depend on them, it was time to go back and make sure that the oldies-but-goodies will still work along side these new-comers.

To that end, I present:

Net::SSH 1.1.3

This maintenance release will hopefully fix the hangs that people have been reporting when dealing with long-running requests in Net::SSH, Net::SFTP, and Capistrano.

gem install net-ssh

It is strongly recommended that all Net::SSH users upgrade to this version.

Capistrano 1.4.2

This release merely adds an explicit dependency on Net::SSH and Net::SFTP versions less than 1.99.0, allowing you to use both cap1 and cap2 side-by-side after Net::SSH v2 (and friends) are released.

gem install --version 1.4.2 capistrano

If you are needing to run cap1 and cap2 side-by-side (for instance, if you haven’t yet upgraded some recipes, but want to enjoy the cap2 goodies on newer projects), you should upgrade your cap1 installation to 1.4.2. If you are completely upgraded to cap2, you can safely ignore this release.

Posted in Announcements | 4 comments

19 Apr 2008

Preview Releases: Net::SSH, Net::SSH::Multi

Posted by Jamis on Saturday, April 19

I’m almost ready to do a preview release of the next Capistrano version, which is built on top of the new Net::SSH library. To do that, though, I need to prime the pump by pushing out a few small fixes to Net::SSH. So, behold!

Net::SSH 2.0 Preview Release #4 (1.99.3):

gem install --source http://gems.jamisbuck.org net-ssh

This release has two minor new features and two fixed bugs:

  • Make sure HOME is set to something sane, even on OS’s that don’t set it by default. This makes things work a little better on Windows than before. (Ahem…any windows users out there that want to start playing with Net::SSH…I’d love to hear from you how it does.)
  • Add a :passphrase option to specify the passphrase to use with private keys. This lets you use encrypted keys without interaction (though since it requires you to hard-code the passphrase in your script…it kind of makes it pointless to use an encrypted key. Still, I’ve had lots of requests for this, and Francis Sullivan finally provided a patch).
  • BUG FIX: a new auth-agent connection will now be opened for every auth-agent channel request, rather than reusing a single auth-agent connection. This fixes some rather bizarre errors on some hosts.
  • BUG FIX: explicitly provided keys (those given via the :keys option) are now loaded correctly, thanks to some timely File.expand_path’ing provided in a patch from Thomas Hudson.

Net::SSH::Multi 1.0 Preview Release #2 (0.99.1)

Unrelated to Capistrano (since the next release of cap won’t be using it), I’m also pushing out a second preview release of Net::SSH::Multi, a library for managing multiple Net::SSH connections in parallel.

gem install --source http://gems.jamisbuck.org net-ssh-multi

This release has a single bug fix:

  • BUG FIX: don’t try to do IO.select on closed streams. This fixes a problem related to auth-agent channels getting closed and causing the parallel session processing to blow up.

Capistrano 2.3.0 preview release?

I’ll hopefully have a preview release for the next Capistrano version next week sometime. It’s close! I’m using it myself, locally, but I want to try it on a few more deploys to make sure it really works as advertised. I haven’t actually run any timings on it, but Capistrano with Net::SSH v2 feels significantly faster than it was on Net::SSH 1.x. Stay tuned!

Posted in Announcements | 2 comments

11 Apr 2008

Net::SSH::Multi + Rake == Tasty Potential

Posted by Jamis on Friday, April 11

Last night I released the first preview of Net::SSH::Multi (gem install --source http://gems.jamisbuck.org net-ssh-multi). Today, let me show you a tasty hint of what you can do with it.

Consider the following Rakefile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def remote
  @remote ||= begin
    require 'net/ssh/multi'

    session = Net::SSH::Multi.start

    session.via 'gateway.host', session.default_user

    session.group :web => session.use('web1', 'web2')
    session.group :app => session.use(*(1..8).map { |n| "app%02d" % n })
    session.group :db  => session.use('db1', :properties => { :primary => true })

    session
  end
end

namespace :remote do
  task :hostnames do
    remote.exec("hostname").wait
  end

  task :app_hostnames do
    remote.with(:app).exec("hostname").wait
  end

  task :web_hostnames do
    remote.with(:web).exec("hostname").wait
  end
end

You can now do things like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ rake remote:hostnames
(in /home/jamis)
[web1] web1.host
[app02] app02.host
[app05] app05.host
[app03] app03.host
[app06] app06.host
[app08] app08.host
[db1] db1.host
[app01] app01.host
[web2] web2.host
[app04] app04.host
[app07] app07.host

The Net::SSH::Multi library is still experimental, but it is stable and full-featured enough that I seriously considered implementing the next release of Capistrano on top of it. (I’ll probably put that off until cap3, though, due to the magnitude of the change.) If you do something cool with it, let me know!

Posted in Tips & Tricks | 5 comments

10 Apr 2008

More preview releases from the Net::SSH family

Posted by Jamis on Thursday, April 10

I’ve got lots of code to share with you all today:

Net::SSH 2.0 Preview Release #3

Not very many external changes, but channels now have an on_open_failure callback that you can employ to be told when a channel could not be opened.

1
2
3
4
5
6
7
channel = ssh.open_channel do |ch|
  # ...
end

channel.on_open_failure do |ch, code, reason|
  puts "could not open channel because #{reason.inspect} #{code}"
end

This change was necessary to make port forwarding a bit more reliable for Net::SSH::Gateway (see below).

Also, individual Net::SSH sessions may contain their own custom properties, much as Net::SSH channel objects do, which can be quite handy when you need to keep some state associated with the session.

ssh[:key] = "value"

This change (and several other internal refactorings) was necessary for the correct working of the Net::SSH::Multi library (see below).

To get the preview release #3 (version 1.99.2):

gem install --source http://gems.jamisbuck.org net-ssh

You can follow development via GitHub:

http://github.com/jamis/net-ssh/tree/master

Net::SFTP 2.0 Preview Release #2

All that was added in this preview release was custom properties on Upload instances:

1
2
3
uploader = sftp.upload("local.file", "remote.file")
uploader[:failed] = false
# ...

This was necessary to get Capistrano file transfers to work with Net::SFTP 2.0.

To get the preview release #2 (version 1.99.1):

gem install --source http://gems.jamisbuck.org net-sftp

You can follow development via GitHub:

http://github.com/jamis/net-sftp/tree/master

Net::SSH::Gateway 1.0 Preview Release #1

Net::SSH::Gateway is (in essence) the extraction of the gateway code from Capistrano into its own library. It lets you tunnel SSH connections through some “gateway” server to servers that would be otherwise inaccessible.

1
2
3
4
5
6
require 'net/ssh/gateway'

gateway = Net::SSH::Gateway.new('gateway.host', 'username')
gateway.ssh('remote.host', 'user') do |ssh|
  # ...
end

You can also use it as a general facilitator for forwarding connections over a local port, when you don’t care what port is to be used—you just want to connect to a remote server.

1
2
3
gateway.open('remote.host', 80) do |port|
  Net::HTTP.get_print '127.0.0.1', '/path', port
end

The current thinking is that the next release of Capistrano will ditch its own gateway implementation in favor of Net::SSH::Gateway. To get this first preview release (version 0.99.0):

gem install --source http://gems.jamisbuck.org net-ssh-gateway

You can follow development via GitHub:

http://github.com/jamis/net-ssh-gateway/tree/master

Net::SSH::Multi 1.0 Preview Release #1

Net::SSH::Multi is the guts of Capistrano, extracted into a library of their own. It allows you to define and categorize servers, and then execute commands in parallel on them, or on subsets of them, using an interface similar, if not identical, to that of Net::SSH::Connection::Session and Channel.

Eventually, Capistrano will be refactored to take advantage of Net::SSH::Multi, but doing so will require some significant changes to Capistrano’s innards, and would almost certainly break many third-party libraries. Thus, you won’t see Capistrano on Net::SSH::Multi until Capistrano 3.0 or so (which will not be the next release of Capistrano). However, you can use Net::SSH::Multi to implement most of Capistrano’s functionality in whatever form you like. Want Capistrano-in-a-rakefile? Have at it!

1
2
3
4
5
6
7
8
9
require 'net/ssh/multi'

Net::SSH::Multi.start do |session|
  session.use 'jamis@somewhere.com'
  session.use 'jamis@elsewhere.com'

  session.exec 'hostname'
  session.loop
end

Grab the first preview release (version 0.99.0):

gem install --source http://gems.jamisbuck.org net-ssh-multi

You can follow development via GitHub:

http://github.com/jamis/net-ssh-multi/tree/master

For all of these libraries I’ve tried to make the rdoc and ri documentation as informative as possible, so please refer to those to get started. If those aren’t helpful enough, let me know what could make them more useful!

Posted in Announcements Projects | 0 comments

22 Mar 2008

Preview Releases: Net::SSH and friends

Posted by Jamis on Saturday, March 22

After far, far too long, I’m extremely pleased to announce the next preview release of Net::SSH v2 (preview release #2, actual version 1.99.1), as well as the first ever preview releases of Net::SFTP v2 (preview release #1, actual version 1.99.0) and Net::SCP v1 (preview release #1, actual version 0.99.0). You can grab them from my gem server:

1
2
3
$ sudo gem install --source http://gems.jamisbuck.org net-ssh
$ sudo gem install --source http://gems.jamisbuck.org net-sftp
$ sudo gem install --source http://gems.jamisbuck.org net-scp

I’ve taken Eric Hodel’s advice this time around and ditched the pretty documentation I had started for Net::SSH; I’m going to see how far I can get with ri and rdoc alone, this time. Give it a try after installing the above: “ri Net::SSH”, for instance.

There are several caveats about this release:

1. The new Net::SSH and Net::SFTP are not backwards compatible with the previous 1.x releases, so make sure any existing scripts are explicitly depending on versions less than 1.99.0 of these libraries. (The latest Capistrano already has that explicit dependency in it, so you should be safe installing these preview releases even if you are using Capistrano).

2. The “shell”, “open3” and “sync-shell” services are gone from Net::SSH. (There may be others, too, which aren’t coming to mind at the moment.) I do not intend to bring them back. If you used those services, I strongly encourage you to reimplement them for the new Net::SSH, and release them as third-party extensions.

3. These libraries are reentrant (or ought to be), but are not thread-safe. That is to say, if you are accessing the same Net::SSH connection from multiple threads, you’re definitely going to want to do something to protect that resource (mutexes, etc.).

That said, let me know what you think, what issues you have, what suggestions you have, and so forth. I’m so happy to have this release done, though. I can see the light at the end of the tunnel finally!

Oh, and lastly, if you happen to be drinking the git kool-aid, you can follow along via github:

Posted in Announcements | 9 comments

17 Mar 2008

Net::SSH and Thread-safety

Posted by Jamis on Monday, March 17

Net::SSH 1.x is thread-safe. Net::SSH v2, as currently implemented in its pre-release state, is not.

I’ve debated this long and hard with myself. Wrapping code in mutexes and doing all the other stuff that thread-safety requires adds a surprising amount of overhead, and it feels painful to me to have to add all that when the most common use-case of the library will be in single-threaded environments. However, without the mutexes and all that overhead, using Net::SSH in a multi-threaded environment (where multiple threads are hitting the same Net::SSH connection) will result in some rather ugly errors, and would require those programs to add their own mutexes and such to protect the integrity of the connection.

I’m leaning towards leaving the library optimized for the single-thread experience, and requiring the people wanting multiple threads of execution to fend for themselves. However, in the interest of getting feedback from people who might actually use the library, I ask you: which would you prefer? A faster library in single-threaded programs? Or a simple program in multi-threaded ones? Is there a general best-practice in this case?

Posted in Projects | 26 comments

13 Mar 2008

Net::SFTP v2: done?!

Posted by Jamis on Thursday, March 13

I think...I think I’m actually, done, more or less, with Net::SFTP v2!

I just committed a last bit of documentation tweaking, and although I’m sure there’s more of that to come, and bugs to fix and features to add, I’m calling this bit “good enough”, and I’m moving on now to Net::SCP.

I’m not actually releasing Net::SFTP v2 at this point—it’s pretty much useless without a corresponding Net::SSH v2 release. So why am I saying anything about it right now? Because it’s the first significant milestone that I’ve completed in my track to complete the new Net::SSH suite of libraries! And I’m excited! And I’ve learned something significant by finishing Net::SFTP v2 before completely finishing Net::SSH v2: by completing a dependency of the primary library first, I saw first-hand where the deficiencies in the primary library were. This has resulted in a much tigher, much more useful API than the Net::SSH v1 and Net::SFTP v1 libraries.

Now, there is no real release of Net::SSH v2 and friends, but that’s not to say that if you’re brave, and don’t mind exploring a bit, you couldn’t get the new Net::SSH and Net::SFTP to work. The new Net::SSH is actually mostly done—I just need to revisit the documentation and update a few things here and there. The code is all on github. If you don’t have git, you can download a tarball directly from github, even.

So, have at it, if you’re so inclined. (And if you’d like on the github bandwagon, I’ve still got two invites burning a hole in my pocket…email me at (my first name) at jamisbuck.org, and I’ll be happy to send you one.)

Update: my github invites are all gone. Sorry!

Posted in Projects | 1 comment

07 Mar 2008

Magic 8ttp Ball

Posted by Jamis on Friday, March 7

My son, Britton, woke up this morning a little before 4am. As I was getting back into bed after feeding him, I saw that the clock read “4:04”, and (being the geek I am) I immediately thought “heh, 404 Sleep Not Found”.

He woke up a few minutes later, needing a bit of comforting (he’s definitely not usually this needy!), and when I got back into bed, the clock read “4:22”, obviously telling me that sleep was an “Unprocessable Entity”.

And thus the Magic 8ttp Ball was born.

Go on! Ask it anything! It’ll give you a suitably ambiguous HTTP response code in return. I’ve even been told it works great on the iPhone for when you have those burning questions on-the-go.

Posted in Announcements | 15 comments