Image

Image

Search This Blog

Friday, August 27, 2010

Print to fax

print to a network printer and the fax is sent! At the top of the page put the destination fax, recipient name, subject...; in order to hide those you need a mask.pdf file that contain just some white spaces that will be overlay-ed


#!/usr/bin/perl -w

# This perl script routes postscript printerdata from printerspooler to fax
#
# copy to /usr/lib/cups/backends/ and run this script from the commandline: echo blah | ./netfax
# it will tell if there are any dependancies unsolved: this tool is dependant upon the following:
# perl (we tested with v5.6 and its likely any v5 will do)
# perl modules Getopt-Long-2.32 and Mail-Sendmail-0.78
# sendfax (from the hylafax package)
# ps2ascii ps2pdf pdf2ps (comes with the ghostscript package)
# pdftk http://www.accesspdf.com/pdftk/
# a mask.pdf file that will hide the command parameters sent at the begining of your page by overlaying a white image
#
# After that you can add new printer to cups: lpadmin -p NetFax -E -v netfax.pl:
# Share the printer in samba and, if your fax server joined the domain, run:
# net -S localhost -U administrator rpc rights grant 'administrator' SePrintOperatorPrivilege
# in smb.conf [printers] section add -J %m to print command (tipically: lpr-cups -P %p -J %m -o raw $s)
# or add cups option = "%m" in the same section and make the drivers share [print$] writable
# Now from windows machine browse the fax server printers, right-click NetFax, choose properties,
# say NO when asked to install drivers, go to Advanced tab, and choose "New Driver". Choose
# some plain PS printer line Apple LaserWriter 12/640 PS and push the drivers to server.
# Now your printer can now be install on all workstations by a vbs script or by using printUI.dll.
#
# The accepted commands, placed at the begining of your faxed document are:
# 'Fax-Nr : XXX-XXXXX;(XXX)XXXXX~' the number can contain dashes or paranthesis. multiple numbers are separated by ;
# 'Clientid : AAAAAA AAAA~' the recipient name
# 'Subjectid : AAAA AAAAAAA~' the message subject
# 'E-m@il : AAA@BBBBBBB~' sender's email. if BBBBBBB matches a different windows machine name
# a winpopup message will be sent to that machine instead of originating machine
#
# Please note that every command line ends by a ~ character!
#
# in order to send a winpopup message add the following lines to notify_mail() function in /var/spool/fax/bin/notify
# HST = `echo $2 | sed -e 's/[^>]*@\([^ ]*\).*/\1/' -e '2.$d'`
# echo $1 | /usr/bin/smbclient -M $HST
#
# neXt - sorin@xxxxxxxx.com - June-2010
#

use strict;
use Getopt::Long;
use Mail::Sendmail;

# constants you must check if they are ok
my $ALLOWMULTIFAX = 1; # allow (1) or not (0) multiple faxdestinations
my $EMAILFROMDOC = 1; # get the emailaddress from samba (0) or the doc (1)
my $SENDFAX = "/usr/bin/sendfax"; # the command to send a fax
my $PS2ASCII = "/usr/bin/ps2ascii"; # the command to convert postscript to readable text
my $PS2PDF = "/usr/bin/ps2pdf"; # transform ps to pdf
my $PDFTK = "/usr/bin/pdftk"; # modify pdfs - used to overlay the mask over commands section
my $PDF2PS = "/usr/bin/pdf2ps"; # transform pdf back to ps
my $WATERMARK = "/etc/initsetup/mask.pdf"; # location of the overlay mask

# constants you can alter but should consider not to
my $TMPDIR = "/tmp/"; # the directory to store temporary files
my $MYNAME = "netfax"; # the name of this tool
my $LOGFILE = $TMPDIR . $MYNAME . ".log"; # the name of the logfile - debugging sessions only
my $PSFILE = $TMPDIR . $MYNAME . $$ . ".ps" ; # the name of the postscript temporary file
my $PSTMPFILE = $TMPDIR . $MYNAME . $$ . "work.ps" ; # the name of the postscript temporary file
my $MAILADDRESS = 'faxadmin@hfax'; # the default mailaddress for errormessages
my $MULTISEP = ";"; # if you have more than 1 faxnr on a line, they are seperated by ;
# this character should NOT appear in $DIGITS
my $DEBUG=0;

