• Welcome to Overclockers Forums! Join us to reply in threads, receive reduced ads, and to customize your site experience!

/bin

Overclockers is supported by our readers. When you click a link to make a purchase, we may earn a commission. Learn More.
This one might come in handy. It makes a minimalist (edit: well, not really if you like Perl modules) but fully-functional chroot jail with arbtirary binaries, Perl modules, dynamic libraries, devices and other fun stuff. By default, the script will give you enough so you can manually chroot into the dir, although this should be tightened up for a real install.
The guide I based this off of can be found here (notice that it's a Perl script that serves the page) and an explanation of why chroot jails are worthless if an attacker can get root access is here.
While this script is intended to make securing your webserver easier, I can't make any guarantees. If someone breaks into your server, you get to keep the pieces.

Note: This is a newer version that uses Module::ScanDeps instead of my homebrew function. It takes significantly longer to run (although I doubt many of you will be running it on a PPro like me), but is also is more likely to work if your module needs something other than modules or scripts. On my box, it took 36 seconds to make the chroot with LWP, and it contained 1109 files.

'nother note: The newer version, updated 4/4/05, now takes care of all dependencies of the libraries that the specified Perl modules use automatically. It also sticks anything that ends in .so (which means shared/dynamic libraries unless your system is screwy) in /lib instead of in the dir where the rest of the Perl stuff is. This didn't cause any problems on my system and is cleaner than potentially having mulitple copies of the same library in different places.
I also fixed a bug that resulted in the toplevel module not being copied if it had a :: in its name. On my trusty dual PPro, the below configuration with only the LWP module takes ~1:40 to run and contains 1106 files.
update: The new version, updated 6/16/05, doesn't work any differently but is much better commented. I'm trying to (re)write my code so that its functionality can be reproduced if everything but comments is stripped out, and this is my first victim.

You can download the code directly here, or copy/paste if my server's down. If you copy/paste, I recommend quoting me so you get exactly what I typed. The link will point to the latest version, although it shouldn't work any differently than what's below.

Code:
#!/usr/bin/perl

#mkplchroot.pl: a script to automate setting up a chroot with Perl modules
#Copyright (C) 2005 Christoph Otto
#
#This program is free software; you can redistribute it and/or
#modify it under the terms of the GNU General Public License
#as published by the Free Software Foundation; either version 2
#of the License, or (at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License (http://www.gnu.org/copyleft/gpl.html#TOC1)
#for more details.

#this is where the chroot will be (doesn't need to exist when the script is run)
my $root="/home/stupid_chroot";

#this is the user and group who will own everything
my $chroot_user="nobody:nogroup";

#these are the Perl modules to install
my @install_mods = (
                    #"Devel::DProf",
                    #"LWP::Simple",
                    "DBD::SQLite","DBI",
                    #"CGI",
                    #"Storable",
                    #"Socket",
                    #"Fcntl",
                    #"GD::Graph::lines",
                    #"File::Copy",
                   );

#thise are the binaries to install
my @install_binaries = ("/usr/bin/perl",
                        "/bin/bash", 
                        #"/usr/bin/strace",
                        #"/bin/sleep",
                        "/bin/ls",
                        "/bin/tar",
                       );

#These are the dynamically loaded libraries to install.
#If one of the binaries doesn't seem to run, check its strace output
#for any failed attempts to open a library.  Unfortunately, 
#there's no better way to check for these.  The files lib is 
#so ls can print user and group names and the dns lib is for anything 
#that deals with network i/o.
my @install_dlibs = (
                     "/lib/libnss_files.so.2", 
                     "/lib/libnss_dns.so.2",
                    );

#these are the special files to install in /dev
my @install_devs = (
                    "null", 
                    "zero", 
                    "urandom"
                   );

##############################################################################
##########You shouldn't need to change anything below this line.##############
##############################################################################

use Module::ScanDeps;
use File::Copy;

#this is where to put Perl's modules inside the chroot dir
my $perl_dir="/usr/share/perl5";

#this is filled with the libraries required by Perl modules
my @install_plibs = ();

#this contains all files to be installed as src => tgt
my %install_files = ();

#make the specified dir and any non-existant parent dirs
sub mkdir_p($)
{
  my $full_path = shift;
  my $curr_path = "";
  #print "mkdir called with $full_path\n";
  foreach my $dir (split /\//,$full_path) {
    $curr_path .= "$dir/";
    #print "checking for $curr_path\n";
    unless ( -e "$curr_path" ) {
      mkdir($curr_path);
      #print "creating\n";
    }
  }
}


#copy a binary and libraries it depends on
sub chroot_copy($$)
{
  #first param is binary, second is where it's copied to
  my $binary = shift;
  my $dest = shift;
  print "copying $binary into chroot\n";
  #use 'ldd' to get information about dependency libraries
  open PIPE, "ldd $binary |";
  while(<PIPE>){
    $pipe_out .= $_;
  }
  close PIPE;
  
  #print "ldd says: $pipe_out";
  #get library names out of ldd's output
  #eg:"        libpthread.so.0 => /lib/tls/libpthread.so.0 (0xb7fb0000)"
  #turn into: "/lib/tls/libpthread.so.0"
  
  for my $library (split "\n", $pipe_out) {
    
    #example:
    #"        libpthread.so.0 => /lib/tls/libpthread.so.0 (0xb7fb0000)"
    $library =~ s/.* => //;
    #"/lib/tls/libpthread.so.0 (0xb7fb0000)"
    $library =~ s/ \(.*//;
    #"/lib/tls/libpthread.so.0"
    
    #only copy the file if it's not already in the chroot
    if ( ! -f "$root/lib/$library" ) {
      copy("$library", "$root/lib");

      #special case because ld-linux.so.2 (aka linux loader) 
      #needs to be executable
      if ( $library =~ /ld-linux/ ) {
        system("chmod 555 $root/$library");
      }
    } 
  }
  #copy the actual binary into the chroot and make executable
  copy("$binary", "$root/$dest");
  if ($dest eq "bin") {
    system("chmod 555 $root/$dest/*");
  }
  
  #add a symlink so scripts with "#!/usr/bin/perl" work fine
  if ("$binary" eq "/usr/bin/perl" ) {
    mkdir_p "$root/usr/bin";
    system("ln -s /bin/perl $root/usr/bin/perl");
  }
}

#copy a module and dependencies into chroot
sub chroot_copy_perl_mod($)
{
  #first param is the name of the module to copy, ie "GD::Graph::lines"
  my $new_mod = shift;
  
  #"GD::Graph::lines"
  $new_mod =~ s/::/\//g;
  #"GD/Graph/lines"
  $new_mod =~ s/$/.pm/;
  #"GD/Graph/lines.pm"
  
  print "installing $new_mod Perl module...\n";
  my @files = ();
  my $mod_file;

  #look at each directory in @INC to find where the module we want lives
  foreach my $dir (@INC) {
    if ( -f "$dir/$new_mod") {
      $mod_file = "$dir/$new_mod";
      last;
    }
  }
  
  #use Module::ScanDeps to find all the dependencies (hopefully)
  my %deps;
  my $deps = scan_deps( 
        files   => [ "$mod_file" ],
        recurse => 1,
  );
        
  #keep stats for more interesting output
  my $file_count = 0;
  my $lib_count  = 0;
  
  #make sure the directory where the module will live exists
  my $path = "$root/$perl_dir/$new_mod";
  $path =~ s/\/[^\/]*$//;
  mkdir_p($path);

  #put the module in its places
  copy "$mod_file", "$root/$perl_dir/$new_mod";
  $file_count++;

  #copy all dependency files (can be Perl modules, .so libraries or other)
  #to their locations, putting libraries in an array for later copying
  foreach my $file (keys %$deps) {

    #find where the module lives
    foreach my $dir (@INC) {
      if (-f "$dir/$file") {
        
        #check if it's a .so library, put on array if so (pun!)
        if ( $file =~ /\.so$/ ) {
          push @install_plibs, "$dir/$file";
          $lib_count++;
        
        #otherwise, it's a normal file so just put it in the 
#Perl dir in the chroot
        } else {
          my $dir_name = "$root/$perl_dir/$file";
          
  #strip off filename extension, use result as dir to put
  #the module in.
  #"/home/perl_chroot/usr/lib/perl5/GD/Graph/lines.pm"
  $dir_name =~ s/\..*//g;
  #"/home/perl_chroot/usr/lib/perl5/GD/Graph/lines"

  #make the dir and copy the module
          mkdir_p($dir_name);
          copy "$dir/$file", "$root/$perl_dir/$file";
          $file_count++;
        }

#we're done with this file so don't keep looking through %INC
        $found = 1;
        last;
      }
    }
    print "didn't find $file\n" unless $found;
    $found = 0;
  }
  print "copied $file_count files and added $lib_count libraries to the queue\n";
  return;
}

print "making dirs...\n";
for my $dir ("$root", 
             "$root/bin", 
     "$root/dev", 
     "$root/lib", 
     "$root/tmp", 
     "$root/etc", 
     "$root/$perl_dir",
     ) {
  if ( ! -e "$dir" ) {
    mkdir_p($dir);
  }
  system("chmod 555 $dir");
}
system("chmod 555 $root");
system("chmod 777 $root/tmp");

print "installing Perl modules...\n";
#Perl modules
foreach my $mod (@install_mods){
  chroot_copy_perl_mod($mod);
}

#I don't feel like writing a recursive version of chmod manually.
system("chmod 500 -Rf $root/$perl_dir");

print "installing libraries required by Perl modules...\n";
#This is so I don't copy the same lib more than once.  It saves lots of time.
#XXX: I should probably just check whether the library exists before copying,
#but this code works fine.
my $prev_lib = "";
foreach my $lib (sort @install_plibs) {
  chroot_copy($lib,"lib") unless $prev_lib eq $lib;
  $prev_lib = $lib;
}

print "installing binaries...\n";
foreach my $binary (@install_binaries) {
  chroot_copy($binary,"bin");
}

#create a minimal /etc/nsswitch.conf (see 'man nsswitch.conf' for more info)
print "writing config files...\n";
open NSS, ">$root/etc/nsswitch.conf";
print NSS "passwd: files
shadow: files
group: files
hosts: files dns
networks: files
protocols: files
services: files";
close NSS;

#make a minimal /etc/passwd containing only the user 'nobody'
open PASSWD, ">$root/etc/passwd";
print PASSWD "root:x:0:0:root:/:/bin/bash
nobody:x:65534:65534:nobody:/nonexistent:/bin/bash";
close PASSWD;

#make a minimal /etc/group containing only the group 'nogroup'
open GROUP, ">$root/etc/group";
print GROUP "root:x:0:root
nogroup:x:65534:";
close GROUP;

#copy some other important (either large or location-dependent) config 
#files from the real /etc to the chroot's
for my $config ("localtime", "protocols", "services", "hosts") {
  copy("/etc/$config", "$root/etc");
}

#take care of explicitly specified dynamic libraries
print "copying dynamic libraries...\n";
foreach my $dlib (@install_dlibs) {
  chroot_copy($dlib,"lib");
}

#take care of explicitly specified special files
print "making devices...\n";
foreach my $dev (@install_devs) {
  open DEVINFO,"ls -lh /dev/$dev |";
  my $devinfo = <DEVINFO>;
  close DEVINFO;
  
  #get major and minor numbers of the device from 'ls'
  #"crw-rw-rw-  1 root root 1, 5 Jun 11 14:04 /dev/zero"
  $devinfo =~ /(\d+) *, *(\d+)/;
  #$1="1",$1="5"
  
  my $dev_maj = $1;
  my $dev_min = $2;
  system("mknod $root/dev/$dev c $dev_maj $dev_min");
}

#666 isn't bad.  It prevents executions.
system("chmod 666 $root/dev/*");
system("chmod 444 $root/dev/null");

#Lazieness again.  It's not like people are going to use this on windows.
system("chown $chroot_user -R $root")
 
Last edited:
Ok, well I guess I will submit mine. First off, note, its a Gentoo Specific script. Basically, before I go to bed at night, I su into root, and bash this little script. It will run all the updates, and also ensure that my system has no broken dependencies.

Note: This requires you to emerge gentoolkit first

Code:
#!/bin/bash

emerge sync;
emerge -uDv world;
emerge -v depclean;
revdep-rebuild -v;
dispatch-conf;
 
Last edited:
KidsDB

This is a script I wrote for the children's gaming computer at the library
where I'm the network administrator. The computer wasn't connected to the
network so I had to find a way to get usage statistics from it. This
program updates a database with the date and times it was accessed and
provides a GUI to see these statistics.

When run with no switch it updates the database. Given the -f or --first
switch will initialize the database. The -g or --gui switch will display
the GUI so that you can get quick information on usage statistics.

This isn't very portable in that to change what kind of statistics to
fetch (e.g. different session times) the code would need to be changed,
but this has been very useful for the situation we have it in now.

Code is included inline as well as an attached tarball. The tarball just
contains an extra setup script and some documentation that I wrote up.

Depends on

Code:
#!/usr/bin/env python

# Copyright 2005 Mike Caley

import datetime, gadfly, os, sys, wx
from optparse import OptionParser

CURRENT_YEAR = 2005

def CmdLineParser():
    """Gets and parses command line arguments."""
    Options = OptionParser(version='0.1.1')
    Options.add_option('-f', '--first', action='store_true', dest='first',
        help='''Initialize the database and tables.  Used when for the first
            time the program starts up.''', default=False)
    Options.add_option('-g', '--gui', action='store_true', dest='gui', 
        help='Enables the GUI application.', default=False)
    opts, args = Options.parse_args()
    return opts

def FirstRun():
    """Sets up the inital database and table.  Execute this program with the --first option on a new installation."""
    if not os.access(os.path.join(os.curdir, 'Database'), 0):
        os.mkdir(os.path.join(os.curdir, 'Database'))
    DBCon = gadfly.gadfly()
    # Make database if one hasn't been made already
    DBCon.startup('Kids', 'Database')
    DBCur = DBCon.cursor()
    # Make the table
    DBCur.execute("CREATE TABLE Usage (Month VARCHAR(2), Day VARCHAR(2), Year VARCHAR(4), Hour VARCHAR(2), Minute VARCHAR(2))")
    DBCon.commit()

def Error(ErrNo, TorW):
    """Function for handling the error number given as well as whether to \
    display it as a test or window message."""

    if ErrNo == 1000:
        if TorW == 't':
            print '''Error: No database
                You must first initialize the database with the -f or --first switch.'''
            sys.exit()
        elif TorW == 'w':
            wx.MessageBox('You must first initialize the database with the -f or --first switch.',
                'Error: No database', wx.OK|wx.ICON_ERROR)

def TranslateMonth(Month):
    """Translates the number representation of a month into the string representation."""
    if Month == 0:
        return 'Janurary'
    elif Month == 2:
        return 'February'
    elif Month == 3:
        return 'March'
    elif Month == 4:
        return 'April'
    elif Month == 5:
        return 'May'
    elif Month == 6:
        return 'June'
    elif Month == 7:
        return 'July'
    elif Month == 8:
        return 'August'
    elif Month == 9:
        return 'September'
    elif Month == 10:
        return 'October'
    elif Month == 11:
        return 'November'
    elif Month == 12:
        return 'December'

def NumberOfDays(Month):
    """Returns the number of days in a month."""
    if Month == 'January' or 'March' or 'May' or 'July' or 'August' or 'October' or 'December':
        return 31
    elif Month == 'April' or 'June' or 'September' or 'November':
        return 30
    elif Month == 'February':
        return 28

def Add():
    """Adds a record to the database showing that it was used."""
    CurMonth = TranslateMonth(datetime.date.today().month)
    CurDay = str(datetime.date.today().day)
    CurYear = str(datetime.datetime.today().year)
    CurHour = str(datetime.datetime.today().hour)
    CurMin = str(datetime.datetime.today().minute)
    try:
        DBCon = gadfly.gadfly('Kids', 'Database')
    except IOError:
        Error(1000, 't')
    else:
        # Cursor initalization
        DBCur = DBCon.cursor()
        DBCur.execute("INSERT INTO Usage (Month, Day, Year, Hour, Minute) VALUES ('%s', '%s', '%s', '%s', '%s')" % (CurMonth, CurDay, CurYear, CurHour, CurMin) )
        DBCon.commit()

class KidsFrame(wx.Frame):
    """The basic window for the GUI framework."""
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title)

        # Type of query
        self.QueryType = wx.ComboBox(self, -1, 'Query Type', choices = ['Average', 'Total'])

        # Month combobox
        months =  ['January', 'February', 'March', 'April', 'May', 'June',
                   'July', 'August', 'September', 'October', 'November',
                   'December']
        self.MonthBox = wx.ComboBox(self, -1, 'Month', choices = months)

        # Year combobox
        years = list()
        for n in range(CURRENT_YEAR, CURRENT_YEAR + 1):
            years.append(n)
        self.YearBox = wx.ComboBox(self, -1, 'Year', choices = years)

        # Submit button
        SubmitButton = wx.Button(self, -1, 'Submit')
        # Bind button event
        SubmitButton.Bind(wx.EVT_BUTTON, self.SelectData)

        # Output text
        self.OutputText = wx.StaticText(self, -1, style = wx.ALIGN_CENTRE)

        TopSizer = wx.BoxSizer(wx.HORIZONTAL)
        TopSizer.Add(self.QueryType, flag = wx.ALL | wx.EXPAND, border = 5)
        TopSizer.Add(self.MonthBox, flag = wx.ALL | wx.EXPAND, border = 5)
        TopSizer.Add(self.YearBox, flag = wx.ALL | wx.EXPAND, border = 5)
        TopSizer.Add(SubmitButton, flag = wx.ALL | wx.EXPAND, border = 5)

        MainSizer = wx.BoxSizer(wx.VERTICAL)
        MainSizer.Add(TopSizer)
        MainSizer.Add(self.OutputText, flag = wx.ALL | wx.EXPAND, border = 5)

        self.SetSizerAndFit(MainSizer)

    def SelectData(self, event):
        SelMonth = self.MonthBox.GetValue()
        SelYear = self.YearBox.GetValue()
        try:
            DBCon = gadfly.gadfly('Kids', 'Database')
        except IOError:
            Error(1000, 'w')
        else:
            DBCur = DBCon.cursor()
            DBCur.execute("SELECT Month, Year FROM Usage WHERE Month = '%s' AND Year = '%s'" % (SelMonth, SelYear))
            SelectedText = DBCur.fetchall()
            if self.QueryType.GetValue() == 'Total':
                self.OutputText.SetLabel( 'Total monthly usage for ' + SelMonth + ' ' + SelYear + ' is ' + str(SelectedText.__len__() / 2) + " hours" )
            if self.QueryType.GetValue() == 'Average':
                self.OutputText.SetLabel( 'Average daily usage for ' + SelMonth + ' ' + SelYear + ' is ' + str( float( SelectedText.__len__() ) / float(NumberOfDays(SelMonth) )) + ' hours')

class KidsApp(wx.App):
    def OnInit(self):
        KidsDB_Frame = KidsFrame(None, -1, 'KidsDB')
        KidsDB_Frame.Show(True)
        self.SetTopWindow(KidsDB_Frame)
        return True

if __name__ == '__main__':
    Opts = CmdLineParser()
    if Opts.first:
        FirstRun()
    elif Opts.gui:
        KidsDB = KidsApp()
        KidsDB.MainLoop()
    else:
        Add()

-DarkArctic
 

Attachments

  • kidsdb.zip
    11.2 KB · Views: 509
Last edited:
here is a small script i run every 3 days :)

