You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@qpid.apache.org by michael goulish <mg...@redhat.com> on 2009/08/03 20:20:59 UTC

Qrsh: a qpid-based remote execution utility.

I just checked in the code and test scripts for "Qrsh" to cpp/src/tests
-- since the original motivation was to help with some cluster-testing
tasks.

I know that the original justification for doing this was .. a little
slim.  But it seems to me that Qpid and remote execution go together
like .. chocolate and peanut butter. Like wine and cheese. Like fire and
gasoline.  So I wanted to do a remote-execution utility using Qpid.  

I wonder if it could grow up into a utility that might be handy to lots
of people, to do things that aren't easy with just ssh.

Here is the qrsh_doc.txt file, which is also checked in  ( to a new
directory, src/tests/qrsh_utils.



##############################################
  qrsh: a Qpid-based remote shell utility

  Last updated:  3 Aug 09    Mick Goulish
##############################################



=============================
Overview
=============================

  You're writing a multi-box test, and you want to write a
  shell script in which you start processes on other boxes
  and kill them (or send arbitrary signals to them).

  But ssh doesn't let you signal them, and bash isn't the
  greatest language in the world for creating data structures
  (like you need to associate the PIDs with box names and
  executable names.)

  Qsh is a utility implemented on Qpid that you can use from
  within your bash script, or any other scripting language.
  With it, you can:

    1. run any executable on any box in your cluster.

    2. don't worry about PIDs and box-names.  You associate
       your own abstract names with the executable instances,
       and then use those names in the rest of your script.
       I.e. "broker_1" "sender_3" etc.

    3. Launch the executable and wait until it returns, and
       get its exit code.
    4. Launch your executable and do other stuff, then come
       back later and see if it has exited.

    5. Get whatever it sent to stdout or stderr.

    6. Get the contents of any other file.

    7. send a command to all your boxes at once

    8. send a command to a randomly selected box.

    9. define groups of boxes, and send a command simultaneously
       to all boxes in a given group.




=============================
Using It
=============================

   1. You need to run a Qpid broker.

   2. You start a Qpid client ( which is called a qrsh_server )
      on all the boxes you care about.  And you give them all
      names like "mrg13", "mrg14" etc.  The names can be anything
      you want, but I've always used one qrsh_server per box,
      and given it the box name.   ( However, you can run two on
      one box, they won't collide. )

   3. After you start all servers, send a "start" command to any
      one of them:

   4. The qrsh_servers use the fanout exchange to talk to each
      other.

   5. In your script, you run an executable called "qrsh".  It knows
      how to talk to the servers, do what you want, and retrieve
      the data you want.


   example start script:  (this does 4 servers on the same box)
   -------------------------------------------------------------

       echo "Starting server mrg22 ..."
       ./qrsh_server mrg22  ./qrsh_run 127.0.0.1  5813  &

       echo "Starting server mrg23 ..."
       ./qrsh_server mrg23  ./qrsh_run 127.0.0.1  5813  &

       echo "Starting server mrg24 ..."
       ./qrsh_server mrg24  ./qrsh_run 127.0.0.1  5813  &

       echo "Starting server mrg25 ..."
       ./qrsh_server mrg25  ./qrsh_run 127.0.0.1  5813  &

       echo "Issuing start command..."
       sleep 2
       ./qrsh 127.0.0.1  5813 mrg22 start
       sleep 1

       echo "Ready."

       # end of script.






=============================
Qrsh Syntax
=============================

     qrsh  host port server_name  command_name  arg*


       "host" and "port" specify the Qpid server to connect to.

       "server_name" can be anything you want.  I always use the name
         of the box that the server is running on.

       "command_name" is the name that you choose to assign to
         the process you are running.  Each process that you decide
         to name must have a unique name within this script.

         Or it could be a reserved command name, that Qsh
         interprets in a special way.

         Reserved command names are:

             exec
             exec_wait
             exited
             get

         "exec" means "interpret the rest of the command line as a
           command to be executed by the designated server.

         "exec_wait" means same as "exec", but wait for the command
           to terminate, and return its exit code.

         "exited" -- you provide 1 arg, which is an abstract
           process name.  qrsh returns 1 if that process has exited,
           else 0.

         "get" -- you provide one arg which is a path.  qrsh returns
           (by printing to stdout) the contents of that file.

       "arg*" is zero or more arguments.  They are interpreted
         differently depending on whether you are using one of
         the above reserved command names, or making up your own
         abstract name for a command.




=============================
Examples
=============================

  1. Run a process on a remote box.

         qrsh mrg23 command_1 /usr/sbin/whatever foo bar baz

     Returns immediately.



  2. Kill a process that you started earlier:

         qrsh mrg23 exec kill -9 command_1

     After the word "exec" put any command line you want.
     The server you're sending this to will replace all abstract
     names in the command with process IDs.  ( In this example,
     just the word "command_1" will be replaced. )  Then it will
     execute the command.



  3. Execute a command, and wait for it to finish

         qrsh mrg23 exec_wait command_name args



  4. Check on whether a command you issude earlier has exited.

         ./qrsh mrg23 exited command_3

     Returns 1 if it has exited, else 0.



  5. Get the contents of a file from the remote system:

        ./qrsh mrg23 get /tmp/foo

     Prints the contents to stdout.



  6. Send a command to all servers at once:

        # This example causes them all to print thir names to stderr.
        ./qrsh all sayName

  7. Define a group of servers and send a command to that group.

      #! /bin/bash

      # Make a group of two of the servers, using "alias",
      # and send the group a command.

      qrsh 127.0.0.1 5813 \
           mrg22 alias group_1

      qrsh 127.0.0.1 5813 \
          mrg23 alias group_1

      echo "Asking group_1 to say their names... "
      qrsh 127.0.0.1 5813 \
           group_1 sayName

      # end of script.




  8. Execute a command and get its stdout and stderr contents.

        #! /bin/bash

        echo "Run a command..."
        ./qrsh 127.0.0.1 5813 \
               mrg23 command_4 my_command foo bar baz

        echo "Wait for a while..."
        sleep 10

        echo "Get stderr output:"
        echo "-------------  begin stderr ---------------"
        ./qrsh 127.0.0.1 5813 \
               mrg23 get command_4 stderr
        echo "-------------  end stderr ---------------"
        echo " "

        echo " "
        echo "Get stdout output:"
        echo "-------------  begin stdout ---------------"
        ./qrsh 127.0.0.1 5813 \
               mrg23 get command_4 stdout
        echo "-------------  end stdout ---------------"

        # end of script.




  9. Send a command to one of your servers, selected
     at random.

           #! /bin/bash

           # I do it multiple times here, so I can see
           # that it really is selecting randomly.

          echo "asking any server to say his name ..."
          ./qrsh 127.0.0.1 5813 \
                 any sayName
          sleep 1

          echo "asking any server to say his name ..."
          ./qrsh 127.0.0.1 5813 \
                 any sayName
          sleep 1

          echo "asking any server to say his name ..."
          ./qrsh 127.0.0.1 5813 \
                 any sayName
          sleep 1

          echo "asking any server to say his name ..."
          ./qrsh 127.0.0.1 5813 \
                 any sayName

        # end of script.



-----   end of qrsh_doc.txt file --------------------------


---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:dev-subscribe@qpid.apache.org