# constants you really should not touch !!!
my $FAXID = 'Fax-Nr[s]{0,1}\s*:\s*'; # search string for fax-nr
my $FAXIDS = 'Fax-Nrs\s*:\s*'; # search string for fax-nrs ( for multifax }
my $DIGITS = '0123456789+( ),-'; # digits allowed in the faxnr
my $MODEMLIKES = '0123456789+,'; # digits my modem will not reject: ,=wait +=int.access
# this should be a subset of $DIGITS
my $EMAILDOC = 'E-m@il :'; # the string to look for an emailaddress
my $CLIENTID = 'Clientid :'; # this is the recipient name
my $SUBJECTID = 'Subjectid :'; # the line with subject must contain this

########## from here on, leave the code alone, unless you are really sure ############

#variables
my @faxlines; # stores the raw faxlines
my @faxdest; # stores the faxnumbers
my $MultiFax = 0; # determines if ENDuser specified to multifax
my $mailaddress = ""; # how do we treat the errormessages
my $lpuser = ""; # username retrieved from lprng or lpd commandline
my $lphost = ""; # hostname retrieved from lprng or lpd commandline
my $client = " "; # the client name
my $subject = " "; # the message subject
my @emaillines; # stores the documentlines containing EMAILDOC
my @clienthost; # stores the temporary sender hostname
my @clientline; # stores the client name line
my @subjectline; # stores the subject line

#Check for arguments - if none, cups is initialising
if (@ARGV == 0) {

exit 0;
}

# check some dependencies
if ( ! -d $TMPDIR ) {
print("Error: temporary directory not found: ", $TMPDIR );
exit 1;
}
if ( ! -e $SENDFAX ) {
Log("Error: sendfax command not found: ", $SENDFAX );
exit 1;
}
if ( ! -e $PS2ASCII ) {
Log("Error: ghostscript command not found: ", $PS2ASCII );
exit 1;
}


# get usefull parameters
my $cupsfile = $ARGV[5]; # CUPS parses a filename with the printdata as the 6th parameer
# this could be undef (after lpr -d blah) or a filename (after a samba action)
my $cupsuser = $ARGV[1]; # CUPS paresed the username with the printdata as the 2nd parameter
# this is usually a user from localhost
GetOptions( 'h=s' => \$lphost, # LPD and LPRng parse host and user name under the -h and -n parameter
'n=s' => \$lpuser); # the postscript is parsed to it in a pipe - to be found in STDIN

my $fullhost = $ARGV[4]; #hostname is found here because in smb.conf I've added -P %m on print command

# let's extract the hostname in order to be added to email address
@clienthost = split(/\s+/,$fullhost);print $clienthost[0];
my $finalhost = $clienthost[0];

# ok lets find out where we can send the mail to
if ( ( $lphost ) and ( $lpuser ) ) { #if the user and host can be found on the commandline
$mailaddress = $lpuser . '@' . $lphost ;
} elsif ( $cupsuser) {
$mailaddress = $cupsuser . '@' . $finalhost ; # create "email" from user+hostname
} else {
$mailaddress = $MAILADDRESS; # or use the E-m@il defined in doc
}

# where is the printerdata?
if ( ( $cupsfile ) and ( -e $cupsfile ) ) {

$PSFILE = $cupsfile;
} else {
&SavePostscriptdata;
}
if ($DEBUG) {
Log("");
Log("------------------------------------------");
Log("");
}