#!/bin/bash

echo 'Hello Master'

sleep 4;
apt-get update;
apt-get dist-upgrade;
apt-get clean
 
at last i made my first, but working script for irssi users:)

#!bin/bash
echo enter irssi configuration path:
x="";
read x;
irssi --config="$x";

just you could help me to finish, i need that when i'm entering a path name /home/... and pressing the TAB button could complete the end of dir... like it works in shell when doing cd command ent entering the first letter of dir.
 
This is a script I hacked out to help me figure out what's going on with my memory. The input file is created by running the following, preferably as soon as you boot:
Code:
#!/bin/bash
while let 1; do
    date >>memlog; cat /proc/meminfo >>memlog; sleep 1m
done

Once you've got a couple points, you can use this script (which I release into the public domain) with "memlog" as its only argument to get a visual idea of what's going on. To graph different data, just change the list starting with "MemTotal". Anything in /proc/meminfo will work and it should be easy to extend. For ttf rendering, you'll want to either change "timesbd.ttf" to an absolute path or put it in the same dir the script lives in. Here's an example of what the output. Note that it only looks like garbage because of the automatic image resizing.
memgraph.png

Have fun.

Edit: The script should now actually work. I had a rather short-sighted bug that gigahertz was unfortunate enough to find for me.
 
