Shell Scripting with a Distributed Twist: Using the Sleep Scripting Language

Learn a Perl-like language whose scripts move around your network.
Adding Agent Support

It should be no surprise that Sleep doesn't have &move. Again, we have to build it. Isn't that half the fun? The file has two functions: &move and &sendAgent:

inline move 
   callcc lambda({
      sendAgent($host, $1); 
   }, $host => $1); 

&move is an inline function. An inline function executes with the parent's variable scope, and commands, such as return, callcc and yield affect the parent. They are useful for hiding flow control tricks made possible with callcc. callcc is like a goto. It pauses the current function and calls the specified anonymous function with the current function as an argument. A paused function resumes execution the next time a script calls it. So, why is this exciting to us? Sleep's paused functions are serializable. This means a script can write a paused function to a socket or a file:

sub sendAgent 
   $handle = connect($1, 8888); 
   writeObject($handle, $2); 

For example, the &sendAgent function writes a paused function to a socket. This function expects a hostname and a function as arguments. It connects to the host with &connect, writes the function with &writeObject, and closes the handle. One piece of magic is missing. It makes no sense to send agents without receiving them.

Receiving Agents

Middleware is software that receives agents. It sits between the operating system and the agents. The following code makes up


The agent middleware must include the file. This gives it and the agents it executes access to &sendAgent and &move:

while (1) 
   local('$handle $agent');

   $handle = listen(8888, 0); 

The middleware executes in an infinite loop listening for connections on port 8888. The &listen function waits for a new connection:

   $agent = readObject($handle); 

The &readObject function reads an object in from a handle. Here, I assume I am reading a function from the handle:

   fork({ [$agent]; }, \$agent); 

The last step is to execute the agent itself. &fork executes code in an isolated thread. I make the agent available in the thread by giving it to &fork. The code I use here executes the agent. When the thread starts, the agent resumes execution from where it left off.

Run This Example

To execute this example, place a copy of and on each computer. Then, execute the middleware with:

$ java -jar sleep.jar

On the first computer, make a script with the &syslog_patrol agent. Create a computers.txt file that lists each IP address with the agent middleware. Then, run your script with:

$ java -jar sleep.jar [local ip address]

Now you have a syslog agent patrolling your network. Don't you feel safe?

What's Next?

Sleep is a language for the Java platform built with the UNIX programming philosophy. Sleep allows you to use existing tools to create solutions to problems. I've shown you how to solve a few system administration problems with Sleep. These examples offer a starting point for you to use the language.

When evaluating a new language, I look for how easily I can bring in external functionality, solve a problem or two and process data. Sadly, I wasn't able to cover data parsing in this article. But, that's okay, Sleep supports all this stuff. You can read the documentation to get a feel for regular expressions, pack and unpack, and &parseDate.

To make the most of these examples, I recommend you run them. Links to the documentation and examples are available in the Resources section. Good luck, and enjoy the language.

Raphael Mudge is an entrepreneur and computer scientist based out of Syracuse, New York. He also wrote Sleep. You can find links to his other work at