dar is a nice free c program to back up to cd's. It's a bit better than tar, because it makes compressed archives exactly to the size specified, unlike tar, which you can only gzip after and split to cd sized chunks. It also is easy to make differential backups against a "catalog" made at each backup. You really need to read the dar tutorial and notes at the dar web site to understand all it's features. Anyways, for fun, I setup some scripts to run dar with IPC::Open3. The only glitch I ran into was needing a localized STDIN to get keyboard import, when cdwrite is called (by dar itself, which controlled the STDIN and STDOUT of cdwrite.

Anyways, this script mostly demonstrates a way of running IPC::Open3 to simulate "expect". It takes a quoted regex of the dar output string, and checks dar's output against the regex, which then can do whatever you want.

There are 2 scripts below, which should be copied to / and run by root. The dar_static binary which is mentioned can be built from the dar distro, and is used for restoring from scratch.

For testing, this script dosn't actually do any cdwrites,it makes some small images.e2fs and the catalog of the backup. It "prohibits" almost all directories with the -P option, so try to make sure that your /etc,/srv, and /mnt directories have at least 150 megs in them to test. That will make about 3 images. At the end of the script, where the catalog is made, I automatically mount the images for you, so disregard the "insert cd" message, and just press enter.

It should be pretty obvious how to change the script to actually write cd's. Also I make a log of all files archived, each slice on 1 line, with files separated by chr(1). This is not neccessary, because dar and dar_manager can create lists from the catalog or cd's. It is just for testing. Also I leave the restore script out because it is trivial, just copy all the files to / and run "dar_static -x root_full -R /". Also no clean up is performed, rm /tmp/dar and /etc/dar and the files left in /.

#######do-backup############################ #!/usr/bin/perl -w use strict; use IPC::Open3; use IO::Handle; use File::Path; use File::Copy; $|=1; my $basename = 'root_full'; my $backupdir = '/tmp/dar'; my $backuploc = "$backupdir/$basename"; if (! -d $backupdir){ mkpath($backupdir) || die "no permission to $bac +kupdir? $!"} my $lead = 'Adding file to archive: '; my $rx = qr/\Q$lead\E(.*)/; my $lead1 = 'Insert blank'; my $rxlog = qr/\Q$lead1\E(.*)/; my $darlog = 'dar.log'; open(LOG,">$darlog") or die $!; my @darvars = qq( -c $backuploc -s 50M -S 45M -v -E './cdwrite %p/%b.% +n.dar %b %n' -b -z -R / -X "*~" -X ".*~" -X "*.e2fs" -X "*.dar" -P 1saves -P dev/pts -P proc -P 1 -P 1out -P bin -P boot +-P c -P dev -P home -P lib -P mnt -P opt -P root -P sbin -P svr -P tmp -P usr -P var -Z tgz -Z gz -Z bz2 -Z zip -D); my $cmd = "dar @darvars"; my $pid = open3(Symbol::gensym, my($get_output),0,$cmd ); while(my $output = <$get_output>) { print "output->$output"; print LOG $1 . chr(1) if $output =~ /$rx/; if($output =~ /$rxlog/){LOG->autoflush(1);print LOG "\n"} } waitpid( $pid, 0 ) or die; $? and die; close LOG; print "\n\e[1;34mDone with slice creation Will create catalog now\e[0m\n\n"; createcat(); print "\e[1;34mFinished\e[0m\n"; exit; ###################################################################### +### sub createcat{ if (! -d 'etc/dar'){ mkpath('etc/dar') || die "no permission to /etc/d +ar ? $!"} print "\e[1;34mPlease insert cd number 1 Press Enter when ready\e[0m\n"; my $ok =<>; #system('mount', '-t','ext2','/dev/sr0',$backupdir); #for real writes system('mount', '-t','ext2','-o','loop','image1.e2fs',$backupdir); my $leadcat = 'The last file'; my $rxcat = qr/\Q$leadcat\E(.*)/; @darvars = qq(-A $backuploc -C $basename.'catalog'); $cmd = "dar @darvars"; my $pid1 = open3(Symbol::gensym, my($get_output),0,$cmd ); while(my $output = <$get_output>) { print "output->$output"; if($output =~ /$rxcat/){ system('eject','/dev/sr0'); system('umount','-f','-d',$backupdir); system('mount', '-t','ext2','-o','loop','image3.e2fs',$backupdir); print "\e[1;34mPlease insert last cd of set Press Enter when ready\e[0m\n"; } } waitpid($pid1, 0 ) or die; $? and die; move("$basename.catalog.1.dar","/etc/dar/$basename.catalog.1.dar"); system('umount','-f','-d',$backupdir); } #######__END__ of do-backup################################ ###########cdwrite###################################### #!/usr/bin/perl -w use strict; use File::Copy; use File::Path; $|=1; my $backupdir = '/tmp/dar'; my $numcopies = 1; my $filename =''; my $basename = ''; my $number = ''; unless ($filename = shift){die "no filename to burn $!\n"} unless ($basename = shift){die "no basename given $!\n"} unless ($number = shift){die "no cd number given $!\n"} print "\e[1;34mcdwrite->filename: $filename\e[0m\n"; print "\e[1;34mcdwrite->basename: $basename\e[0m\n"; print "\e[1;34mcdwrite->number: $number\e[0m\n"; my $count = 60; my $mntloc = 'tmp/dar/writemnt'; if (! -d $mntloc){ mkpath($mntloc) || die "no permission to $mntloc? $ +!"} #this seems to work for the 650m chunks print "\n\e[1;34mCreating empty image.e2fs \e[0m\n"; system ('dd','if=/dev/zero','of=image.e2fs','bs=1024k',"count=$count") +; print "\n\e[1;34mMaking ext2 filesystem on image.e2fs\e[0m\n"; system ('/sbin/mke2fs','-F','-b 2048','image.e2fs'); print "\n\e[1;34mMounting image via loop\e[0m\n"; system ('mount','-text2','-oloop','image.e2fs',"$mntloc"); print "\n\e[1;34mCopying files to image.e2fs\e[0m\n"; foreach('./restore','dar_static'){ my $result = copy($_,"$mntloc/$_"); if($result == 0){last} } #system('cp',$filename,"$mntloc/$basename.$number.dar"); copy($filename,"$mntloc/$basename.$number.dar"); &cdwriteout(); #unlink 'image.e2fs'; #delete images and slices unless first slic +e #if($number > 1){unlink "$backupdir/$basename.$number.dar"} #(for cata +log creation later) #####if you have room to save your images's my $old = 'image.e2fs'; my $new = 'image'.$number.'.e2fs'; rename $old,$new; #rmdir $mntloc or warn $!; exit; ###############################################################3 sub cdwriteout{ print "\n\e[1;34mDoing cdwrite\e[0m\n"; system('umount','-f','-d',$mntloc); for(1..$numcopies){ # system('eject','/dev/sr0'); print "\n\e[1;34mInsert blank cdrom labeled $number then press ente +r when drive is ready\e[0m\n"; { local *STDIN; open( STDIN, "< /dev/tty" ); my $ok = <STDIN>; } #use -dummy to test #system('cdrecord','-v','-dummy','-eject','speed=40','dev=1,0,0','imag +e.e2fs'); } }

In reply to Backing up with Open3 and dar by zentara

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.