Last edited:
paginate takes a PDF file as input and processes it through ghostscript and mpage to facilitate two-sided printing on non-duplex printers. The real star here is mpage, which allows you to shrink a page so that more than one can fit on a standard sheet of paper. The default is to print on US-letter sized paper, four logical pages to a sheet (two pages on one side, two on the other). Output is in the form of two PDF files, you print one of them out, then print the other on the reverse side. Fold/cut in half, take to a bookbinder, and voila! :beer:

Oh, and since the pdf-to-postscript-and-back conversions aren't the fastest in the world, I even built in a progress indicator :rolleyes:
 

Attachments

  • paginate.txt
    1.4 KB · Views: 246
i made a script that i use to easily update my kernel when a new one comes out... it is made to run on debian based systems (as it uses a bit of apt-get) but it could be easily modified for other distros... i actually have a few versions that i have worked on, including one that takes advantage of a smp enabled system (dual with ht) but this is the basic one that should work on any system

Code:
#!/bin/sh
# kernel update script
# created by:		matt bentley
# created:		09/10/2006	13:37
# updated:		09/10/2006	14:35
# usage:  		run script in the form:  './kernel_update $kernel' where $kernel is the kernel you wish to use


if [ -z $1 ]; then
	echo "error!  please specify which kernel version you which to use"
	echo "(example: './kernel_update2.sh 2.6.16.20')"
	
