Programming
Using Ruby to run commands on a lab of Linux machines
by Drew Dahl on Feb.24, 2011, under Linux, Programming
Lately, I’ve been getting acquainted with Rails development at work. It’s been a pretty steep learning curve (for that matter, I guess it still is), but I’ve enjoyed it thus far. So, with my new found Ruby skills (or, I guess more-so my new found need to learn Ruby), I wrote a script that uses SSH to iteratively connect to every computer in a lab and update them. This could be used for just about anything, but for my instance it was updating a lab. There was a bit more to my script as I needed to recompile some device drivers when there was a new kernel, but for simplicities sake, I’ve ripped them out. Hope this helps someone else!
First, you’ll need to install the ruby-ssh library.
sudo gem install highline
And, the script is:
require 'rubygems'
require 'net/ssh'
require 'highline/import'
hosts=[ "host1",
"host2" ]
cmds = ["yum -y update",
"init 6"]
username = "root"
# Assuming that all hosts have the same password
password = ask("Enter Password: ") { |q| q.echo = false }
hosts.each do |host|
Net::SSH.start( host , username, :password => password) do |ssh|
puts "Connected to #{host}"
cmds.each do |cmd|
puts "Performing #{cmd} on #{host}"
output = ssh.exec! cmd do |ch, stream, data|
if stream == :stderr
puts "Error: #{data}"
else
puts data
end
end
end
end
end
And, that’s all there is to it! There’s a real lack of comments, but I feel it’s pretty self-explanatory. Enjoy!
Simple Shell in C
by Drew Dahl on Dec.02, 2010, under Linux, Programming
Well, life has been a 24/7 hell for the last few months. As an example of how much free time I’ve had, I haven’t seen a couple of my really good friends since July or August. Hopefully they haven’t forgotten about me
In any case, I wrote a pretty good simple shell in C for my Operating Systems class. I finished it back in October, but haven’t posted it until now as several students just recently finished theirs. Wouldn’t want them to cheat.
Less rambling. The reason I’m posting this is that I think it is a really good example of using some basic system calls, such as malloc(), printf(), fgets(), strtok(), strcmp(), strcpy(), sprintf(), free(), chdir(), fork(), execpe(), opendir(), and wait(). Hopefully someone finds this useful
#include <stdlib .h>
#include <unistd .h>
#include <string .h>
#include <sys /types.h>
#include <dirent .h>
const int SIZE=100;
const int ARGSIZE=10;
void cd(char *dir)
{
int ret = 0;
//Check to see if directory argument is blank
if(dir == '\0')
dir = getenv("HOME");
//Check to see if directory argument starts with ~ and replace it with $HOME
else if(dir[0] == '~')
{
char* temp = malloc(SIZE);
strcpy(temp,dir+1);
sprintf(dir,"%s%s",getenv("HOME"),temp);
free(temp);
}
//Change Directory
ret = chdir(dir);
if(ret != 0)
fprintf(stderr,"Failed to enter directory: %s\n",dir);
else
printf("%s\n",dir);
}
void ls(char *dir)
{
DIR* open_dir;
struct dirent* drent;
if(dir == '\0') //See if dir is valid, if not set it to current directory
dir = (char*)".";
if((open_dir = opendir(dir)) != NULL) //open dir
{
while((drent = readdir(open_dir)) != NULL) //get contents of directory
{
printf("%s\n",drent->d_name); //print contents
}
closedir(open_dir); //close dir
}
}
void execute(char *args[])
{
int status;
pid_t pid;
//fork and execute the command
if((pid = fork()) == 0)
{
execvp(args[0],args);
//execvp should only return if there was an error
fprintf(stderr,"Unknown command\n");
exit(0);
}
else if(pid < 0)
{
fprintf(stderr,"Failed to fork(): %s\n", args[0]);
status = -1;
}
//Wait for child so stdin and stdout aren't fighting for use
else
while(wait(&status) != pid)
continue;
}
int main(int argc, char *argv[], char *envp[])
{
char *temp;
char *line;
char *args[ARGSIZE];
char argIndex = 0;
for(;;)
{
line = malloc(SIZE); //Allocate memory for line
argIndex = 0; //Initialize argIndex
printf("\n[SHELL ] ");
fgets(line, SIZE, stdin); //Get Input
temp = strtok(line, " \n"); //Get input into an array to use w/ execve
while(temp != NULL)
{
args[argIndex] = temp;
argIndex++;
temp = strtok(NULL, " \n");
}
args[argIndex] = (char*) 0; //Set the end of the arguments list
if(strcmp(args[0], "quit") == 0 || strcmp(args[0], "exit") == 0)
break; //break out for for(;;) loop
if(line== "\n")
printf("[SHELL ] ");
else if ((strcmp(args[0], "ls") ==0))
ls(args[1]); //run ls
else if ((strcmp(args[0], "cd") == 0))
cd(args[1]); //run cd
else
execute(args); //Fork and Execute command
free(line); //Free memory from line
}
printf("\n");
return 0;
}
And, in case you want a Makefile (I know I do!):
OBJECTS =
PROC = shell
CFLAGS =
LFLAGS =
$(PROC):
$(CC) $(CFLAGS) simpleshell.c -o $(PROC) $(LFLAGS)
all:
$(CC) $(CFLAGS) simpleshell.c -o $(PROC) $(LFLAGS)
clean:
rm -rf *.o *.c~ $(PROC)
Enjoy!
(P.S… Todoist-for-Android updates will follow! I promise! The holidays are coming after all! :-] )
Make it snow
by Drew Dahl on Jan.17, 2010, under HowTo, Programming
A friend of mine set this up on his page for Christmas. I thought it was kind of cool, so I thought I’d post it here.
You can download the code from my site directly here. (Right click or option-click the link and choose “Save As…” to download this file.)
