Gheek.net

November 7, 2008

iSCSI init script supporting MySQL checking

Filed under: centos, iscsi, linux, mysql, shell scripts — Tags: , , , — lancevermilion @ 10:17 am

Here is a iSCSI init script for CentOS 5.x. I presume it will work on all flavors of Linux, but haven’t tested. This init script is the original init script but modified to support checking for MySQL databases that might be using the iSCSI mounted disk. So we do not want to umount the iSCSI disk while MySQL is running. I also added checks to see if iscsid is actually running, if it is then make sure you are not already logged in. If you are then don’t try to login again. Also once iSCSI is successfully started we want to mount the iSCSI disk so it is available.

*NOTE: Make sure to adjust your boot init setup. Normally mysql will start before iscsi and iscsid EXCEPT for init 5. Which by default init 5 is the only level which will start mysqld. If you have changed this or yours if not the same make sure you account for this.


chkconfig --list | egrep "iscsi|mysql"
iscsi 0:off 1:off 2:off 3:on 4:on 5:on 6:off
iscsid 0:off 1:off 2:off 3:on 4:on 5:on 6:off
mysqld 0:off 1:off 2:off 3:off 4:off 5:on 6:off

init level 3

ls -l /etc/rc.d/rc3.d/ | egrep -i "mysql|iscsi" | awk '{print $9, $10, $11, $12;}'
K36mysqld -> ../init.d/mysqld
S07iscsid -> ../init.d/iscsid
S13iscsi -> ../init.d/iscsi

init level 5

ls -l /etc/rc.d/rc5.d/ | egrep -i "mysql|iscsi" | awk '{print $9, $10, $11, $12;}'
S07iscsid -> ../init.d/iscsid
S13iscsi -> ../init.d/iscsi
S64mysqld -> ../init.d/mysqld

/etc/init.d/iscsi

#!/bin/sh
#
# chkconfig: 345 13 89
# description: Logs into iSCSI targets needed at system startup
#
# Source function library.
. /etc/init.d/functions

PATH=/sbin:/bin:/usr/sbin:/usr/bin

RETVAL=0

start()
{

        status iscsid > /dev/null 2>&1
        RETVAL=$?

        if [ $RETVAL -ne 0 ]; then
                /etc/init.d/iscsid start
        fi


        status iscsid > /dev/null 2>&1
        RETVAL=$?

        #
        # Verify iscsi is logged in to the iscsi disk
        # and iscsid is actually running.
        #
        iscsiadm -m session -R > /dev/null 2>&1
        iscsiadmcheck=$?
        if [ $RETVAL -eq  0 ]; then
           if [ $iscsiadmcheck -ne "0" ]; then
             echo -n $"Setting up iSCSI targets: "
             # this script is normally called from startup so log into
             # nodes marked node.startup=automatic
             iscsiadm -m node --loginall=automatic
             touch /var/lock/subsys/iscsi
             success
             echo
             sleep 5
             mount -a -O _netdev
           else
             action $"iscsid: " /bin/true
             echo "iscsi:   [ is running ]"
           fi
        else
           action $"Starting iscsid: " /bin/false
           RETVAL=1
        fi
}

stop()
{
        rm -f /var/lock/subsys/iscsi

        # If this is a final shutdown/halt, do nothing since
        # lvm/dm, md, power path, etc do not always handle this
        if [ "$RUNLEVEL" = "6" -o "$RUNLEVEL" = "0" -o "$RUNLEVEL" = "1" ]; then
                success
                return
        fi

        # Do NOT turn off iscsi if root is possibly on a iscsi disk
        rootopts=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $4; }}' /etc/mtab)
        if [[ "$rootopts" =~ "_netdev" ]] ; then
                action $"Stopping iscsid: " /bin/false
                echo $"Can not shutdown iSCSI. Root is on a iSCSI disk."
                exit 1
        fi

        #
        # MySQL checking. If MySQL loads a DB from an iscsi disk we need to make sure
        # MySQL is NOT running before we shutdown iscsi and umount the iscsi disk.
        #
        mysqlopts=$(awk '{  if ( $1 ~ /^datadir/ ) { gsub("datadir=", "", $1); print $1; } }' /etc/my.cnf)
        iscsiopts=$(awk -v mysqlopts=$mysqlopts '{ if ($1 !~ /^[ \t]*#/ && $2 != "/" && mysqlopts ~ $2 ) { print $4; }}' /etc/mtab)
        /etc/init.d/mysqld status > /dev/null 2>&1
        mysqlcheck=$?
        if [[ "$iscsiopts" =~ "_netdev" ]] ; then
                if [ "$mysqlcheck" -eq 0 ]; then
                  action $"Stopping iscsid: " /bin/false
                  echo "Can not shutdown iSCSI. MySQL is mounted on a iSCSI disk."
                  exit 1
                fi
        fi
        iscsiadm -m node --logoutall=all
        /etc/init.d/iscsid stop
        success

        status iscsid > /dev/null 2>&1
        RETVAL=$?
        iscsiadm -m session -R > /dev/null 2>&1
        iscsiadmcheck=$?
        if [[ "$iscsiadmcheck" -ne 0 && $RETVAL -ne 0 ]]; then
          umount -a -O _netdev
        else
           action $"Stopping iscsid: " /bin/false
           echo "iSCSI did NOT logout successfully"
           RETVAL=1
        fi
}

case "$1" in
        start)
                start
                ;;
        stop)
                stop
                ;;
        restart)
                stop
                start
                ;;
        status)
                status iscsid
                RETVAL=$?
                ;;
        condrestart)
                [ -f /var/lock/subsys/iscsi ] && restart
                ;;
        *)
                echo $"Usage: $0 {start|stop|restart|status|condrestart}"
                exit 1
esac
exit $RETVAL

/etc/init.d/iscsid

#!/bin/sh
#
# chkconfig: 345 7 89
# description: Starts and stops the iSCSI daemon.
#
# processname: iscsid
# pidfile: /var/run/iscsid.pid
# config:  /etc/iscsi/iscsid.conf

# Source function library.
. /etc/init.d/functions

PATH=/sbin:/bin:/usr/sbin:/usr/bin

RETVAL=0