else
	
	# install required debian packages from repository
	echo "---INSTALLING NECESSARY PROGRAMS---"
	sleep 3
	apt-get install kernel-package ncurses-dev fakeroot wget bzip2 module-init-tools initrd-tools procps
	
	# change pwd to /usr/src directory
	cd /usr/src
	
	# remove previous link to linux source
	echo "---REMOVING PREVIOUS SOURCE LINKS---"
	sleep 3
	rm -r linux
	
	# remove any files from old build
	echo "---REMOVING OLD BUILD FILES---"
	sleep 3
	rm -r linux-$1
	
	if [ -e /usr/src/linux-$1.tar.bz2  ]; then
		echo "---NO DOWNLOAD IS NECESSARY, PROPER SOURCE FOUND---"
		sleep 3
		echo "---EXTRACTING SOURCE---"
		sleep 3
		tar -xjf linux-$1.tar.bz2
			
	else
		echo "---DOWNLOAD REQUIRED, DOWNLOADING PROPER SOURCE---"
		sleep 3
		wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-$1.tar.bz2
		echo "---EXTRACTING SOURCE---"
		sleep 3
		tar -xjf linux-$1.tar.bz2
	
	fi
	
	# create symbolic link
	ln -s linux-$1 linux
	
	# change pwd to /boot directory
	cd /boot
	
	# copy old config from current kernel
	echo "---COPYING CONFIG FROM CURRENT KERNEL---"
	sleep 3
	cp config-$(uname -r) /usr/src/linux/.config
	
	# change pwd to /usr/src/linux
	cd /usr/src/linux
	
	# build menuconfig
	echo "---BUILDING MENUCONFIG---"
	sleep 3
	make menuconfig
	
	# build interdependencies in the kernel sources
	echo "---BUILDING INTERDEPENDENCIES---"
	sleep 3
	make dep
	
	# purge unwanted files from previous builds
	echo "---PURGING OLD FILES---"
	sleep 3
	make clean
	
	# make the kernel image
	echo "---COMPILING KERNEL IMAGE---"
	echo "   (this may take a while)"
	sleep 3
	#make zImage
	make bzImage
	
	# make the modules
	echo "---COMPILING KERNEL MODULES---"
	sleep 3
	make modules
	
	# installing the new kernel
	echo "---INSTALLING NEW KERNEL---"
	sleep 3
	#cp /usr/src/linux/arch/i386/boot/zImage /boot/vmlinuz-$1
	cp /usr/src/linux/arch/i386/boot/bzImage /boot/vmlinuz-$1
	
	# install the new modules
	echo "---INSTALLING NEW MODULES---"
	sleep 3
	make modules_install
	
	# install the new system.map
	echo "---INSTALLING NEW SYSTEM.MAP---"
	sleep 3
	cp /usr/src/linux/System.map /boot/System.map-$1
	
	# setup grub
	echo "---SETTING UP GRUB---"
	sleep 3
	update-grub
	
	# copy new config
	echo "---COPYING NEW CONFIG TO BOOT---"
	sleep 3
	cp /usr/src/linux/.config /boot/config-$1
	
fi

please comment on this and let me know if there is anything people see that i could improve upon... i've thought about adding an automatically detection for smp systems but haven't really had any need for it since my old 2 systems running linux are my dual xeons and my laptop... i'm not exactly in need of anything special...
 

Attachments

  • kernel_update2.sh.txt
    2.6 KB · Views: 241
here one a friend of mine did... so credit goes to: Lordnor

if you su to root.. then you might tell the script to run as root but if you`r user is root i`ll work just fine.

Code:
#!/usr/bin/perl

use strict;
use warnings;

