Shell Scripting with a Distributed Twist: Using the Sleep Scripting Language
System administration is all about reaching out and touching everything. And, doing that requires automation. Sleep can automate SSH sessions with ease. Here is the &ssh_cmd function in action:
debug(7);
include("ssh.sl");
global('@output');
@output = ssh_cmd($user => "root",
$pass => "123456",
$host => "foo.example.com",
$command => "cat /etc/shadow");
printAll(@output);
This script authenticates to foo.example.com via SSH, executes "cat /etc/shadow", and prints the result on the local machine. Before we go further, there is something you should know. Sleep doesn't have an &ssh_cmd function. We have to build it.
Perl has the CPAN for modules. Sleep scripts can take advantage of the Java class library to add functionality. Here, I walk you through the code for ssh.sl:
import com.trilead.ssh2.* from:
trilead-ssh2-build213.jar;
Sleep uses import to get access to classes in another package. Unlike Java, Sleep can import directly from a third-party Java archive file at runtime. This is useful for trying things out quickly. Here I use the Trilead SSH for Java library to add SSH to Sleep:
sub ssh_cmd
{
local('$conn $sess $data $handle @data');
# create a connection
$conn = [new Connection: $host, 22];
[$conn connect];
This code creates a new com.trilead.ssh2.Connection object. Next, I call the connect method on this object to set up an SSH connection:
# authenticate [$conn authenticateWithPassword: $user, $pass];
Then, I call the authenticateWithPassword method on the connection. The Java library expects two string parameters. Sleep is smart enough to convert scalars to Java types as necessary:
# execute the command $sess = [$conn openSession]; [$sess execCommand: $command];
Here, I create an SSH session from the connection with the openSession method. This method returns a com.trilead.ssh2.Session object. Sleep places the object into a scalar variable. If you want to execute more than one command, create a session for each command as I've done here:
# wire up a Sleep I/O handle for STDOUT
$handle = [SleepUtils getIOHandle:
[$sess getStdout], $null];
The next thing to do is get the output from the session. Sleep has a class called SleepUtils with useful functionality. One of the methods constructs an I/O handle from Java input and output stream objects. Here, I made a readable I/O object from [$sess getStdout]. To write values, replace $null with the STDIN value for the session. This is available as [$sess getStdin]:
# read output into an array @data = readAll($handle);
From this point, you can manipulate the remote process like any other handle. Below, I read the entire contents of the handle into the array @data:
# close it all down closef($handle); [$sess close]; [$conn close]; return @data; }
The last step is to close down the session and connection. The &ssh_cmd function returns the contents of @data.
To execute this code, create ssh.sl from the example above, download trilead-ssh2-build212.jar, and re-use the SSH automation code for your own purposes. Place all these files in the same directory. Then, type:
$ java -jar sleep.jar yourscript.sl
Programs that move from computer to computer are mobile agents. Agent programming is a way of thinking about distributed computing. Some tasks fit very well into the mobile agent paradigm. For example, if you have to search all files in a network for some string, it makes no sense to download every single file and search it. It is much more efficient to move the search code to each computer and let the searching happen locally. Mobile agents make this possible.
Mobile agents also save you from the need to define a client and server protocol. You can place the entire interaction between two or more computers into a single function and let it start hopping around to complete the task.
So, what does a mobile agent look like? A mobile agent is a function that calls &move to relocate itself. Here is a syslog patrol agent. This agent patrols your network, checking the syslog dæmon on each box. If the dæmon is down, it tries to restart it. After each patrol, the agent starts over again:
debug(7);
include("agentlib.sl");
Before this script can do anything, I include the agent library file (I dissect this file in the next section):
sub syslog_patrol
{
local('$host @computers @proc $handle');
$handle = openf("computers.txt");
@computers = readAll($handle);
closef($handle);
The first task is to get a list of all computers. For this, I read in the contents of computers.txt. I assume each line has the hostname or IP address of a computer ready to receive my agents:
$handle = $null;
When an agent moves, it takes its variables, call stack and program counter with it. Sleep has to serialize this data to move a function. Serialization is the process of converting data to bytes. Scripts cannot serialize I/O handles. To prevent a disaster, I set the handle to $null before moving:
while (size(@computers) > 0)
{
$host = @computers[0];
The next task is to loop through each host. In this script, I use a list iteration approach. This approach removes the first item from @computers with each execution. @computers gets smaller and smaller until nothing is left. The item we want to work with always is at the front. I use list iteration here because foreach loops are not serializable:
move($host);
This one function call is all it takes to relocate the agent. The statement after this function will execute from $host with its variables and state intact. In this example, I don't have any error handling. I assume the host is up and that the agent can move itself there. Error handling isn't hard to add, and the Sleep documentation provides more on this topic:
@proc = filter({
return iff("*syslogd" iswm $1);
}, `ps ax`);
This code gets a list of all processes that match the wild card "*syslogd*". &filter applies the anonymous function to each item in the array given by `ps ax`. And, &filter collects the non-$null return values of these operations and puts them into an array. This is Sleep's version of grep. I can use the size of the @proc array to check whether syslog is running:
if (size(@proc) == 0)
{
chdir('/etc/rc.d/init.d');
`./syslog start`;
}
Here, I check whether syslog is running. To start it, I change directories, and execute the syslog dæmon:
@computers = sublist(@computers, 1);
}
The last step of the loop is to remove the first item from @computers. I use &ublist to do this:
sendAgent($home, lambda($this, \$home)); }
At the end of the patrol, I send the agent back to the starting computer. I use &lambda to make a fresh copy of the agent function with no saved state. I pass the $home variable into the copy so it knows where to go when it restarts:
sendAgent(@ARGV[0], lambda(&syslog_patrol,
$home => @ARGV[0]));
This code launches the agent into the system. I assume @ARGV[0] is the hostname of the home system with the computers.txt file.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Dynamic DNS—an Object Lesson in Problem Solving | May 21, 2013 |
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
- Dynamic DNS—an Object Lesson in Problem Solving
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Using Salt Stack and Vagrant for Drupal Development
- New Products
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- Download the Free Red Hat White Paper "Using an Open Source Framework to Catch the Bad Guy"
- Dart: a New Web Programming Experience
- Linux from the Beginning
- Why Hulu Plus Sucks, and Why You Should Use It Anyway
Enter to Win an Adafruit Pi Cobbler Breakout Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Pi Cobbler Breakout Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?




1 hour 28 min ago
3 hours 19 min ago
8 hours 32 min ago
11 hours 44 min ago
13 hours 59 min ago
14 hours 28 min ago
15 hours 26 min ago
16 hours 55 min ago
18 hours 3 min ago
18 hours 50 min ago