# ok we have a postscriptfile, now
if ( &RetrieveRawFaxline ) { # we found one ore more lines
if ( &ExtractFaxnumber ) { # we could extract a real faxnumber
$client = &GetClientFromDoc; # get the Client Id
$subject = &GetSubjectFromDoc; # Get the Subject
if ($EMAILFROMDOC) {
$mailaddress = &GetEmailFromDoc; # Get the email from doc
}
if ($DEBUG) {
Log("Debug: email address = ",$mailaddress);
Log("Debug: postscript file = ",$PSFILE);
Log("Debug: cups file = ",$cupsfile);
}

&TrySending; # mask the header and send the fax
} else { # no real faxnumber could be extracted
&SendErrorMail;
Log("No Fax Number extracted");
}
} else { # no lines with faxnr found
&SendErrorMail;
Log("No Fax-Nr found");
}

# delete the temporary printfiles in case DEBUG is off
if (!$DEBUG) {
unlink $PSFILE;
unlink $PSTMPFILE;
unlink $PSTMPFILE . ".pdf";
unlink $PSTMPFILE . "clean.pdf";
}
Log("End of task");

# always exit gracefully.
exit 0;


# sub #################################################
# save the information in the pipe to the ps tmp file
sub SavePostscriptdata {
Log("sub SavePostscriptData");
open PS, ">".$PSFILE or die("Sorry, cannot open temporary postscript file $PSFILE .\n");
while () {
print PS $_ ;
}
close PS;
}

# sub #################################################
sub RetrieveRawFaxline {
my $CL = $PS2ASCII . " " . $PSFILE . " |";
my $ret = 0;

open CL, $CL; # carry out ps2ascii on the ps-file and return the output into perl
while (my $line=) {
chomp $line;
if ($line =~ /$FAXID/i) { # if the rawline matches with fax-nr
push @faxlines, $line ; # add it to the stack of matching lines
$ret++;
}
if ($line =~ /$FAXIDS/i) { # if the rawline matches with fax-nrs
$MultiFax = 1; # the userties to multifax
}
if ($line =~ /$CLIENTID/i) { # if the rawline matches with clientid
push @clientline, $line ; # add it to the stack of matching lines
if ($DEBUG) {
Log("Debug: clientline added - ",$line);
}
}
if ($line =~ /$SUBJECTID/i) { # if the rawline matches with subjectid
push @subjectline, $line ; # add it to the stack of matching lines
if ($DEBUG) {
Log("Debug: subjectline added - ",$line);
}
}
if ($line =~ /$EMAILDOC/i) { # if the rawline matches with "email"
push @emaillines, $line; # add it to the emailstack
if ($DEBUG) {
Log("Debug: emailline added - ",$line);
}
}
}
close CL;


# check the multifax setting
$MultiFax = $ALLOWMULTIFAX if $MultiFax; # ALLOWMULTIFAX overrides Multifax

return $ret;
}