# find tty and user
print "...Finding my current TTY and user info:\n";
my ($tty, $user);
my @tmp = split(/\s+/, `ps aux | grep blast_ttys | grep -v grep`);
($tty, $user) = ($tmp[6], $tmp[0]);
@tmp = split(/\//, `cat /etc/passwd | grep $user`);
my $shell = pop(@tmp);
chomp $shell;

sleep 2;
print "\nmy tty is ".$tty."!\n";
print "my user is ".$user."!\n";
print "my shell is ".$shell."!\n";

# find other ttys I own
print "\nFinding other TTYs I own:\n";
my @otherTtys = `w | awk '\$1 ~ /$user/ {print \$2}' | grep -v $tty`;
foreach (@otherTtys) {
        chomp;
        print "...found: ".$_.".\n";
}

# find the shells and kill them
print "\n...Finding process info for other TTYs:\n";
my (@psOut, @shellPids);
foreach (@otherTtys) {
        @tmp = `ps aux | grep $_ | grep $user | grep -v grep`;
        push @psOut, @tmp;
}
foreach (@psOut) {
        if (/$shell/) {
                @tmp = split;
                print "I'm going to blast/kill this pid: ".$tmp[1].".\n";
                push @shellPids, $tmp[1];
        }
}

foreach (@shellPids) {
        `kill -9 $_`;
}
 
Here is a fairly small python program I wrote that includes a full GUI and it takes a Python file and will compile it into optimized python bytecode. Also requires python-wxgtk2.6 or above.

You can also find it on Google Code as a tar.gz which includes an installer and icons and stuff. But here it is:

Code:
#!/usr/bin/env python
#-------------------------------
# gPyCompile v0.1.1
#-------------------------------
# Written by Alec Hussey
# License: General Public License
#-------------------------------

import os, compiler
from wx import stc
from wxPython.wx import *

ID_OPEN = 100
ID_SAVE = 105
ID_EXIT = 110
ID_COMPILE = 120
ID_SYNTAXCHECK = 125
ID_RUNPROGRAM = 130
ID_ABOUT = 150

class gpycFrame(wxFrame):
	def __init__(self, parent, ID, title):
		wxFrame.__init__(self, parent, ID, title, wxDefaultPosition, wxSize(700, 500))
		self.Filename = ""
		self.Directory = ""
		self.TextControl = stc.StyledTextCtrl(self, 1, style=wxTE_MULTILINE)
		self.CreateStatusBar()
		
		fileMenu = wxMenu()
		fileMenu.Append(ID_OPEN, "&Open", "Open a file.")
		fileMenu.Append(ID_SAVE, "&Save", "Save the current file.")
		fileMenu.AppendSeparator()
		fileMenu.Append(ID_EXIT, "E&xit", "Terminate the application.")
		sourceMenu = wxMenu()
		sourceMenu.Append(ID_COMPILE, "Compile", "Compile the program to bytecode.")
		sourceMenu.Append(ID_SYNTAXCHECK, "Syntax Check", "Check syntax of the program.")
		sourceMenu.Append(ID_RUNPROGRAM, "Run Program", "Run the newly compiled program.")
		helpMenu = wxMenu()
		helpMenu.Append(ID_ABOUT, "&About", "More information about the program.")
		
		menuBar = wxMenuBar()
		menuBar.Append(fileMenu, "&File")
		menuBar.Append(sourceMenu, "S&ource")
		menuBar.Append(helpMenu, "&Help")
		
		self.SetMenuBar(menuBar)
		self.Show(True)
		
		EVT_MENU(self, ID_OPEN, self.OnOpen)
		EVT_MENU(self, ID_SAVE, self.OnSave)
		EVT_MENU(self, ID_EXIT, self.OnExit)
		EVT_MENU(self, ID_COMPILE, self.OnCompile)
		EVT_MENU(self, ID_SYNTAXCHECK, self.OnSyntaxCheck)
		EVT_MENU(self, ID_RUNPROGRAM, self.OnRunProgram)
		EVT_MENU(self, ID_ABOUT, self.OnAbout)
	def OnOpen(self, event):
		opendialog = wxFileDialog(self, "Choose a File", self.Directory, "", "*.py", wxOPEN)
		if opendialog.ShowModal() == wxID_OK:
			self.Filename = opendialog.GetFilename()
			self.Directory = opendialog.GetDirectory()
			try:
				try:
					fopen = open(os.path.join(self.Directory, self.Filename), "r")
					self.TextControl.ClearAll()
					self.TextControl.AddText(fopen.read())
				except IOError:
					msgdialog = wxMessageDialog(self, "An exception was triggered. Couldn't open file.", "IO Error", wxOK | wxICON_ERROR)
					msgdialog.ShowModal()
					msgdialog.Destroy()
			except UnicodeDecodeError:
				msgdialog = wxMessageDialog(self, "An exception was triggered. Invalid encoding or encoding not supported.", "Unicode Decode Error", wxOK | wxICON_ERROR)
				msgdialog.ShowModal()
				msgdialog.Destroy()
			fopen.close()
	def OnSave(self, event):
		if self.Filename != "" and self.Directory != "":
			try:
				fopen = open(os.path.join(self.Directory, self.Filename), "w+")
				fopen.write(self.TextControl.GetText())
			except IOError:
				msgdialog = wxMessageDialog(self, "An exception was triggered. Couldn't write to file.", "IO Error", wxOK | wxICON_INFORMATION)
				msgdialog.ShowModal()
				msgdialog.Destroy()
			fopen.close()
	def OnExit(self, event):
		self.Close(True)
	def OnCompile(self, event):
		if self.Filename != "" and self.Directory != "":
			self.SetStatusText("Compiling program...")
			compiler.compileFile(str(os.path.join(self.Directory, self.Filename)))
			self.SetStatusText("Complete")
			# Show message dialog
			msgdialog = wxMessageDialog(self, "File was compiled successfully.", "Information", wxOK | wxICON_INFORMATION)
			msgdialog.ShowModal()
			msgdialog.Destroy()
		else:
			msgdialog = wxMessageDialog(self, "You don't have any files open.", "Information", wxOK | wxICON_INFORMATION)
			msgdialog.ShowModal()
			msgdialog.Destroy()
	def OnSyntaxCheck(self, event):
		if self.Filename != "" and self.Directory != "":
			self.SetStatusText("Checking syntax...")
			try:
				compiler.parse(self.TextControl.GetText())
			except SyntaxError:
				errdialog = wxMessageDialog(self, "An error was found in your code.\n\n"+`compiler.ast.Module`, "Syntax Error", wxOK | wxICON_ERROR)
				errdialog.ShowModal()
				errdialog.Destroy()
				return False
			msgdialog = wxMessageDialog(self, "No errors were found in your code.", "Information", wxOK | wxICON_INFORMATION)
			msgdialog.ShowModal()
			msgdialog.Destroy()
			self.SetStatusText("Complete")
		else:
			msgdialog = wxMessageDialog(self, "You don't have any files open.", "Information", wxOK)
			msgdialog.ShowModal()
			msgdialog.Destroy()
	def OnRunProgram(self, event):
		if self.Filename != "" and self.Directory != "":
			self.SetStatusText("Running program...")
			self.filecheck = open(os.path.join(self.Directory, self.Filename))
			if not self.filecheck:
				msgdialog = wxMessageDialog(self, "Either you have deleted the compiled program or you have not yet compiled it.", "Information", wxOK | wxICON_ERROR)
				msgdialog.ShowModal()
				msgdialog.Destroy()
				self.SetStatusText("Error Running Program")
			else:
				try:
					os.popen("python " + os.path.join(self.Directory, self.Filename+"c"))
				except:
					msgdialog = wxMessageDialog(self, "An error occured while running the program.", "Information", wxOK | wxICON_ERROR)
					msgdialog.ShowModal()
					msgdialog.Destroy()
					self.SetStatusText("Error Running Program")
				self.SetStatusText("Complete")
		else:
			msgdialog = wxMessageDialog(self, "You don't have any files open.", "Information", wxOK)
			msgdialog.ShowModal()
			msgdialog.Destroy()
			self.SetStatusText("Complete")
	def OnAbout(self, event):
		dialog = wxMessageDialog(self, "gPyCompile 0.1.1 \n\n"
										"A simple GUI for the Python bytecode compiler.\n\n"
										"Writen by Alec Hussey\n"
										"Contact: [email protected]",
										"About", wxOK | wxICON_INFORMATION)
		dialog.ShowModal()
		dialog.Destroy()

class gpycApp(wxApp):
	def OnInit(self):
		frame = gpycFrame(NULL, -1, "gPyCompile")
		frame.Show(True)
		self.SetTopWindow(frame)
		return True

application = gpycApp(0)
application.MainLoop()
 
I made this perl script, intitially as a utility I needed for a website. But basically it takes a file and iterates through each line, inserting a prefix and suffix as it goes along. In my case I used it in conjunction with Javascript and a file with a bunch of links. Then there is a master page which it takes and displays, but replaces a global variable called LINKS inside the file with the dynamically generated javascript. You can obviously adapt it to do whatever. :)
Code:
#!/usr/bin/perl