start()
{
        echo -n $"Turning off network shutdown. "
        # we do not want iscsi or network to run during system shutdown
        # incase there are RAID or multipath devices using
        # iscsi disks
        chkconfig --level 06 network off
        rm /etc/rc0.d/*network
        rm /etc/rc6.d/*network

        echo -n $"Starting iSCSI daemon: "
        modprobe -q iscsi_tcp
        modprobe -q ib_iser
        daemon iscsid
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] || return

        touch /var/lock/subsys/iscsid

        success
        echo
        sleep 5
}

stop()
{
        rm -f /var/lock/subsys/iscsid

        # If this is a final shutdown/halt, do nothing since
        # we may need iscsid for as long as possible (halt script kills
        # us at the last second)
        if [ "$RUNLEVEL" = "6" -o "$RUNLEVEL" = "0" -o "$RUNLEVEL" = "1" ]; then
                success
                return
        fi

        # don't turn off iscsi if root is possibly on a iscsi disk
        rootopts=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $4; }}' /etc/mtab)
        if [[ "$rootopts" =~ "_netdev" ]] ; then
                echo $"Can not shutdown iSCSI. Root is on a iSCSI disk."
                exit 1
        fi

        mysqlopts=$(awk '{  if ( $1 ~ /^datadir/ ) { gsub("datadir=", "", $1); print $1; } }' /etc/my.cnf)
        iscsiopts=$(awk -v mysqlopts=$mysqlopts '{ if ($1 !~ /^[ \t]*#/ && $2 != "/" && mysqlopts ~ $2 ) { print $4; }}' /etc/mtab)
        /etc/init.d/mysqld status > /dev/null 2>&1
        mysqlcheck=$?
        if [[ "$iscsiopts" = "rw,_netdev" ]] ; then
                if [ "$mysqlcheck" -eq 0 ]; then
                  echo "Can not shutdown iSCSI. MySQL is on a iSCSI disk."
                  exit 1
                fi
        fi


        echo -n $"Stopping iSCSI daemon: "

        # iscsid does not have a nice shutdown process.
        # It really should never be stopped
        #pkill -KILL iscsid
        killproc iscsid
        echo

        modprobe -r ib_iser 2>/dev/null
        modprobe -r iscsi_tcp 2>/dev/null
}

restart()
{
        stop
        start
}

case "$1" in
        start)
                start
                ;;
        stop)
                stop
                ;;
        restart)
                stop
                start
                ;;
        status)
                status iscsid
                RETVAL=$?
                ;;
        condrestart)
                [ -f /var/lock/subsys/iscsid ] && restart
                ;;
        *)
                echo $"Usage: $0 {start|stop|restart|status|condrestart}"
                exit 1
esac

exit $RETVAL

October 28, 2008

Show live mysql queries

Filed under: mysql, perl — Tags: , , , — lancevermilion @ 1:10 pm

Original code found at “http://iank.org/querysniffer/”. I have stripped much of it and inserted a log of code from “http://www.perlmonks.org/?node_id=170648” to make it a little nicer. I also added a lot of stuff via variables now.

Reference “http://www.redferni.uklinux.net/mysql/MySQL-Protocol.html” for more info on reading the pcap info.

The code will return something like this. Keep in mind the question mark has a value that is passed in with the command. I do not know how to strip out the binary around it so I choose to exclude it so I can at least get the SQL commands executed. For me this told me that the application was doing a nice SQL statement to start with then doing a not so friendly one after. I was able to go back to the developer and ask him to chase this down.

SELECT * FROM sys_log  WHERE  field1 = ?  AND  timestamp >= ? AND timestamp <= ? ORDER BY timestamp DESC LIMIT 20000
INSERT INTO log_entry (timestamp,log_type,source,description) VALUES (?, ?, ?, ?)
SELECT * FROM sys_log  WHERE  field1 = ? ORDER BY timestamp DESC LIMIT 20000
INSERT INTO log_entry (timestamp,log_type,source,description) VALUES (?, ?, ?, ?)

You will need libpcap-devel, libpcap, and perl modules (Net::Pcap, Net::PcapUtils, NetPacket::Ethernet, NetPacket::IP, NetPacket::TCP, Socket). Make sure you run “perl -c” on the script.

#!/usr/bin/perl -w
use strict;
use Net::Pcap;
use Net::PcapUtils;
use NetPacket::Ethernet qw(:strip);
use NetPacket::IP qw(:strip);
use NetPacket::Ethernet;
use NetPacket::TCP;
use Socket;
use constant MYSQL_PORT => 3306;

#   Script Version
my $ver = 0.11;

#   Remove the numbers for the command type codes you
#   do not want to see.
#   Beware binary data is not filtered just yet so you
#   might end up screwing up ascii display to your terminal
#   if the right set of binary characters pass through your screen.
#use constant COM_QUERY_TYPES => qw( 2 3 5 6 11 16 22 23 24 25 );
use constant COM_QUERY_TYPES => qw( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 );
my @COM_QUERY_TYPES = (COM_QUERY_TYPES);

#   If you do not want to filter lines that only contain binary data
#   then change the value to 0;
my $filterbinary = 1;

#   MySQL Command codes
my %cmdcode = (
  0 => 'SLEEP',
  1 => 'QUIT',
  2 => 'INIT_DB',
  3 => 'QUERY',
  4 => 'FIELD_LIST',
  5 => 'CREATE_DB',
  6 => 'DROP_DB',
  7 => 'REFRESH',
  8 => 'SHUTDOWN',
  9 => 'STATISTICS',
  10 => 'PROCESS_INFO',
  11 => 'CONNECT',
  12 => 'PROCESS_KILL',
  13 => 'DEBUG',
  14 => 'PING',
  15 => 'TIME',
  16 => 'DELAYED_INSERT',
  17 => 'CHANGE_USER',
  18 => 'BINLOG_DUMP',
  19 => 'TABLE_DUMP',
  20 => 'CONNECT_OUT',
  21 => 'REGISTER_SLAVE',
  22 => 'PREPARE',
  23 => 'EXECUTE',
  24 => 'LONG_DATA',
  25 => 'CLOSE_STMT',
  26 => 'RESET_STMT',
  27 => 'SET_OPTION',
);

my $err;

#   Use network device passed in program arguments or if no
#   argument is passed, determine an appropriate network
#   device for packet sniffing using the
#   Net::Pcap::lookupdev method

my $dev = $ARGV[0];
unless (defined $dev) {
    $dev = Net::Pcap::lookupdev(\$err);
    if (defined $err) {
        die 'Unable to determine network device for monitoring - ', $err;
    }
}

#   Specify the MTU you want to use on teh interface
my $mtu = 1500;

#   Source/Destination filter
my $filter_string = "(dst 127.0.0.1)";

#   Do not print these SQL query commands when displaying SQL queries;
#   Change $do_not_print to = ''; if you do not want to filter the printing
#   of the stuff listed below
my $do_not_print = "^SET NAMES|^SET character|^SHOW VARIABLE|^SHOW COLLATION|^SET autocommit|^SET sql_mode";

#   Number of packets to capture
#   Zero or a negative number means capture packets indefinitely
#   (or until an error occurs if the $to_ms argument of
#   the open_live method is set to 0)
#   100 = 100 packets to capture
my $count = -1;

#   Optimize the capture filter
#   0 = false (will not optimize)
#   1 = true  (will optimize)
my $optimize = 0;



#                             #
# DO NOT EDIT BELOW THIS LINE #
#                             #




#   Look up network address information about network
#   device using Net::Pcap::lookupnet - This also acts as a
#   check on bogus network device arguments that may be
#   passed to the program as an argument.
#
#   Note: The address and netmask are returned as integers
#         so you will need to convert them


my ($address, $netmask);
if (Net::Pcap::lookupnet($dev, \$address, \$netmask, \$err)) {
    die 'Unable to look up device information for ', $dev, ' - ', $err;
}
#   Convert the integer returned for the addresses to decimal ip addr format
my $Address = inet_ntoa(pack "N", $address);
my $Netmask = inet_ntoa(pack "N", $netmask);

#   Create packet capture object on device

my $object;
$object = Net::Pcap::open_live($dev, $mtu, 0, 0, \$err);
unless (defined $object) {
    die 'Unable to create packet capture on device ', $dev, ' - ', $err;
}

#   Compile and set packet filter for packet capture
#   object - For the capture of TCP packets with the SYN
#   header flag set directed at the external interface of
#   the local host, the packet filter of '(dst IP) && (tcp
#   [13] & 2 != 0)' is used where IP is the IP address of
#   the external interface of the machine.  For
#   illustrative purposes, the IP address of 127.0.0.1 is
#   used in this example.

my $filter_compiled;
Net::Pcap::compile(
    $object,
    \$filter_compiled,
    "$filter_string",
    $optimize,
    $netmask
) && die 'Unable to compile packet capture filter';
Net::Pcap::setfilter($object, $filter_compiled) &&
    die 'Unable to set packet capture filter';

my $mysqlport = MYSQL_PORT;

# Print the header before the output is displayed
print "+------------------------------------------------+\n";
print "|   MySQL Live SQL command monitor (Ver. $ver)   |\n";
print "+------------------------------------------------+\n";
print "| Filter params:
|   Interface: $dev
|   IP Address: $Address
|   NetMask: $Netmask
|   MTU: $mtu
|   Src/Dst Filter: $filter_string
|   Read # of Packets: $count
|   SQL Command Types: @COM_QUERY_TYPES
|   MySQL Port: $mysqlport
";
print "+------------------------------------------------+\n";

#   Set callback function and initiate packet capture loop
Net::Pcap::loop($object, $count, \&process_packets, '' ) ||
    die 'Unable to perform packet capture';

Net::Pcap::close($object);


sub process_packets {
  my ($user_data, $header, $packet) = @_;

  ## Strip the ethernet and IP headers
  my $tcp_obj = NetPacket::TCP->decode(ip_strip(eth_strip($packet)));

  ## Strip ethernet encapsulation of captured packet
  my $tcp_obj1 = NetPacket::Ethernet::strip($packet);

  ## Decode contents of TCP/IP packet contained within
  ## captured ethernet packet
  my $ip = NetPacket::IP->decode($tcp_obj1);
  my $tcp = NetPacket::TCP->decode($ip->{'data'});

  ## If dest_port (mysql port), grab the payload and parse it
  if ($tcp_obj->{dest_port} == MYSQL_PORT)
  {
     my $data = $tcp_obj->{data};
     return unless $data;

     my $len = unpack('C3',$data);
     return unless $len > 0;

     my $type = unpack('C',substr($data,4));
     foreach (@COM_QUERY_TYPES)
     {
       if ($type == $_)
       {
          my $Data = substr($data,5);
          if ( $do_not_print ne '' )
          {
            printf ( "SQL_CMD from %s to %s: \n  %s: %s\n\n", "$ip->{'src_ip'}", "$ip->{'dest_ip'}", "$cmdcode{$type}", "$Data" ) if $Data !~ /$do_not_print/;
          }
          else
          {
            printf ( "SQL_CMD from %s to %s: \n  %s: %s\n\n", "$ip->{'src_ip'}", "$ip->{'dest_ip'}", "$cmdcode{$type}", "$Data" );
          }
      }
    }
  }
}


#
#   POD info for perldoc
#

=head1 NAME

mysqlsniff.pl: MySQL query sniffer

=head1 VERSION

 0.11 Lance V added support for all command types.
      Added filtering
      Added exit after n packets
      Added Compiled packet filter
      Added many features from http://www.perlmonks.org/?node_id=170648
 0.10

=head1 USAGE

    mysqlsniff.pl [interface]

interface is optional, defaulting to the interface returned by
Net::Pcap::lookupdev()

Note: PCAP will require root/sudo access.

=head1 DESCRIPTION

mysqlsniff.pl is a query sniffer for mysql.  It sniffs the network with
pcap, extracts queries from mysql packets, and prints them on standard
output.

=head1 PROTOCOL

see: L
COM_QUERY packets look like this:

    0f 00 00 00
    03
    "show databases"

The first three bytes are length, the fourth is the packet number for
this transaction.  I'm ignoring the packet number and only looking at
the length, to make sure it's nonzero before continuing.

The fifth byte is the command type.  QUERY is 03.  (A complete list
can be found in mysql header files).

The rest (in the case of QUERY packets) is the query string.

=head1 AUTHOR

 Lance Vermilion 
 Ian Kilgore 

=head1 COPYRIGHT & LICENSE

Copyright 2007 iContact, all rights reserved.

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=head1 TODO

1. Fix the binary + ascii output generated with the EXECUTE query. it should only show ascii ouput and filter the binary output.

2. Find out why the CLOSE_STMT does not show any statment for closing.

3. Inspect the errors that are returned convert them to human readable.

=head1 SEE ALSO

L

=cut

September 24, 2008

Vi/Ex script line mode

Filed under: Ex, linux, Vi — Tags: , , — lancevermilion @ 5:09 pm

This would edit “/etc/ld.so.conf” which is owned by root and allow you to add “/usr/local/BerkeleyDB.4.6/lib” to the end of the file. “$” represents the last line of the file (this is determined by Vi/Ex). If you were to put the number “5” in place of “$” and there was only 2 lines in the file this would fail since that line does not exist.

sudo ex - /etc/ld.so.conf << BLAH
$ append
/usr/local/BerkeleyDB.4.6/lib
.
wq
BLAH

This will search “/etc/openldap/slapd.conf” for “var//” and replace that with “var/” AND “etc//” and replace that with “etc/”.

sudo ex - /etc/openldap/slapd.conf << BLAH
g/var\/\//s//var\//g
g/etc\/\//s//etc\//g
wq
BLAH

Reference Here for a command guide.
Reference Here for a tutorial.

January 28, 2008

xorg_conf

Filed under: linux, xorg — Tags: , , — lancevermilion @ 12:06 am

This is a generic xorg.conf


# /etc/X11/xorg.conf (xorg X Window System server configuration file)
#
# This file was generated by dexconf, the Debian X Configuration tool, using
# values from the debconf database.
#
# Edit this file with caution, and see the /etc/X11/xorg.conf manual page.
# (Type "man /etc/X11/xorg.conf" at the shell prompt.)
#
# This file is automatically updated on xserver-xorg package upgrades *only*
# if it has not been modified since the last upgrade of the xserver-xorg
# package.
#
# If you have edited this file but would like it to be automatically updated
# again, run the following command:
# sudo dpkg-reconfigure -phigh xserver-xorg

Section "Files"
FontPath "/usr/share/X11/fonts/misc"
FontPath "/usr/share/X11/fonts/cyrillic"
FontPath "/usr/share/X11/fonts/100dpi/:unscaled"
FontPath "/usr/share/X11/fonts/75dpi/:unscaled"
FontPath "/usr/share/X11/fonts/Type1"
FontPath "/usr/share/X11/fonts/100dpi"
FontPath "/usr/share/X11/fonts/75dpi"
FontPath "/usr/share/fonts/X11/misc"
# path to defoma fonts
FontPath "/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType"
EndSection

Section "Module"
Load "i2c"
Load "bitmap"
Load "ddc"
Load "dri"
Load "extmod"
Load "freetype"
Load "glx"
Load "int10"
Load "type1"
Load "vbe"
EndSection

Section "InputDevice"
Identifier "Generic Keyboard"
Driver "kbd"
Option "CoreKeyboard"
Option "XkbRules" "xorg"
Option "XkbModel" "pc105"
Option "XkbLayout" "us"
Option "XkbOptions" "lv3:ralt_switch"
EndSection

Section "InputDevice"
Identifier "Configured Mouse"
Driver "mouse"
Option "CorePointer"
Option "Device" "/dev/input/mice"
Option "Protocol" "ExplorerPS/2"
Option "ZAxisMapping" "4 5"
Option "Emulate3Buttons" "true"
EndSection

Section "InputDevice"
Identifier "Synaptics Touchpad"
Driver "synaptics"
Option "SendCoreEvents" "true"
Option "Device" "/dev/psaux"
Option "Protocol" "auto-dev"
Option "HorizScrollDelta" "0"
EndSection

Section "InputDevice"
Driver "wacom"
Identifier "stylus"
Option "Device" "/dev/wacom" # Change to
# /dev/input/event
# for USB
Option "Type" "stylus"
Option "ForceDevice" "ISDV4" # Tablet PC ONLY
EndSection

Section "InputDevice"
Driver "wacom"
Identifier "eraser"
Option "Device" "/dev/wacom" # Change to
# /dev/input/event
# for USB
Option "Type" "eraser"
Option "ForceDevice" "ISDV4" # Tablet PC ONLY
EndSection

Section "InputDevice"
Driver "wacom"
Identifier "cursor"
Option "Device" "/dev/wacom" # Change to
# /dev/input/event
# for USB
Option "Type" "cursor"
Option "ForceDevice" "ISDV4" # Tablet PC ONLY
EndSection

Section "Device"
Identifier "Intel Corporation Mobile 915GM/GMS/910GML Express Graphics Controller"
Driver "i810"
BusID "PCI:0:2:0"
EndSection

Section "Monitor"
Identifier "Generic Monitor"
Option "DPMS"
EndSection

Section "Screen"
Identifier "Default Screen"
Device "Intel Corporation Mobile 915GM/GMS/910GML Express Graphics Controller"
Monitor "Generic Monitor"
DefaultDepth 24
SubSection "Display"
Depth 1
Modes "1024x768"
EndSubSection
SubSection "Display"
Depth 4
Modes "1024x768"
EndSubSection
SubSection "Display"
Depth 8
Modes "1024x768"
EndSubSection
SubSection "Display"
Depth 15
Modes "1024x768"
EndSubSection
SubSection "Display"
Depth 16
Modes "1024x768"
EndSubSection
SubSection "Display"
Depth 24
Modes "1024x768"
EndSubSection
EndSection

Section "ServerLayout"
Identifier "Default Layout"
Screen "Default Screen"
InputDevice "Generic Keyboard"
InputDevice "Configured Mouse"
InputDevice "stylus" "SendCoreEvents"
InputDevice "cursor" "SendCoreEvents"
InputDevice "eraser" "SendCoreEvents"
InputDevice "Synaptics Touchpad"
EndSection

Section "DRI"
Mode 0666
EndSection

xorg-dual_conf

Filed under: linux, xorg — Tags: , , , — lancevermilion @ 12:05 am

A xorg.conf modified for use of dual displays. Namely a laptop screen and external monitor.


# /etc/X11/xorg.conf (xorg X Window System server configuration file)
#
# This file was generated by dexconf, the Debian X Configuration tool, using
# values from the debconf database.
#
# Edit this file with caution, and see the /etc/X11/xorg.conf manual page.
# (Type "man /etc/X11/xorg.conf" at the shell prompt.)
#
# This file is automatically updated on xserver-xorg package upgrades *only*
# if it has not been modified since the last upgrade of the xserver-xorg
# package.
#
# If you have edited this file but would like it to be automatically updated
# again, run the following command:
# sudo dpkg-reconfigure -phigh xserver-xorg

Section "Files"
FontPath "/usr/share/X11/fonts/misc"
FontPath "/usr/share/X11/fonts/cyrillic"
FontPath "/usr/share/X11/fonts/100dpi/:unscaled"
FontPath "/usr/share/X11/fonts/75dpi/:unscaled"
FontPath "/usr/share/X11/fonts/Type1"
FontPath "/usr/share/X11/fonts/100dpi"
FontPath "/usr/share/X11/fonts/75dpi"
FontPath "/usr/share/fonts/X11/misc"
# path to defoma fonts
FontPath "/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType"
EndSection

Section "Module"
Load "i2c"
Load "bitmap"
Load "ddc"
#Load "dri"
Load "extmod"
Load "freetype"
Load "glx"
Load "int10"
Load "type1"
Load "vbe"
EndSection

Section "InputDevice"
Identifier "Generic Keyboard"
Driver "kbd"
Option "CoreKeyboard"
Option "XkbRules" "xorg"
Option "XkbModel" "pc105"
Option "XkbLayout" "us"
Option "XkbOptions" "lv3:ralt_switch"
EndSection

Section "InputDevice"
Identifier "Configured Mouse"
Driver "mouse"
Option "CorePointer"
Option "Device" "/dev/input/mice"
Option "Protocol" "ExplorerPS/2"
Option "ZAxisMapping" "4 5"
Option "Emulate3Buttons" "true"
EndSection

Section "InputDevice"
Identifier "Synaptics Touchpad"
Driver "synaptics"
Option "SendCoreEvents" "true"
Option "Device" "/dev/psaux"
Option "Protocol" "auto-dev"
Option "HorizScrollDelta" "0"
EndSection

Section "InputDevice"
Driver "wacom"
Identifier "stylus"
Option "Device" "/dev/wacom" # Change to
# /dev/input/event
# for USB
Option "Type" "stylus"
Option "ForceDevice" "ISDV4" # Tablet PC ONLY
EndSection

Section "InputDevice"
Driver "wacom"
Identifier "eraser"
Option "Device" "/dev/wacom" # Change to
# /dev/input/event
# for USB
Option "Type" "eraser"
Option "ForceDevice" "ISDV4" # Tablet PC ONLY
EndSection

Section "InputDevice"
Driver "wacom"
Identifier "cursor"
Option "Device" "/dev/wacom" # Change to
# /dev/input/event
# for USB
Option "Type" "cursor"
Option "ForceDevice" "ISDV4" # Tablet PC ONLY
EndSection

Section "Device"
#Identifier "Intel Corporation Mobile 915GM/GMS/910GML Express Graphics Controller"
Identifier "intel0"
Driver "i810"
BusID "PCI:0:2:0"
Option "MonitorLayout" "CRT,LFP"
VideoRam 131072
Screen 0
Option "DevicePresence" "true"
# Option "ForceBIOS" "1920x1440=1920x1200"
# Option "FlipPrimary" "true"
EndSection

Section "Device"
#Identifier "Intel Corporation Mobile 915GM/GMS/910GML Express Graphics Controller"
Identifier "intel1"
# Option "Rotate" "CCW"
Driver "i810"
BusID "PCI:0:2:0"
Screen 1
#Option "DisplayInfo" "false"
Option "DevicePresence" "true"
# Option "ForceBIOS" "1920x1440=1920x1200"
# Option "FlipPrimary" "true"
EndSection

Section "Monitor"
Identifier "Internal"
Option "DPMS"
EndSection

Section "Monitor"
Identifier "E172FP"
Option "DPMS"
EndSection

Section "Screen"
Identifier "builtinlcd"
#Device "Intel Corporation Mobile 915GM/GMS/910GML Express Graphics Controller"
Device "intel0"
Monitor "Internal"
DefaultDepth 24
SubSection "Display"
Depth 1
Modes "1024x768"
EndSubSection
SubSection "Display"
Depth 4
Modes "1024x768"
EndSubSection
SubSection "Display"
Depth 8
Modes "1024x768"
EndSubSection
SubSection "Display"
Depth 15
Modes "1024x768"
EndSubSection
SubSection "Display"
Depth 16
Modes "1024x768"
EndSubSection
SubSection "Display"
Depth 24
Modes "1024x768"
EndSubSection
EndSection

Section "Screen"
Identifier "externallcd"
#Device "Intel Corporation Mobile 915GM/GMS/910GML Express Graphics Controller"
Device "intel1"
Monitor "E172FP"
DefaultDepth 24
SubSection "Display"
Depth 1
Modes "1024x768"
EndSubSection
SubSection "Display"
Depth 4
Modes "1024x768"
EndSubSection
SubSection "Display"
Depth 8
Modes "1024x768"
EndSubSection
SubSection "Display"
Depth 15
Modes "1024x768"
EndSubSection
SubSection "Display"
Depth 16
Modes "1024x768"
EndSubSection
SubSection "Display"
Depth 24
Modes "1024x768"
EndSubSection
EndSection

Section "ServerLayout"
#Identifier "Default Layout"
Identifier "Xinerama"
Screen 0 "builtinlcd" 0 0
Screen 1 "externallcd" LeftOf "builtinlcd"
InputDevice "Generic Keyboard"
InputDevice "Configured Mouse"
InputDevice "stylus" "SendCoreEvents"
InputDevice "cursor" "SendCoreEvents"
InputDevice "eraser" "SendCoreEvents"
InputDevice "Synaptics Touchpad"
Option "Xinerama" "true"
EndSection

Section "DRI"
Mode 0666
EndSection

January 27, 2008

nixlogin_exp

Filed under: bigip, expect, f5, linux, nix, rancid — Tags: , , , , , — lancevermilion @ 11:52 pm

In order to get this to work you will need to add something like this to your .cloginrc

add userprompt linuxsvr* sshOnlyNoPrompt
add autoenable linuxsvr* 1
add user linuxsvr*

#! /usr/bin/expect --
##
## $Id: clogin.in,v 1.79 2004/05/27 21:57:52 heas Exp $
##
## Copyright (C) 1997-2004 by Terrapin Communications, Inc.
## All rights reserved.
##
## This software may be freely copied, modified and redistributed
## without fee for non-commerical purposes provided that this license
## remains intact and unmodified with any RANCID distribution.
##
## There is no warranty or other guarantee of fitness of this software.
## It is provided solely "as is".  The author(s) disclaim(s) all
## responsibility and liability with respect to this software's usage
## or its effect upon hardware, computer systems, other software, or
## anything else.
##
## Except where noted otherwise, rancid was written by and is maintained by
## Henry Kilmer, John Heasley, Andrew Partan, Pete Whiting, and Austin Schutz.
##
#
# The login expect scripts were based on Erik Sherk's gwtn, by permission.
#
# clogin - Cisco login
#
# Most options are intuitive for logging into a Cisco router.
# The default is to enable (thus -noenable).  Some folks have
# setup tacacs to have a user login at priv-lvl = 15 (enabled)
# so the -autoenable flag was added for this case (don't go through
# the process of enabling and the prompt will be the "#" prompt.
# The default username password is the same as the vty password.
#

# Usage line
set usage "Usage: $argv0 \[-autoenable\] \[-noenable\] \[-c command\] \
\[-Evar=x\] \[-e enable-password\] \[-f cloginrc-file\] \[-p user-password\] \
\[-s script-file\] \[-t timeout\] \[-u username\] \
\[-v vty-password\] \[-w enable-username\] \[-x command-file\] \
\[-y ssh_cypher_type\] router \[router...\]\n"

# env(CLOGIN) may contain:
#	x == do not set xterm banner or name

# Password file
set password_file $env(HOME)/.cloginrc
# Default is to login to the router
set do_command 0
set do_script 0
# The default is to automatically enable
set avenable 1
# The default is that you login non-enabled (tacacs can have you login already
# enabled)
set avautoenable 0
# The default is to look in the password file to find the passwords.  This
# tracks if we receive them on the command line.
set do_passwd 1
set do_enapasswd 1
# attempt at platform switching.
set platform ""

# Find the user in the ENV, or use the unix userid.
if {[ info exists env(CISCO_USER) ] } {
    set default_user $env(CISCO_USER)
} elseif {[ info exists env(USER) ]} {
    set default_user $env(USER)
} elseif {[ info exists env(LOGNAME) ]} {
    set default_user $env(LOGNAME)
} else {
    # This uses "id" which I think is portable.  At least it has existed
    # (without options) on all machines/OSes I've been on recently -
    # unlike whoami or id -nu.
    if [ catch {exec id} reason ] {
	send_error "\nError: could not exec id: $reason\n"
	exit 1
    }
    regexp {\(([^)]*)} "$reason" junk default_user
}

# Sometimes routers take awhile to answer (the default is 10 sec)
set timeout 45

# Process the command line
for {set i 0} {$i  (enable) " }
	-re "(denied|Sorry|Incorrect)"	{
			  # % Access denied - from local auth and poss. others
			  send_user "\nError: Check your Enable passwd\n";
			  return 1
			}
	"% Error in authentication" {
			  send_user "\nError: Check your Enable passwd\n"
			  return 1
			}
	"% Bad passwords" {
			  send_user "\nError: Check your Enable passwd\n"
			  return 1
			}
    }
    # We set the prompt variable (above) so script files don't need
    # to know what it is.
    set in_proc 0
    return 0
    puts "past expect enable prompt"
}

# Run commands given on the command line.
proc run_commands { prompt command } {
    global in_proc platform
    set in_proc 1

    # If the prompt is (enable), then we are on a switch and the
    # command is "set length 0"; otherwise its "term length 0".
    # skip if its an extreme (since the pager can not be disabled on a
    # per-vty basis).
    if { [ string compare "extreme" "$platform" ] } {
	if [ regexp -- ".*> .*enable" "$prompt" ] {
	    send "\r"
	    #send "set length 0\r"
	    # This is ugly, but reduces code duplication, allowing the
	    # subsequent expects to handle everything as normal.
	    set command "set logging session disable;$command"
	} else {
	    #send "term length 0\r"
	    send "\r"
	}
	# escape any parens in the prompt, such as "(enable)"
	regsub -all {[)(]} $prompt {\\&} reprompt
	# match cisco config mode prompts too, such as router(config-if)#,
	# but catalyst does not change in this fashion.
	regsub -all {^(.{1,14}).*([#>])$} $reprompt {\1([^#>\r\n]+)?[#>](\\([^)\\r\\n]+\\))?} reprompt
	expect {
	    -re $reprompt	{}
	    -re "\[\n\r]+"	{ exp_continue }
	}
    } else {
	regsub -all "\[)(]" $prompt {\\&} reprompt
    }

    # this is the only way i see to get rid of more prompts in o/p..grrrrr
    log_user 0
    # Is this a multi-command?
    if [ string match "*\;*" "$command" ] {
	set commands [split $command \;]
	set num_commands [llength $commands]
	# the pager can not be turned off on the PIX, so we have to look
	# for the "More" prompt.  the extreme is equally obnoxious, with a
	# global switch in the config.
	for {set i 0} {$i < $num_commands} { incr i} {
	    send "[subst -nocommands [lindex $commands $i]]\r"
	    expect {
		-re "\b+"			{ exp_continue }
		-re "^\[^\n\r *]*$reprompt"	{ send_user -- "$expect_out(buffer)"
						}
		-re "^\[^\n\r]*$reprompt."	{ send_user -- "$expect_out(buffer)"
						  exp_continue }
		-re "\[\n\r]+"			{ send_user -- "$expect_out(buffer)"
						  exp_continue }
		-re "\[^\r\n]*Press  to cont\[^\r\n]*"	{
						  send " "
						  # bloody ^[[2K after " "
						  expect {
							-re "^\[^\r\n]*\r" {}
							}
						  exp_continue
						}
		-re "^ *--More--\[^\n\r]*"	{
						  send " "
						  exp_continue }
		-re "^\[^\n\r]*"	{
						  send_user -- "$expect_out(buffer)"
						  send " "
						  exp_continue }
	    }
	}
    } else {
	# the pager can not be turned off on the PIX, so we have to look
	# for the "More" prompt.  the extreme is equally obnoxious, with a
	# global switch in the config.
	send "[subst -nocommands $command]\r"
	expect {
		-re "\b+"			{ exp_continue }
		-re "^\[^\n\r *]*$reprompt"	{ send_user -- "$expect_out(buffer)"
						}
		-re "^\[^\n\r]*$reprompt."	{ send_user -- "$expect_out(buffer)"
						  exp_continue }
		-re "\[\n\r]+"			{ send_user -- "$expect_out(buffer)"
						  exp_continue }
		-re "\[^\r\n]*Press  to cont\[^\r\n]*"	{
						  send " "
						  # bloody ^[[2K after " "
						  expect {
							-re "^\[^\r\n]*\r" {}
							}
						  exp_continue
						}
		-re "^ *--More--\[^\n\r]*"	{
						  send " "
						  exp_continue }
		-re "^\[^\n\r]*"	{
						  send_user -- "$expect_out(buffer)"
						  send " "
						  exp_continue }
	}
    }
    log_user 1

    if { [ string compare "extreme" "$platform" ] } {
	send "\rexit\r"
    } else {
	send "\rquit\r"
    }
    expect {
	-re "^\[^\n\r *]*$reprompt"		{
						  # the Cisco CE and Jnx ERX
						  # return to non-enabled mode
						  # on exit in enabled mode.
						  send "\rexit\r"
						  exp_continue;
						}
	"Do you wish to save your configuration changes" {
						  send "n\r"
						  exp_continue
						}
	-re "\[\n\r]+"				{ exp_continue }
	timeout					{ return 0 }
	eof					{ return 0 }
    }
    set in_proc 0
}

#
# For each router... (this is main loop)
#
source_password_file $password_file
set in_proc 0
foreach router [lrange $argv $i end] {
    set router [string tolower $router]
    send_user "$router\n"

    # Figure out prompt.
    # Since autoenable is off by default, if we have it defined, it
    # was done on the command line. If it is not specifically set on the
    # command line, check the password file.
    if $avautoenable {
	set autoenable 1
	set enable 0
	set prompt "(#| \\(enable\\))"
    } else {
	set ae [find autoenable $router]
	if { "$ae" == "1" } {
	    set autoenable 1
	    set enable 0
	    set prompt "(#| \\(enable\\))"
	} else {
	    set autoenable 0
	    set enable $avenable
	    set prompt "(\\$|\\>|\\:)"
	    #set prompt ">"
            puts "prompt: $prompt"
	}
    }

    # look for noenable option in .cloginrc
    if { [find noenable $router] != "" } {
	set enable 0
    }

    # Figure out passwords
    if { $do_passwd || $do_enapasswd } {
      set pswd [find password $router]
      if { [llength $pswd] == 0 } {
	send_user "\nError: no password for $router in $password_file.\n"
	continue
      }
      if { $enable && $do_enapasswd && $autoenable == 0 && [llength $pswd]  \\\(enable\\\)"	{
				  set junk $expect_out(0,string);
				  regsub -all "\[\]\[]" $junk {\\&} prompt;
				}
    }

    if { $do_command } {
	if {[run_commands $prompt $command]} {
	    continue
	}
    } elseif { $do_script } {
	# If the prompt is (enable), then we are on a switch and the
	# command is "set length 0"; otherwise its "term length 0".
	if [ regexp -- ".*> .*enable" "$prompt" ] {
	    #send "set length 0\r"
	    send "\r"
	    send "set logging session disable\r"
	} else {
	    #send "term length 0\r"
	    send "\r"
	}
	expect -re $prompt	{}
	source $sfile
	close
    } else {
	label $router
	log_user 1
	interact
    }

    # End of for each router
    wait
    sleep 0.3
}
exit 0

January 26, 2008

nixlogin_pl

Filed under: f5, linux, nix, perl, rancid — Tags: , , , , — lancevermilion @ 7:26 am
#! /usr/bin/perl
##
## $Id: nixrancid.in,v 1.4 2008/01/21 10:43:25 lvermilion Exp $
##
#
# TODO
# * Add to personal rancid distribution.
# * OS Detection (maybe use variable to support user defined OS)
# * Collection of more system critical files
# * Fix netstat to not include Use/Expire fields on BSD
#
# Changelog
#
# v1.4  lvermilion 1-21-08
# Added support so the original F5 script works on Linux/BSD/Unix
# Added support for the command "sudo su root"
# Added BSDConfFile, since these files are BSD specific
# and we don't want them ran unless we are on a BSD system
# Added a variety of linux/BSD commands
# Removed F5 commands at this point until OS detection is completed.
#
# v1.3 lvermilion
# Add banner formatting so it is more clear what command was ran
# Add support for more F5 commands (profile/monitor/regkey/license/etc).
#
# v1.2  mashcraft 9-18-07
# Fixed invalid TERM causing intermitent failures
# Works as non-root user
# Added Platform info and static routes
#
# v1.1  mashcraft 8-2-07
# Debugging problems with HF8.
#
#
## Copyright (C) 1997-2004 by Terrapin Communications, Inc.
## All rights reserved.
##
## Copyright (C) 2007 by Omniture, Inc. Ver 1.1-1.2
## All rights reserved.
##
## Copyright (C) 2008 by Gheek.net Ver 1.3-1.4
## All rights reserved.
##
## This software may be freely copied, modified and redistributed
## without fee for non-commerical purposes provided that this license
## remains intact and unmodified with any RANCID distribution.
##
## There is no warranty or other guarantee of fitness of this software.
## It is provided solely "as is".  The author(s) disclaim(s) all
## responsibility and liability with respect to this software's usage
## or its effect upon hardware, computer systems, other software, or
## anything else.
##
## Except where noted otherwise, rancid was written by and is maintained by
## Henry Kilmer, John Heasley, Andrew Partan, Pete Whiting, and Austin Schutz.
##
#
# Based on rancid, this script handles F5 BigIP/(Li|U)nix,BSD systems.
# Modifications by Mike Ashcraft and Lance Vermilion.
#
# This script has been tested with Big-IP Version 9.1.2, 9.2.x and 9.3.1
#
# This script uses nixlogin.  You will need to configure the
# host in .cloginrc as follows:
#
# add user hostname		username
# add userprompt hostname	sshOnlyNoPrompt # The default prompt regex matches the last login message and causes problems
# add method hostname		ssh
# add password hostname		password
# add autoenable hostname	1
#
#  RANCID - Really Awesome New Cisco confIg Differ
#
# usage: nixrancid [-d] [-l] [-f filename | $host]
#
use Getopt::Std;
getopts('dfl');
$log = $opt_l;
$debug = $opt_d;
$file = $opt_f;
$host = $ARGV[0];
$clean_run = 0;
$found_end = 0;
$found_version = 0;
$found_env = 0;
$found_diag = 0;
$timeo = 90;				# clogin timeout in seconds

my(@commandtable, %commands, @commands);# command lists
my(%filter_pwds);			# password filtering mode

# This routine is used to print out the router configuration
sub ProcessHistory {
    my($new_hist_tag,$new_command,$command_string,@string) = (@_);
    if ((($new_hist_tag ne $hist_tag) || ($new_command ne $command))
	&& defined %history) {
	print eval "$command \%history";
	undef %history;
    }
    if (($new_hist_tag) && ($new_command) && ($command_string)) {
	if ($history{$command_string}) {
	    $history{$command_string} = "$history{$command_string}@string";
	} else {
	    $history{$command_string} = "@string";
	}
    } elsif (($new_hist_tag) && ($new_command)) {
	$history{++$#history} = "@string";
    } else {
	print "@string";
    }
    $hist_tag = $new_hist_tag;
    $command = $new_command;
    1;
}

sub numerically { $a  $b; }

# This is a sort routine that will sort numerically on the
# keys of a hash as if it were a normal array.
sub keynsort {
    local(%lines) = @_;
    local($i) = 0;
    local(@sorted_lines);
    foreach $key (sort numerically keys(%lines)) {
	$sorted_lines[$i] = $lines{$key};
	$i++;
    }
    @sorted_lines;
}

# This is a sort routine that will sort on the
# keys of a hash as if it were a normal array.
sub keysort {
    local(%lines) = @_;
    local($i) = 0;
    local(@sorted_lines);
    foreach $key (sort keys(%lines)) {
	$sorted_lines[$i] = $lines{$key};
	$i++;
    }
    @sorted_lines;
}

# This is a sort routine that will sort on the
# values of a hash as if it were a normal array.
sub valsort{
    local(%lines) = @_;
    local($i) = 0;
    local(@sorted_lines);
    foreach $key (sort values %lines) {
	$sorted_lines[$i] = $key;
	$i++;
    }
    @sorted_lines;
}

# This is a numerical sort routine (ascending).
sub numsort {
    local(%lines) = @_;
    local($i) = 0;
    local(@sorted_lines);
    foreach $num (sort {$a  $b} keys %lines) {
	$sorted_lines[$i] = $lines{$num};
	$i++;
    }
    @sorted_lines;
}

# This is a sort routine that will sort on the
# ip address when the ip address is anywhere in
# the strings.
sub ipsort {
    local(%lines) = @_;
    local($i) = 0;
    local(@sorted_lines);
    foreach $addr (sort sortbyipaddr keys %lines) {
	$sorted_lines[$i] = $lines{$addr};
	$i++;
    }
    @sorted_lines;
}

# These two routines will sort based upon IP addresses
sub ipaddrval {
    my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#);
    $a[3] + 256 * ($a[2] + 256 * ($a[1] +256 * $a[0]));
}
sub sortbyipaddr {
    &ipaddrval($a)  &ipaddrval($b);
}

# sub Platform  31-Jan-2007  Mike Ashcraft mashcraft@omniture.com
# This routine parses "cat filename"
sub Platform {
    print STDERR "    In Platform: $_" if ($debug);

    ProcessHistory("COMMENTS","","BO","\n!+----------------------------------------------+\n!|\n!| ####  Running $cmd\n!|\n!+----------------------------------------------+\n");

    while () {
        tr/15//d;
        last if (/^$prompt/);
        next if (/degC/);
        ProcessHistory("","","$cmd","$_");
    }
    $found_end = 1;
    return(0);
}

# sub BSDConfFile  21-Jan-2008  Lance Vermilion lvermilion@gheek.net
# This routine parses "cat filename"
sub BSDConfFile {
    print STDERR "    In BSDConfFile: $_" if ($debug);
        $uname=`uname`;

    ProcessHistory("COMMENTS","","BO","\n!+----------------------------------------------+\n!|\n!| ####  Running $cmd\n!|\n!+----------------------------------------------+\n") if ( $uname !~ /BSD/i );

    while () {
        last if ( $uname !~ /BSD/i );
        tr/15//d;
        last if (/^$prompt/);
        ProcessHistory("","","$cmd","$_") if ( $uname =~ /BSD/i );
    }
    $found_end = 1;
    return(0);
}

# sub ConfFile  31-Jan-2007  Mike Ashcraft mashcraft@omniture.com
# This routine parses "cat filename"
sub ConfFile {
    print STDERR "    In ConfFile: $_" if ($debug);

    ProcessHistory("COMMENTS","","BO","!+----------------------------------------------+\n!|\n!| ####  Running $cmd\n!|\n!+----------------------------------------------+\n");

    while () {
        tr/15//d;
        last if (/^$prompt/);
        if ( $cmd =~ /netstat/ )
        {
          next if /.*UHLW.*/
        }
        next if ($cmd =~ /config sync show/ && !/^\s+Status/);
        ProcessHistory("","","$cmd","$_");
    }
    $found_end = 1;
    return(0);
}