# sub #################################################
sub ExtractFaxnumber {
my $ret = 0; # return value: 0=nothing found, more=ok

if ( $MultiFax ) { # extract all the faxnumbers you can find
for ( my $i=0; $i<@faxlines; $i++) { # for all the rawline push @faxdest, &GetFaxNumbersFrom($faxlines[$i]); #extract the numbers } $ret = @faxdest; } else { # just extract the first faxnumber in the first line my @fns = &GetFaxNumbersFrom($faxlines[0]); # extract the numbers from the first raw line if ( defined $fns[0] ) { # if it exists push @faxdest, $fns[0]; # put it on the return stack $ret++; } } return $ret; } # sub ################################################# sub GetFaxNumbersFrom { my @ret = (); my $rawline = shift; if ( defined $rawline ) { my $ModemRejects = "[^" . $MODEMLIKES . "]"; # regexp with non-modem chars if ( $rawline =~ /$FAXIDS/i ) { #line contains fax-nrs $rawline =~ s/$FAXID/;/gi ; # substitute all the Fax-Nr with an ; my @fnrs = split(/;/, $rawline); # split the line up between non-allowed digits for ( my $i=0; $i<@fnrs; $i++) { # for all the splitups my $f = $fnrs[$i]; my $goodpart = '([' . $DIGITS . ']*)[^' . $DIGITS . ']*.*$'; $f =~ s/$goodpart/$1/ ; # keep the goodpart $f =~ s/$ModemRejects//g; # remove all the non-modem characters if ( $f gt "" ) { # and if anything is left push @ret, $f; # add it to the return stack } } } else { # if we find a faxnr, take special care my $re = '^.*' . $FAXID; # search for fax-nr $re .= "("; $re .= "[" . $DIGITS . "]*"; # followed by allowed digits $re .= ")"; $re .= "[^" . $DIGITS . ']*.*$'; # followed by non-allowed digits $rawline =~ s/$re/$1/i ; # and extract the allowed part from it $rawline =~ s/$ModemRejects//g; # then remove all the non-modem characters if ( $rawline gt "" ) { # and if anything is left push @ret, $rawline; # add it to the return stack } } } return @ret; } # sub ################################################# sub GetEmailFromDoc { my $result = $mailaddress; # the default return is the existing mailaddress if (@emaillines > 0) { # if there are any emailsadresses found

# take the 1st found only, ignore the rest
# anything after the : is the emailaddress
#(undef, my $em) = split(/$EMAILDOC/, $emaillines[0]);
(undef, my $em1) = split(/$EMAILDOC/, $emaillines[0]);
#Log("pre space em1=",$em1);
# remove trailing and leading spaces

$em1 =~ s/^\s+//, $em1 =~ s/\s+$//;
# $em1 =~ s/^\s*(\S*)\s*$/$1/;
if ($DEBUG) {
Log("Debug: post space strip em1=",$em1);
}

# Log(" second split of em1=",$em1);
(my $em, my $em2) = split(/~/,$em1);
if ($DEBUG) {
Log("Debug: final em = ",$em);
}
# if there is a @ in the middle consider the email address valid
if ($em =~ /\w+@\w+/) {
$result = $em;
}
}
return $result;
}

# sub #################################################
sub GetClientFromDoc {
my $result = $client; # the default return is the existing client name
if (@clientline > 0) { # if there are any client lines found

# take the 1st found only, ignore the rest
# anything after the : is the clientname
#(undef, my $em) = split(/$EMAILDOC/, $emaillines[0]);
(undef, my $cl1) = split(/$CLIENTID/, $clientline[0]);
#Log("pre space cl1=",$cl1);
# remove trailing and leading spaces

$cl1 =~ s/^\s+//, $cl1 =~ s/\s+$//;
# $cl1 =~ s/^\s*(\S*)\s*$/$1/;
if ($DEBUG) {
Log("Debug: post space strip cl1=",$cl1);
}
# The line ends at ~
(my $cl, my $cl2) = split(/~/,$cl1);

if ($DEBUG) {
Log("Debug: final cl = ",$cl);
}
$result = $cl;
}
return $result;
}

# sub #################################################
sub GetSubjectFromDoc {
my $result = $subject; # the default return is the existing subject
if (@subjectline > 0) { # if there are any subject lines found

# take the 1st found only, ignore the rest
# anything after the : is the subject
(undef, my $su1) = split(/$SUBJECTID/, $subjectline[0]);
#Log("pre space su1=",$su1);
# remove trailing and leading spaces.

$su1 =~ s/^\s+//, $su1 =~ s/\s+$//;
# $su1 =~ s/^\s*(\S*)\s*$/$1/;
if ($DEBUG) {
Log("Debug: post space strip su1=",$su1);
}
# The line ends at ~
(my $su, my $su2) = split(/~/,$su1);
if ($DEBUG) {
Log("Debug: final su = ",$su);
}
$result = $su;
}
return $result;
}

# sub #################################################
sub TrySending {
for ( my $i=0; $i<@faxdest; $i++ ) { # for every found faxnumber # compile a commandline # check if file exists if (-e $PSFILE) { my $fcp = "cp " . $PSFILE . " " . $PSTMPFILE; system $fcp; } # transform to pdf, my $pspdf = $PS2PDF . " " . $PSTMPFILE . " " . $PSTMPFILE . ".pdf"; system $pspdf; # execute if ($DEBUG) { # and log it Log($pspdf); } # apply mask, my $wmark = $PDFTK . " " . $WATERMARK . " background " . $PSTMPFILE . ".pdf output " . $PSTMPFILE . "clean.pdf"; system $wmark; #execute if ($DEBUG) { # and log it Log($wmark); } # transform back to ps my $pdfps = $PDF2PS . " " . $PSTMPFILE . "clean.pdf " . $PSFILE; system $pdfps; # execute if ($DEBUG) { # and log it Log($pdfps); } # now send the fax my $fc = $SENDFAX . " -n -R -f " . $mailaddress . " -i \"" . $subject . "\" -d \"" . $client . "@" . $faxdest[$i] . "\" " . $PSFILE ; # my $fc = $SENDFAX . " -n -D -f " . $mailaddress . " -d " . $faxdest[$i] . " " . $PSFILE ; system $fc; # execute it if ($DEBUG) { # and log it Log($fc); } } } # sub ################################################# sub SendErrorMail { my $mh = "\n"; $mh .= "The faxnumber is not recognized in your fax of " . localtime() . "\n"; $mh .= "\n"; $mh .= "The faxnumber is recognised via this text:\n"; $mh .= " Fax-Nr : \n";
$mh .= "\n";

if ( $ALLOWMULTIFAX ) {
$mh .= " or\n";
$mh .= " Fax-Nrs : ; ; ... \n";
$mh .= "\n";
}

$mh .= "The 'Fax-Nr' part is not case sensitive.\n";
$mh .= "The characters allowed in the are: '" . $DIGITS . "'.\n";
$mh .= "\n";
$mh .= "Please correct and retry.\n";

sendmail( To => $mailaddress ,
From => 'Your hylafax gateway ',
Subject => 'Your facsimile request failed.',
Message => $mh
);

Log("sent errormail to $mailaddress");

}

# sub #################################################
sub Log {
open LG, ">>" . $LOGFILE;
print LG join(" ", @_), "\n";
close LG;
}

Saturday, June 19, 2010

Replacing a failing software raid drive in 10 easy steps

Un post de acum 3-4 ani pe care unul din amicii de la birou n-a fost in stare sa-l gasesca pe board-ul intern:

1 - cat /proc/mdstat and check for referrences to failing device
(sda = first sata hdd, sdb = the second one, so on...) the failed
partition should be something like /dev/sdb5 (I'm goin to refer to this
partition as /dev/sdYn and I'm going to call the good one /dev/sdXn)
2 - fdkisk -l /dev/sdX (where sdX is the GOOD hdd); fdisk -l /dev/sdY
- take a note of all partition configuration
3 - remove failed hdd: mdadm --manage /dev/md0 --fail /dev/sdYn ;
mdadm --manage /dev/md0 --remove /dev/sdYn (/dev/sdYn is the failed device!)
4 - phisically replace hdd (maybe with a shutdown before? :-) )
5 - sfdisk -d /dev/sdX | sfdisk /dev/sdY will create identical partitions
on the new hdd, similar to the ones on the good hdd (usually a /boot
of 100MB as primary partition and the rest as extended type FD "Linux
raid autodetect")
6 - check if the partitions are identical: fdkisk -l /dev/sdY
(compare with what you read at step 2)
7 - mdadm --manage /dev/md0 --add /dev/sdYn will add the new
partition tothe raid array
8 - watch the rebuid procedure: watch -n 10 cat /proc/mdstat (if
you are bored type ^C - the rebuid is done anyway)
9 - in order to make a copy of the boot partition too, do a mount
/dev/sdY1 /boot2 (the first partition is usually the 100MB /boot), then
do acd /boot ; find . -depth -print | cpio -padmV /boot2 ; grub-install /dev/sdY
10 - enjoy a beer, you have a working raid again!

Saturday, March 13, 2010

Spamfilter 2.0 - teoria initiala

Se implinesc in curand 4 ani de cand a inceput istoria asta. Acum 4 ani m-am apucat sa fac primul filtru antispam si habar n-aveam la ce ma inham (nu ca celelalte proiecte, care au venit dupa ar fi fost mai usoare, dimpotriva, da' inceputu' e intotdeauna mai greu). Dupa 4 ani filtru' meu inca e in topul celor mai bune din lume, blocand in medie cam 97% din spam, dar pe masura ce trece timpul, apar tot mai evidente limitarile versiunii 1,x, printre care lipsa unei metode de a permite fiecarui user sa-si gereze individual propriile mesaje, fara necesitatea unui admin, viteza foarte mica de raspuns in cazul cautarilor in mesajele din carantina, structura multi-layer, data de faptul ca am tot facut adaugiri la software-ul initial, dar nu am facut o reala integrare, ci am tot adaugat filtre unul in fata celuilalt - care poate induce intarzieri de pana la 5 minute in prelucrare (cu tot cu greylisting) si nu permite managementul centralizat al exceptiilor. Astfel, in versiunea 1.x, am ajuns sa am o lista de exceptii in postgrey, una in postfix si alta in spamd, iar lista din postgrey nici macar nu are o interfata web de management! Foarte important e si suportul de solidstate disk, care in v1 o cam suge rau de tot (se vede clar ca e adaugat dupa si mi-a dat cele mai multe batai de cap dealtfel).
Sigur, am si parti bune in 1.x, pe care le voi copia in v2, printre care: autoupdate/push updates, remote services monitoring, redir, call-home licensing...
Voi pastra combinatia postfix-spamassassin ca si structura de baza, dar proabil ca voi muta toata configuratia si storage-ul intr-o baza de date. Bazat pe scriptul de getuser probabil, voi crea o metoda autentificare a userilor la serverul principal de mail daca e exchange, iar pentru un server unix va trebui sa descopar cum imi pot autentifica userii la serverul pop3 - in felul asta nu am nevoie de alte combinatii user/parola pentru managementul mesajelor in carantina.
Trebuie sa fie posibil sa transfer bazele de date postgey si baesyan (actualmente berkleydb) in noul sistem, pen' ca sigur o sa trebuiasca sa upgradez din vechile sisteme sia ar fi bine sa pastrez rata mare de detectie pe care o am deja.
Trebuie sa investighez daca nu cumva cramfs/alt_filesystem_read_only in combinatie cu unionfs nu e o solutie mai buna pentru SSD-uri sau USB-flashuri (care actualmente sunt super-lente, iar pe masini cu >1mil de spamuri/luna crapa execrabil cu ext3fs chiar daca am mutat /tmp in ram si am limitat drastic scrierile pe disk).
Ca o ultima idee ar fi sa mut /etc/initsetup-ul intr-o interfata web, scapand astfel de nevoia initiala de a avea kbd+screen pentru instatalare si permitandu-mi poate sa modific cutia in ceva gen router cu doar un port rj45, un powercord si un powerbutton.

Edit: beta 1 is out! working on bug fixes now.
Edit2: spamfilter2, codename "miserable failure" is retired. let's welcome SpamFilter3!

Sunday, February 14, 2010

Laptop brightness

Elitebook-ul meu nu vrea sa mapeze Fn+F9 / Fn+F10 pentru brightness down/up. Fn+F11 merge (light sensor), dar F9 si F10 nu. Nici macar in xev nu apare nimic. Kde power management in schimb modifica brightness-ul in functie de power-profile pe care il aplica, e doar o problema de key-mapping. Mai mult, un echo 1-10 in /sys/class/backlight/acpi_video0/brightness imi schimba brightness-ul, deci tot ce am de facut e sa mapez miste taste care sa trimita un +1 / -1 in /sys/class/backlight/acpi_video0/brightness Nu pot face asta direct dintr-un script pentru ca va trebui sa-l fac suid root, iar mai nou (http://en.wikipedia.org/wiki/Setuid#setuid_on_executables ) nu prea mai poti sa suid un script. Sa scriem deci un programel care sa poata fi suid root.

#include 

void usage()
{
fprintf(stderr, "Usage: lcd-brightness [value]\n");
}

int main(int argc, char *argv[])
{
FILE *fp;
int bright = 0;
const char *kFileName =
"/sys/class/backlight/acpi_video0/brightness";

switch (argc) {
case 1:
fp = fopen(kFileName, "r");
fscanf(fp, "%d", &bright);
printf("%d\n", bright);
break;
case 2:
fp = fopen(kFileName, "w");
bright = atoi(argv[1]);
fprintf(fp, "%d\n", bright);
break;
default:
usage();
return -1;
}

fclose(fp);
return 0;
}

sa-l salvam undeva in path cu numele brightness si acum putem mapa niste taste in kde care sa-l apeleze:


Iar ca si command scriem:

brightness $(expr $(brightness) - 1); kdialog 
--passivepopup "Decrease Brightness to `cat 
/sys/class/backlight/acpi_video0/brightness`" 1
- asta va da un frumos notification pop-up cand este apelat:

Evident, trebuie mapata o combinatie si pentru Brightness up, care va face +1 in loc de -1 in comanda.

Sunday, February 07, 2010

Another Backup

Versiunea care foloseste tar (pentru ca cpio din debilian moare cand ti-e lumea mai draga si nu vreau sa pun cpio din surse)



#!/bin/sh
#       @(#) AUTOTBACK 2.8 09/12/09
# 
# 09/12/2009 (sorin@xxxxxxxx.com) mod for debian5. remove hit report. changed to use TAR
# 28/08/2008 (sorin@xxxxxxxx.com) modified for rhel5. skip /proc /sys /tmp
# modified 9/14/2000 to provide hit reporting on web site
#
#       Usage  -Command to be incorporated in cron of root for off Peak
#               automatic system TAR Backup.
#               Generates report in /var/autotback directory, mail and prints it.
#
#

####### Define Local Variables ################
RECIPIENT1=service@xxxxxxxx.com
RECIPIENT2=sorin@xxxxxxxx.com
PRINTER=HP4050
TAPE=/dev/st0
BACKDIR=/
EXCLUDE=/sys/*
EXCLUDE1=/proc/*
EXCLUDE2=/dev/*
EXCLUDE3=/var/run/*
EXCLUDE4=/tmp/*

###############################################

# System variables
LOCK=/var/autotback/backlock
DEFAULTDIR=/var/autotback
REPORTFILE=/var/autotback/backrep
TEMPFILE=/var/autotback/backtmp
TEMPFILE2=/var/autotback/backtmp2
ALLIST=/var/autotback/allist
LIST=/var/autotback/list
ERRORMSG="Another backup is running or the last backup has not finished well. Please check"
DELIMIT="================================================================================"

# define a remove lock and set a trap on exit
remove_lock()
{
       rm -f $LOCK
       }
# make sure we release the lock no matter how we exit, when we exit
trap remove_lock 0
# Check if another backup is running or if the script crashed in such way that the lock is still there, clear the lock
if [ -r $LOCK ]
then
 DIFF=`echo "\`date +%s\`-\`cat $LOCK\`" | bc`
 if [ $DIFF -gt 86400 ]; then echo "More than one day since backup is NOT running, autoclean..." >> $REPORTFILE; rm -f $LOCK; fi
 sed -i -e "1i\ $ERRORMSG" -e "1i\ $DELIMIT" -e "1i\ " $REPORTFILE
 echo $ERRORMSG >> $REPORTFILE
 echo $REPORTFILE | mail -s "Backup Failure on $HOSTNAME" $RECIPIENT1 $RECIPIENT2
 lp -d $PRINTER $REPORTFILE
 exit 5
fi

# Cleanup obsolete traces
cd $BACKDIR
rm -rf $DEFAULTDIR
if [ ! -d $DEFAULTDIR ]
then
       mkdir -p $DEFAULTDIR
fi

# Create lockfile
echo "`date +%s`">$LOCK

# Start backup
echo "                           Automatic Backup Report
(c)1991-2010 Xxxxxxxx Xxxxxxxxx Inc.
$DELIMIT

Backup of $BACKDIR on $HOSTNAME started at `date`
">>$REPORTFILE

# Create a list of what we have to backup and exclude
#cd $BACKDIR
#find . -depth -print  >$ALLIST
#grep -vE ".$EXCLUDE|.$EXCLUDE1|.$EXCLUDE2|.$EXCLUDE3|.$EXCLUDE4" $ALLIST >$LIST
echo "BACKUP started on `date`">$TEMPFILE

# Start saving at the begining of the tape
mt -f $TAPE rewind 2>>$TEMPFILE2
#cat $LIST | cpio -ocvB >$TAPE 2>>$TEMPFILE
tar --exclude=$EXCLUDE --exclude=$EXCLUDE1 --exclude=$EXCLUDE2 --exclude=$EXCLUDE3 --exclude=$EXCLUDE4 -cvpf $TAPE $BACKDIR >>$TEMPFILE 2>>$TEMPFILE2
backstat=$?
tail $TEMPFILE2 >>$REPORTFILE
echo "
Exit status = $backstat
">>$REPORTFILE
if [ $backstat -eq 0 ]
then
 echo "*** Backup COMPLETED OK ***">>$REPORTFILE
fi
if [ $backstat -eq 1 ]
then
 echo "*** Backup may be incomplete or have missing files ***">>$REPORTFILE
fi
if [ $backstat -eq 2 ]
then
 echo "*** Backup has encounter a fatal error. Please check ***">>$REPORTFILE
fi
echo "Tape Save finished on `date`
$DELIMIT
">>$REPORTFILE
# Check total nr of blocks reported by cpio
#set `tail -1 $TEMPFILE`
#BACKTOT=$1
#echo "Total of amount of Backup was $1 blocks.
echo "Verify of $BACKDIR on $HOSTNAME started at `date`
">>$REPORTFILE
# Tape rewind / Verify
mt -f $TAPE rewind 2>>$TEMPFILE2
# cpio -icvtB <$TAPE >>$TEMPFILE 2>>$TEMPFILE2
tar --exclude=$EXCLUDE --exclude=$EXCLUDE1 --exclude=$EXCLUDE2 --exclude=$EXCLUDE3 --exclude=$EXCLUDE4 --exclude=$EXCLUDE -tpvf $TAPE >>$TEMPFILE 2>>$TEMPFILE2
verstat=$?
tail $TEMPFILE2 >>$REPORTFILE
echo "
Exit status = $verstat
">>$REPORTFILE
if [ $verstat -eq 0 ]
then
 echo "***  Verify COMPLETED OK ***
">>$REPORTFILE
if [ $verstat -eq 1 ]
then
 echo "***  Verify may be incomplete ***
">>$REPORTFILE
if [ $verstat -eq 2 ]
then
 echo "***  Verify has encounter a fatal error. Please check ***
">>$REPORTFILE
cat $TEMPFILE >> $REPORTFILE
fi
echo "Tape Verify finished on `date`
">>$REPORTFILE
# Check nr of verified blocks reported by cpio and send warning if not ok
#set `tail -1 $TEMPFILE2`
#VERTOT=$1
#if [ "$BACKTOT" != "$VERTOT" -o $backstat -ne 0 -o $verstat -ne 0 ]
#then
#        echo "*** WARNING BACKUP TRANSFER TOTALS DID NOT MATCH ***">>$REPORTFILE
#        echo "***              PLEASE VERIFY                   ***
# ">>$REPORTFILE
#else
#        echo "*** Transfer Totals Concur ***
# ">>$REPORTFILE
#fi
echo $DELIMIT >>$REPORTFILE

# Send / Print the report
cat $REPORTFILE | mail -s "Backup Report $HOSTNAME" $RECIPIENT1 $RECIPIENT2
lp -d $PRINTER $REPORTFILE

# Remove lock, eject and exit
sleep 5
rm -f $LOCK
mt -f $TAPE rewoffl 2>>$TEMPFILE2
exit 0

Sunday, January 10, 2010

2k10

2010 - si se fac 5 ani de cand am ajuns aici.
[...]
La multi ani!

Blog Archive