#use CGI ':standard';

sub str_replace {
	my $replace_this = shift;
	my $with_this = shift; 
	my $string = shift;
	
	my $length = length($string);
	my $target = length($replace_this);
	
	for (my $i = 0; $i < ($length - $target + 1); $i++) {
		if (substr($string, $i, $target) eq $replace_this) {
			$string = substr($string, 0, $i) . $with_this . substr($string, ($i + $target));
			#return $string;
		}
	}
	return $string;
}

sub get_links {
	my $i = 0;
	my $prefix = "contents[";
	my $prefix2 = "]='<font size=\"2\" face=\"Arial\"><b>";
	my $suffix = "</b></font>'";
	
	open(LINKSDB, "linksdb.txt") or die "Error opening file.";
	for $line (<LINKSDB>) {
		@links = ($prefix, $i, $prefix2, $line, $suffix);
		$links_dict .= join('', @links)."\n";
		$i++;
	}
	close LINKSDB;
	return $links_dict;
}

#open(PAGE, "page.html") or die "Error opening file.";
#for $line (<PAGE>) {
#	print str_replace("LINKS", get_links(), <PAGE>);
#}
#close PAGE;
print get_links();
I have a bash script to build a base linux from scratch system as the book does it automatically, no configuration, on its way.
 
Last edited:
It's really basic, but I use it to start my GMod server. It could easily be modified to work with CS:S, HL2DM, etc.

Code:
#!/bin/bash
echo "Starting up Garry's Mod 10 server..."
sleep 1
wine ./srcds.exe -game garrysmod +map gm_flatgrass +maxplayers 6 -console +hostname "SERVER NAME HERE"
echo "Server Started!"
 
Heres a bash script I wrote to easily encrypt and decrypt my GPG encrypted files.
Code:
#!/bin/bash

# Written by Alec Hussey

function usage
{
	cat <<- __MSG__
$0
enc	Encrypt a file
dec	Decrypt a file
-h	Help
__MSG__
}

while [ "$1" != "" ]; do
	case $1 in
		enc )
			shift
			gpg -e -r "Alec Hussey" $1
			exit 0
			;;
		dec )
			shift
			gpg -o $2 -d $1
			exit 0
			;;
		* | -h )
			usage
			exit 1
			;;
	esac
	shift
done

Heres another one I use to start Wolfenstein: ET with sound every time, you must run this as root.
Code:
#!/bin/bash

echo "et.x86 0 0 direct" > /proc/asound/card0/pcm0p/oss ; et
 
i know this is an old topic, but i figured i would share a few scripts that i use all the time. they are mostly setup in cron jobs that run throughout the day.

this script sends me a system status report three times a day to my email account. it sends at 6am, noon, and 6pm using cron. this is working on my debian 'stable' server. instead of actually using sendmail, i use ssmtp which uses my exchange server to send the mails to me.

status_report
Code:
#!/bin/bash

tmp=/tmp/status-report-`date +%F`
touch $tmp && chmod 600 $tmp

if [ `date +%p` = "AM" ]
then
echo -e "subject: morning system status report [`uname -n` - `date +%x`]\n" > $tmp
else
        if [ `date +%H` = "12" ]
        then
        echo -e "subject: noon system status report [`uname -n` - `date +%x`]\n" > $tmp
        else
        echo -e "subject: evening system status report [`uname -n` - `date +%x`]\n" > $tmp
        fi
fi

echo -e "\n -- Users -- " >> $tmp
w >> $tmp
echo -e "\n -- Temperatures -- " >> $tmp
/root/scripts/temperatures >> $tmp
echo -e "\n -- Drive Status -- " >> $tmp
cat /proc/mdstat >> $tmp
echo -e "\n -- UPS Status -- " >> $tmp
/root/scripts/ups_status >> $tmp
echo -e "\n -- Free Disk Space -- " >> $tmp
df -h >> $tmp
echo -e "\n -- Ram -- " >> $tmp
free -m >> $tmp
echo -e "\n -- System Updates -- " >> $tmp
/root/scripts/apt_upgrade >> $tmp
echo -e "\n -- Processes -- " >> $tmp
#ps auxf >> $tmp
top -n 1 -b >> $tmp

sudo sendmail -f root root < $tmp

rm $tmp

temperatures
Code:
#!/bin/bash

sensors | egrep '(Chipset)|(CPU 1)|(CPU 2)'

ups_status
Code:
#!/bin/bash

sudo apcaccess status | egrep '(MODEL    :)|(STATUS)|(BCHARGE)|(LOADPCT)|(TIMELEFT)|(LASTXFER)|(NUMXFERS)'
 
Last edited:
This bash script is to be called by rtorrent when downloads are finished, moves the downloaded file to the right folder, and emails and texts me notifications.

Code:
#!/bin/bash

##usage, add the following to .rtorrent.rc :
##system.method.set_key = event.download.finished,notify_me,"execute=/path/to/this/file.sh,$d.get_name="

## target=/media/torrents/tv/24/$(ls /media/torrents/tv/24/| tail -n 1) is the last folder in the 24 folder, so it puts it in the correct season folder. 
##script assumes that downloads are saved in: /media/torrents/downloading/

##target is the folder the matched file will be moved to 
##notify a list of people to email seperaed by comers about the download finishing 
 