# sub DirList  31-Jan-2007  Mike Ashcraft mashcraft@omniture.com
# This routine parses directory listings.
#
# Disable color and make sure the date format is consistent
# For example: ll --time-style=long-iso --color=never
#
sub DirList {
    print STDERR "    In ConfFile: $_" if ($debug);

    ProcessHistory("COMMENTS","","BO","!+----------------------------------------------+\n!|\n!| ####  Running $cmd\n!|\n!+----------------------------------------------+\n");

    while () {
        tr/15//d;
        last if (/^$prompt/);
        ProcessHistory("","","$cmd","$_");
    }
    $found_end = 1;
    return(0);
}

# sub NoOutput  18-Sep-2007  Mike Ashcraft mashcraft@omniture.com
# This routine handles commands where you do not want any output
#
#
sub NoOutput {
    print STDERR "    In ConfFile: $_" if ($debug);

    while () {
        tr/15//d;
        last if (/^$prompt/);
    }
    $found_end = 1;
    return(0);
}

# dummy function
sub DoNothing {print STDOUT;}

# Main
@commandtable = (
	{'TERM=xterm'			=> 'NoOutput'},
	{'export TERM'			=> 'NoOutput'},
	{'uname -a'			=> 'Platform'},
	{'netstat -rn'			=> 'ConfFile'},
	{'cat /etc/passwd'		=> 'ConfFile'},
	{'cat /etc/group'		=> 'ConfFile'},
	{'cat /etc/hosts'		=> 'ConfFile'},
	{'cat /etc/resolv.conf'		=> 'ConfFile'},
	{'cat /etc/my.cnf'		=> 'ConfFile'},
	{'cat /etc/drbd.conf'		=> 'ConfFile'},
	{'cat /etc/fstab'		=> 'ConfFile'},
	{'cat /etc/rc.conf'		=> 'ConfFile'},
	{'cat /etc/iscsi/iscsid.conf' 	=> 'ConfFile'},
	{'cat /etc/modprobe.conf'	=> 'ConfFile'},
	{'cat /etc/sysconfig/network-scripts/ifcfg-bond0'		=> 'ConfFile'},
	{'cat /etc/sysconfig/network-scripts/ifcfg-bond1'		=> 'ConfFile'},
	{'cat /etc/sysconfig/network-scripts/ifcfg-eth0'		=> 'ConfFile'},
	{'cat /etc/sysconfig/network-scripts/ifcfg-eth1'		=> 'ConfFile'},
	{'cat /etc/sysconfig/network-scripts/ifcfg-eth2'		=> 'ConfFile'},
	{'cat /etc/sysconfig/network-scripts/ifcfg-eth3'		=> 'ConfFile'},
	{'cat /etc/sysconfig/network-scripts/ifcfg-eth4'		=> 'ConfFile'},
	{'cat /etc/sysconfig/network-scripts/ifcfg-eth5'		=> 'ConfFile'},
	{'alternatives --config java' 	=> 'ConfFile'},
	{'/sbin/chkconfig --list' 	=> 'ConfFile'},
	{'/usr/bin/yum list installed' 	=> 'ConfFile'},
#        {'bigpipe platform'             => 'Platform'},
#        {'bigpipe version'              => 'ConfFile'},
#        {'bigpipe list'                 => 'ConfFile'},
#        {'bigpipe base list'            => 'ConfFile'},
#        {'bigpipe profile list'         => 'ConfFile'},
#        {'bigpipe monitor list'         => 'ConfFile'},
#        {'bigpipe config sync show'             => 'ConfFile'},
#        {'cat /config/RegKey.license'           => 'ConfFile'},
#        {'bigpipe route static show'            => 'ConfFile'},
#        {'ls --full-time --color=never /config/ssl/ssl.crt'     => 'DirList'},
#        {'ls --full-time --color=never /config/ssl/ssl.key'     => 'DirList'},

);
# Use an array to preserve the order of the commands and a hash for mapping
# commands to the subroutine and track commands that have been completed.
@commands = map(keys(%$_), @commandtable);
%commands = map(%$_, @commandtable);

