Remote hdd cloning

Some time ago i managed to clone the drive of my server over ssh. Although transmission was compressed with bzip2 it took awful long and i didn’t have a clue how long i would finally take.

Today i stumpled upon this post. The author uses a tool called pv: pv – monitor the progress of data through a pipe.

To clone a disk into a file over ssh:

dd if=/dev/hda bs=16065b | pv | gzip -c | ssh user@host "cat > clone.gz"

To restore the clone:

ssh user@host "gzip -d -c clone.gz" | pv | dd of=/dev/hda bs=16065b

Nevertheless, i mostly use

ssh foo@bar "dd if=/dev/sda | bzip2" > clone.bzip2

so i need not have my ssh private key laying around some server.

| Comments (0) »

16-Aug-07


Rails’ respond_to method

Ruby On Rails has a neat little feature called “respond_to”:

class WeblogController < ActionController::Base
  def index
    @posts = Post.find :all
    respond_to do |format|
      format.html
      format.xml { render :xml => @posts.to_xml }
      format.rss { render :action => "feed.rxml" }
    end
  end
end

Quelle

This feature uses the routes with the new default route since 1.2:

map.connect ':controller/:action/:id.:format'.

as well as accept header.

With the later and certainly co-starring Internet Explorer 5.5 to 7.0 the fun starts.

In most examples developers serve html, xml and javascript like here. I cannot confirm neither negate that the following problem occurs with these types as well:

I just finished developing an “respond_to jpg” method:

This was there from the beginning: http://dailyfratze.de/michael/2007/8 and i could easily achieve this http://dailyfratze.de/michael/2007/8.jpg with the exact same method:

respond_to do |format|      
  if(!user)
    # some stuff to see if the user exists, blah blah
    redirect_to(:action => :index)
    return
  else
    # some common stuff
 
    format.html {}
 
    format.jpg do
      # some rmagick stuff
      images = Array.new
      # some more and finally 
      send_data image.to_blob, :type =>"image/jpeg", :disposition =>'inline'
      # the return is important, without it and without render, the other block is executed as well
      return
    end
  end
end

I use the following routes in the following order:

map.connect ':user/:year/:month.:format',
                  :controller   => 'daily',
                  :action       => 'month',
                  :requirements => {:year  => /(19|20)\d\d/,
                  :month => /(0?[1-9]|1[012])/}
 
map.connect ':user/:year/:month/',
                   :controller   => 'daily',
                  :action       => 'month',
                  :requirements => {:year  => /(19|20)\d\d/,
                                           :month => /(0?[1-9]|1[012])/}

I know, this is not very DRY, but i didn’t find a way to make the dot in ‘:user/:year/:month.:format’, optional. Format isn’t a problem, but the dot was there to stay. (*)

Nevertheless, the thing worked perfect. Firefox and Safari send “*/*” as an accept header, the format argument was taken and all was well.

IE sends something like “image/jpeg”, “image/png”, “application/x-shockwave-flash”, [… some more stuff…], “*/”* the first request and all subsequent request send “*/*” as accept header. Hell yeah. After closing the window, the process repeats itself.

What does this mean? The first visit to a monthly view on Daily Fratze brought an jpeg image to IE users, the second the standard html page. Crap!

I found a post on a similar problem here: Strange behaviour of respond_to in IE.

The commentors says to put the most important block first but this isn’t an option if the accept header is used wrong. To me it seems that respond_to is somewhat broken. It should use the :format parameter or the accept header, not a mix of it.

I came up with the following solution:

respond_to do |format|      
  format.html {}
 
  format.jpg do
     # some rmagick stuff
     images = Array.new
     send_data image.to_blob, :type =>"image/jpeg", :disposition =>'inline'
     return
  end if params[:format] == 'jpg'  # If responds_to doesn't take care of :format, i'll do!
end

If i generate links to this method with url_for(…blah…, :format => ‘jpg’) i get the correct format and i guess this will work for js, rss and co. as well.

Edit:(*) I’ve noticed some change in behaviour in Rails 2.3.x: I now use :format => nil in the routes and the dot is optional as well then and i have dropped the more or less duplicate routes.

| Comments (9) »

06-Aug-07


RMagick vs. the Rest of the World

Installing RMagick seems to be a major pain in the ass… On all systems i got my hands on.

On a fresh Ubuntu Feisty Fawn gems presented me this:

configure: error: C compiler cannot create executables

Hrmpf, ImageMagick was installed, gcc for sure… What did i miss?

   1. sudo apt-get install imagemagick  
   2. sudo apt-get install libmagick9-dev  
   3. sudo gem install rmagick  

Well, the 2nd one…. Found here.

| Comments (0) »

24-Jul-07


Simple tokenizing with Oracle PL/SQL

I was in need of tokenizing some comma delimited data within an Oracle Database. A pity, there’s no split for a varchar2 like java.lang.String.split. I could have used Java in the database, but that would be lame, too.j

I found this little function which uses pipelined results, that is, it returns his results while being processed and furthermore, it can be used as a table in a from clause. Great as i need no extra code to check my values in my case.

So here it is:

CREATE OR REPLACE TYPE split_tbl AS TABLE OF VARCHAR2(32767);
/
show errors;
 
CREATE OR REPLACE FUNCTION f_split (
    p_list VARCHAR2,
    p_del VARCHAR2 := ','
) RETURN split_tbl pipelined
IS
    l_idx    PLS_INTEGER;
    l_list    VARCHAR2(32767) := p_list;
    l_value VARCHAR2(32767);
BEGIN
    LOOP
        l_idx := INSTR(l_list,p_del);
        IF l_idx > 0 THEN
            pipe ROW(LTRIM(RTRIM(SUBSTR(l_list,1,l_idx-1))));
            l_list := SUBSTR(l_list,l_idx+LENGTH(p_del));
        ELSE
            pipe ROW(LTRIM(RTRIM(l_list)));
            EXIT;
        END IF;
    END LOOP;
    RETURN;
END f_split;
/
show errors;

This thing takes two parameters, the first one the string to be tokenized, the second an optional delimiter. It returns all tokens trimmed as a row for each token.

Kudos to Scott Stephens.

| Comments (4) »

18-Jul-07