#sets the target folder based on the name of the download
case $1 in
        *.iso) target=/media/torrents/DiskImages [email protected],[email protected] ;;
        *.img) target=/media/torrents/DiskImages notify= ;;
        *Chuck*) target="/media/torrents/tv/Chuck/$(ls /media/torrents/tv/Chuck/| tail -n 1)" notify= ;;
        *24.S*) target="/media/torrents/tv/24/$(ls /media/torrents/tv/24/| tail -n 1)" notify=;;
        *House*) target="/media/torrents/tv/House/$(ls /media/torrents/tv/House/| tail -n 1)" notify= ;;
        *South.Park*) target="/media/torrents/tv/Southpark/$(ls /media/torrents/tv/Southpark/| tail -n 1)" notify=;;
        *Two.and.a.Half.Men*) target="/media/torrents/tv/TwoAndAHalfMen/$(ls /media/torrents/tv/TwoAndAHalfMen/| tail -n 1)" notify=;;
        *Lie.to.Me*) target="/media/torrens/tv/LieToMe/$(ls /media/torrens/tv/LieToMe/ | tail -n 1)" notify=;; 
        *FlashForward*) target="/media/torrents/tv/FlashForward/$(ls /media/torrents/tv/FlashForward/| tail -n 1)" notify= ;;
        *NCIS.L*) target="/media/torrents/tv/NCIS-LA/$(ls /media/torrents/tv/NCIS-LA/| tail -n 1)" notify= ;;
        *NCIS*) target="/media/torrents/tv/NCIS/$(ls /media/torrents/tv/NCIS/| tail -n 1)" notify= ;;
        *Top.Gear*) target="/media/torrents/tv/TopGear/$(ls /media/torrents/tv/TopGear/ | tail -n 1)" notify= ;;
        *TheITCroud*) target="/media/torrents/tv/TheITCroud/$(ls /media/torrents/tv/TheITCroud/| tail -n 1)" notify= ;;
        *Burn.Notice*) target="/media/torrents/tv/BurnNotice/$(ls /media/torrents/tv/BurnNotice/| tail -n 1)" notify= ;;
        *Scrubs*) target="/media/torrents/tv/Scrubs/$(ls /media/torrents/tv/Scrubs/| tail -n 1)" notify= ;; 
        *The.Big.Bang.Theory*) target="/media/torrents/tv/TheBigBangTheory/$(ls /media/torrents/tv/TheBigBangTheory/| tail -n 1)" notify=;;
        *Human.Target*) target="/media/torrents/tv/HumanTarget/$(ls /media/torrents/tv/HumanTarget/| tail -n 1)" notify= ;; 
        *Caprica*) target="/media/torrents/tv/Caprica/$(ls /media/torrents/tv/Caprica/| tail -n 1)" notify= ;;
        *The.Simpsons*) target="/media/torrents/tv/The.Simpsons/$(ls /media/torrents/tv/The.Simpsons/| tail -n 1)" notify=  ;;
        *Bones*) target="/media/torrents/tv/Bones/$(ls /media/torrents/tv/Bones/| tail -n 1)" notify= ;;
        *Argumental*) target="/media/torrents/tv/Argumental/$(ls /media/torrents/tv/Argumental/ | tail -n 1)" notify= ;; 
        *"The Jeremy Kyle Show"*) target="/media/torrents/tv/TheJeremyKyleShow/" [email protected] ipod=0 ;; 
        *"Mock the Week"*) target="/media/torrents/tv/MockTheWeek/$(ls /media/torrents/tv/MockTheWeek/ | tail -n1)" notify= ;;
        *"Embarrassing Bodies"*) target="/media/torrents/tv/EmbarrassingBodies/" notify=;;
        *"Russell Howard"*) target="/media/torrents/tv/RussellHowardsGoodNews/$(ls /media/torrents/tv/RussellHowardsGoodNews/ | tail -n1)" notify= ;;
        *) target=/media/torrents/finished notify= ;;
esac


#moves the completed download to target decided above 
mv "/media/torrents/downloading/$1" "$target" 

#links the old file to the new file so that rtorrent can still seed 
ln -s "$target/$1" "/media/torrents/downloading/$1"

##emails the people in the notify option 
echo -e "$(date) : $1 - Download completed. \n\nfile has been moved to $target/$1"| mail -s "[rtorrent] - Download completed : $1" $notify #

##sends sms to a mobile of choice, from the 3g dongle. 
echo -e "$1 - Download completed. moved to $target" > ~/.message 
gammu sendsms text 07********* < ~/.message

echo $1 >> /home/mark/showsfinished

##update xbmc, and notify viewer 
/usr/bin/xbmc-send -a "UpdateLibrary(video)"
/usr/bin/xbmc-send -a "CleanLibrary(video)"
/usr/bin/xbmc-send -a "Notification([Rtorrent],$1 has finished Downloading)"


edit: didnt relize how old this thread was.
 
Here is the script that I run on my file server daily and is used for the daily backup of all systems on the network and a weekly archive of certain folders. For Windows machines, I use DeltaCopy as the client; the server just runs a RSYNC server. There are a few sections to this script. Everything is dumped to the log for further review in case there were errors.


  1. Sets the logging paths and dumps the current time
  2. Sets the current time as variables
  3. Sets the RSYNC paths
  4. RSYNC runs, copying files from the specified backup folder to a non-user accessible external drive; this runs daily
  5. If the date is equal to "1" (Monday), it goes into the archiving function I added. It simply creates a tarball of all our WoW folders. It saves them to a user accessible network drive in case we need to restore. It then makes a copy of the tarball to the external drive for backup purposes
  6. Sets the time everything finished
  7. Calculates the time it took to run the script
  8. Finishes logging to a file
It took me many revisions and much testing to get this to work. I rely on it daily, so it is rock solid.

Code:
#!/bin/bash
#This script contains all of the rsync commands that are run daily on
#Thideras' file server.  The main use for this script is to backup to
#alternate locations, such as an external drive or remote location.

LOG=/share/hitachi/logs/rsync-$(date +%m-%d-%Y).log

#Give the date and time started
echo ----------LOG START---------- 1>>$LOG
echo This log started on `date +%H`:`date +%M`:`date +%S` 1>>$LOG
echo ----------LOG START---------- 1>>$LOG
echo 1>>$LOG

#Set the current time
STARTHOUR=10#`date +%H`
STARTMIN=10#`date +%M`
STARTSEC=10#`date +%S`

#============================================================================#
#This section is the daily rsync section
#============================================================================#

#Set the locations
COREY=/share/hitachi/rsync/corey/
COREY_COPYTO=/share/external/rsync_copy/corey

DAN=/share/hitachi/rsync/dan/
DAN_COPYTO=/share/external/rsync_copy/dan

DIANA=/share/hitachi/rsync/diana/
DIANA_COPYTO=/share/external/rsync_copy/diana

#Copy the files
rsync -av --delete $COREY $COREY_COPYTO 1>>$LOG
rsync -av --delete $DAN $DAN_COPYTO 1>>$LOG
rsync -av --delete $DIANA $DIANA_COPYTO 1>>$LOG

#============================================================================#
#End daily rsync section
#============================================================================#






#============================================================================#
#This is the archive function, runs on Monday only
#============================================================================#