$cisco_cmds=join(";",@commands);
$cmds_regexp=join("|",@commands);

open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n";
select(OUTPUT);
# make OUTPUT unbuffered if debugging
if ($debug) { $| = 1; }

if ($file) {
    print STDERR "opening file $host\n" if ($debug);
    print STDOUT "opening file $host\n" if ($log);
    open(INPUT,"<$host") || die "open failed for $host: $!\n";
} else {
    print STDERR "executing nixlogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
    print STDOUT "executing nixlogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
    if (defined($ENV{NOPIPE})) {
	system "nixlogin -t $timeo -c \"$cisco_cmds\" $host  $host.raw 2>&1" || die "nixlogin failed for $host: $!\n";
	open(INPUT, "< $host.raw") || die "nixlogin failed for $host: $!\n";
    } else {
	open(INPUT,"nixlogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "nixlogin failed for $host: $!\n";
    }
}

# determine password filtering mode
if ($ENV{"FILTER_PWDS"} =~ /no/i) {
    $filter_pwds = 0;
} elsif ($ENV{"FILTER_PWDS"} =~ /all/i) {
    $filter_pwds = 2;
} else {
    $filter_pwds = 1;
}

ProcessHistory("","","","!RANCID-CONTENT-TYPE: nix\n!\n");
ProcessHistory("COMMENTS","keysort","B0","!\n");
ProcessHistory("COMMENTS","keysort","D0","!\n");
ProcessHistory("COMMENTS","keysort","F0","!\n");
ProcessHistory("COMMENTS","keysort","G0","!\n");
TOP: while() {
    tr/15//d;
    if (/\s?logout$/) {
	$clean_run=1;
	last;
    }
    if (/^Error:/) {
	print STDOUT ("$host nixlogin error: $_");
	print STDERR ("$host nixlogin error: $_") if ($debug);
	$clean_run=0;
	last;
    }
    while (/#\s*($cmds_regexp)\s*$/) {
	$cmd = $1;
	if (!defined($prompt)) {
	    $prompt = ($_ =~ /^([^#]+#)/)[0];
	    $prompt =~ s/([][}{)(\\])/\\$1/g;
	    print STDERR ("PROMPT MATCH: $prompt\n") if ($debug);
	}
	print STDERR ("HIT COMMAND:$_") if ($debug);
	if (! defined($commands{$cmd})) {
	    print STDERR "$host: found unexpected command - \"$cmd\"\n";
	    $clean_run = 0;
	    last TOP;
	}
	$rval = };
	delete($commands{$cmd});
	if ($rval == -1) {
	    $clean_run = 0;
	    last TOP;
	}
    }
}
print STDOUT "Done $logincmd: $_\n" if ($log);
# Flush History
ProcessHistory("","","","");
# Cleanup
close(INPUT);
close(OUTPUT);

if (defined($ENV{NOPIPE})) {
    unlink("$host.raw") if (! $debug);
}

# check for completeness
if (scalar(%commands) || !$clean_run || !$found_end) {
    if (scalar(%commands)) {
	printf(STDOUT "$host: missed cmd(s): %s\n", join(',', keys(%commands)));
	printf(STDERR "$host: missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug);
    }
    if (!$clean_run || !$found_end) {
	print STDOUT "$host: End of run not found\n";
	print STDERR "$host: End of run not found\n" if ($debug);
	system("/usr/bin/tail -1 $host.new");
    }
    unlink "$host.new" if (! $debug);
}

Blog at WordPress.com.