if [ `date +%u` -eq "1" ]
  then
        echo Starting weekly archive 1>>$LOG

        #Set the backup source locations
        COREY1="/share/hitachi/rsync/corey/World of Warcraft"
        DAN1="/share/hitachi/rsync/dan/World of Warcraft"

        #Set the backup destination locations
        COREY1_GZIP="/share/hitachi/backups/Corey_WoW/WoW-$(date  +%m-%d-%Y).tar.gz"
        COREY2_GZIP="/share/external/backups/corey/WoW-$(date  +%m-%d-%Y).tar.gz"
        DAN1_GZIP="/share/hitachi/backups/Dan_WoW/WoW-$(date  +%m-%d-%Y).tar.gz"
        DAN2_GZIP="/share/external/backups/dan/WoW-$(date  +%m-%d-%Y).tar.gz"

        #Tar and Gzip the files
        tar -cf - "$COREY1" | gzip > "$COREY1_GZIP" &
        tar -cf - "$DAN1" | gzip > "$DAN1_GZIP"

        #Copy the files to the external drive
        cp "$COREY1_GZIP" "$COREY2_GZIP"
        cp "$DAN1_GZIP" "$DAN2_GZIP"

        echo Weekly archive complete! 1>>$LOG
  else
        echo Weekly archive is not set to run today 1>>$LOG
fi

#============================================================================#
#End weekly archive
#============================================================================#        


#Get the current time in minutes and seconds, assign to variables
ENDHOUR=10#`date +%H`
ENDMIN=10#`date +%M`
ENDSEC=10#`date +%S`

#Compute the difference between the start and end time
HOUR=$(($ENDHOUR - $STARTHOUR))
MIN=$(($ENDMIN - $STARTMIN))
SEC=$(($ENDSEC - $STARTSEC))

#If the time goes under 0, correct the time
if [ $SEC -lt "0" ]
   then
        SEC=$(($SEC + 60))
        MIN=$(($MIN - 1))
fi

if [ $MIN -lt "0" ]
   then
        MIN=$(($MIN + 60))
        HOUR=$(($HOUR - 1))
fi

if [ $HOUR -lt "0" ]
   then
        HOUR=$(($HOUR + 24))
fi 

#Add the end date and time
echo 1>>$LOG
echo -----------LOG END----------- 1>>$LOG
echo This log ended on `date +%H`:`date +%M`:`date +%S` 1>>$LOG
echo Runtime: "$HOUR"h "$MIN"m "$SEC"s 1>>$LOG
echo -----------LOG END----------- 1>>$LOG

exit
 
this isn't much of a script, but i find it to be very useful when i want to try to determine the pid of a vmware VM

Code:
#!/bin/bash

ps -ef | grep vmware-vmx | grep VMware | awk '{ print $2 " " $19}' | awk -F \/ '{ print $1 $NF }' | rev | cut -b 5- | rev | sort -k 2

output example:
root@athena:~/scripts# ./vmware_pid
31783 dc1.mbentley.net
4838 dc2.mbentley.net
30946 exchange1.mbentley.net
15868 server01.contoso.com
7930 server02.contoso.com
6269 webserver.mbentley.net

if i remember correctly, this may only work if you have your virtual machines named similar to mine with '<machine name>.<domain>.<top level domain>' but it could be wrong. should be fairly simple to modify.
 
here is another script that i wrote for #idlerpg (see http://splat.mine.nu/idlerpg if you don't know what that is). i have two scripts. the first one is to just return the status to the command line. the second will check the status page and see if i am online or not. if i am not, it will email me.

Code:
#!/bin/bash
## written by mbentley

## set variables
command=$0
username=$1

function check_username {
        if [ -z "${username}" ];
        then
                echo "Usage: $command <username>";
                exit 1
        fi
}

function temp_dir {
        tempdir=/tmp/idlerpg_$username_`date +%N`
        mkdir $tempdir
        if [ ! -d "$tempdir" ]
        then
                exit 1
        fi
}

function query_stats {
        cd $tempdir
        wget -t 1 -T 5 -q http://splat.mine.nu/idlerpg/xml.php?player=$username
}

function verify_download {
        if [ ! -e "$tempdir/xml.php?player=$username" ]
        then
                echo "Error fetching data!  Please check manually:  http://splat.mine.nu/idlerpg/players.php";
                cleanup_tmp
                exit 1
        fi
}

function cleanup_tmp {
        rm -rf $tempdir
}

function validate_user {
        validate=`cat $tempdir/xml.php?player=$username | grep "<online>" | awk -F "[<>]" '{ print $3 }'`
        if [ -z "${validate}" ];
        then
                echo "$username is not a valid user (usernames are case sensitive)";
                cleanup_tmp
                exit 1
        fi
}

function grab_status {
        user_status=$validate
}

function status_check {
        if [ $user_status == 1 ];
        then
                echo "$username is online";
        else
                echo "$username is offline";
        fi
}

## run functions
check_username
temp_dir
query_stats
verify_download
validate_user
grab_status
status_check
cleanup_tmp

example output:

root@athena:~/scripts# ./idlerpg_v1 mbentley
mbentley is online
root@athena:~/scripts# ./idlerpg_v1 Baked
Baked is offline

Code:
#!/bin/bash
## written by mbentley

## set variables
command=$0
username=$1

function check_username {
        if [ -z "${username}" ];
        then
                echo "Usage: $command <username>";
                exit 1
        fi
}

function temp_dir {
        tempdir=/tmp/idlerpg_$username_`date +%N`
        mkdir $tempdir
        if [ ! -d "$tempdir" ]
        then
                exit 1
        fi
}

function query_stats {
        cd $tempdir
        wget -t 1 -T 5 -q http://splat.mine.nu/idlerpg/xml.php?player=$username
}

function verify_download {
        if [ ! -e "$tempdir/xml.php?player=$username" ]
        then
                cleanup_tmp
                exit 1
        fi
}

function cleanup_tmp {
        rm -rf $tempdir
}

function validate_user {
        validate=`cat $tempdir/xml.php?player=$username | grep "<online>" | awk -F "[<>]" '{ print $3 }'`
        if [ -z "${validate}" ];
        then
                cleanup_tmp
                exit 1
        fi
}

function grab_status {
        user_status=$validate
}

function status_check {
        if [ $user_status == 0 ];
        then
                email_offline
        fi
}

function email_offline {
        mail=$tempdir/mail_`date +%F`
        touch $mail
        chmod 600 $mail
        echo -e "subject: idleRPG: $username is offline" >> $mail
        echo -e "$username is currently offline!" >> $mail
        /usr/sbin/sendmail -f [email protected] root < $mail
}

## run functions
check_username
temp_dir
query_stats
verify_download
validate_user
grab_status
status_check
cleanup_tmp

with this one, there is no output but will email me:
Date: Wed, 09 Jun 2010 15:49:47 -0400
From: root <[email protected]>
Subject: idleRPG: Baked is offline

Baked is currently offline!
 
Last edited:
Back