Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Firebird databases backup script

by Mery84 (Novice)
on Feb 28, 2012 at 13:47 UTC ( [id://956665]=perlquestion: print w/replies, xml ) Need Help??

Mery84 has asked for the wisdom of the Perl Monks concerning the following question:

Hello :) It`s my first attempt to learn perl. Until now I`ve preferred to write scripts in bash but they are not much flexible as i think perl can be. First things you should know - this script isn`t complete yet. Some of defined variables are not used yet. Issue coresponds to foreach loops. First one foreach reads filenames with correct extension defined in $bazaroz and put all of those filenames in table @files. Second foreach should for all files listed in @files perform operation defined in line 35 - system('./gbak.... When I launch this part of script which IMHO should work perl throws out:
./backup.pl Search pattern not terminated at ./backup.pl line 35.
Can you please explain me about what search pattern it says? whole script below:
#!/usr/bin/perl -w my $fbbin = "/opt/firebird/bin"; my $bazy = "/opt/databases"; my $bazaroz = "gdb"; my $shared = "/opt/shared"; my $kopie = "/home/mery/backup/temp"; my $kopietar = "/home/mery/backup/complete"; my $usbdev = "/dev/sdc1/"; my $localdir = "/mnt/storage/testy"; my $mailerr = "core-powiadomienia\@core.com.pl"; my $klient = "PanTester"; my $mailtopic = "Raport nocnej kopii zapasowe w firmie $klient"; #date settings my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(t +ime); my $ymd = sprintf("%04d-%02d-%02d-%02d-%02d-%02d",$year+1900,$mon,$mda +y,$hour,$min,$sec); my $type = $bazaroz; my $dir = $bazy; $type = "*.$type"; print "Szukam plikow z rozszerzeniem $type \n"; chdir ($dir); @files = qx(ls $type 2>&1); foreach (@files) { print "Baza: $_\n"; } #Backup foreach (@files) { system('cd $fbbin); print "Tworze kopie bazy $baza \n"; system('./gbak -user sysdba -password masterkey -BACKUP_DATABA +SE localhost:$bazy\/$_ $kopie\/$_.gbk') or print "Blad archiwizowania + bazy $baza \n"; print "Gotowa kopia bazy $baza \n"; } print "Koniec archiwizacji baz w firmie $klient w dniu $ymd \n";

Replies are listed 'Best First'.
Re: Firebird databases backup script
by Anonymous Monk on Feb 28, 2012 at 13:57 UTC

    Don't shell out to cd, use chdir

    single quotes do not interpolate, so print 'cd $fbbin' prints literally cd $fbbin not cd /opt/firebird/bin

    This is where you syntax error was, you were missing a closing single quote

    Don't do localtime date math yourself, use strftime

    use POSIX(); print POSIX::strftime('%Y-%m-%d-%H-%M-%S', localtime);

    Don't shell out to ls, use glob function, so  my @files = glob "*.$type";

    Thats it :)

      Thanks for your help. One issue fixed. Now I have problem to succesfully execute the most important backup command. Second foreach loop have system command (below pasted latest, fixed a bit version):
      foreach (@files) { chdir($fbbin); print "Tworze kopie bazy $_ \n"; system('./gbak -user sysdba -password masterkey -BACKUP_DATABA +SE localhost:$bazy$_ $kopie$_.gbk') or print "Blad archiwizowania baz +y $_ \n"; print "Gotowa kopia bazy $_ \n"; }
      I`ve try it in many ways in single quotes `` or '' also in "" always command output is the same:
      gbak: ERROR:requires both input and output filenames gbak:Exiting before completion due to errors sh: 2: /mnt/storage/testy/simplemarketing.gdb: not found sh: 3: .gbk: not found Gotowa kopia bazy simplemarketing.gdb
      It looks like the ./gbak command from Firebird binaries don`t reads the variables correctly. By hand this command looks:
      ./gbak -user sysdba -password masterkey -BACKUP_DATABASE localhost:/op +t/databases/demo.gdb /mnt/storage/testy/demo.gdb.gbk
      and works without problems. In my script: /opt/dabasaes/ comes from $bazy demo.gdb - database filename should be inserted by $_ from table @files destination dir /mnt/storage/testy/ should be inserted by $localdir and extended by .gbk file extension. But from perl script this command don`t work....

        Single quotes do not interpolate, but double quotes do, so use "" (this part explained in basic syntax section of perlintro )

        Its time like these I yearn for a perlquote :)

Re: Firebird databases backup script
by sundialsvc4 (Abbot) on Feb 28, 2012 at 20:42 UTC

    I suggest that you begin your script with:

    use strict; use warnings;
    (immediately after the shebang...) and that you do so, forevermore, routinely.   This will tell Perl to detect many common typos and other mistakes.

    I certainly agree 150% with your assessment of using Perl vs. using Bash.   Mind you, I am not “bashing bash” when I say that Perl has earned its reputation as “the Swiss Army® Knife of pragmatic computer programming.”   (One thing that can unquestionably be said about Mr. Larry Wall, and his many successors since that time, was that:   they knew what very-practical tool they needed, and they built it very well.)   Many folks are initially caught off-guard at first glance by what at first seems to be “loosey goosey” approach of Perl, but, the longer you look at it and consider it, the more wise it reveals itself to be.   (Aye, despite its inevitable warts.)   The time that you spend learning about this language, and delving into the vast CPAN library which supports it, is time that you will one day indeed have been very glad to have spent.

Re: Firebird databases backup script
by Mery84 (Novice) on Feb 28, 2012 at 21:34 UTC
    Hello,
    @Anonymous Monk
    As I mentioned earlier I`ve tried both way in '' and "" and both don`t work.

    @sundialsvc4
    Thank for your nice opinion :).

    For now i`ve fixed script a bit and translated it from polish descriptions and var names to english for easier reading for you :). Latest version of script:
    #!/usr/bin/perl -w use strict; use warnings; #Variables my $fbbin = "/opt/firebird/bin/"; my $data = "/opt/databases/"; my $ext = "gdb"; #my $shared = "/opt/shared/"; my $tempdir = "/opt/backup/"; #my $destdir = "/home/mery/backup/complete/"; #my $usbdev = "/dev/sdc1/"; #my $localdir = "/mnt/storage/testy/"; #my $mailerr = "core-powiadomienia\@core.com.pl"; my $klient = "PanTester"; my $mailtopic = "Raport nocnej kopii zapasowej w firmie $klient"; use POSIX(); print POSIX::strftime('%Y-%m-%d-%H-%M-%S', localtime); #Create database filenames table @files my $type = $ext; my $dir = $data; $type = "*.$type"; print "looking for files with extension $type \n"; chdir ($dir); my @files = qx(ls $type 2>&1); foreach (@files) { print "Found database: $_\n"; } # This loop run external gbak backup command to create $_.gbk files as + output in $tempdir foreach (@files) { chdir ($fbbin); # print "Tworze kopie bazy $_ \n"; system("./gbak -user sysdba -password masterkey -BACKUP_DATABA +SE localhost\:$data$_ $tempdir`$_.gbk`") or die "Blad archiwizowania +bazy $_ \n"; # print "Gotowa kopia bazy $_ \n"; }
    Output:
    2012-02-28-22-23-33looking for files with extension *.gdb Found database: demo2.gdb Found database: demo.gdb Found database: SimpleMarketing2.gdb Found database: simplemarketing.gdb gbak: ERROR:requires both input and output filenames gbak:Exiting before completion due to errors sh: 1: demo2.gdb: not found sh: 2: .gbk: not found sh: 3: /opt/backup/: Permission denied gbak: ERROR:requires both input and output filenames gbak:Exiting before completion due to errors sh: 1: demo.gdb: not found sh: 2: .gbk: not found sh: 3: /opt/backup/: Permission denied gbak: ERROR:requires both input and output filenames gbak:Exiting before completion due to errors sh: 1: SimpleMarketing2.gdb: not found sh: 2: .gbk: not found sh: 3: /opt/backup/: Permission denied gbak: ERROR:requires both input and output filenames gbak:Exiting before completion due to errors sh: 1: simplemarketing.gdb: not found sh: 2: .gbk: not found sh: 3: /opt/backup/: Permission denied
    /opt/backup is chmoded to 777 and owned by nobody.nogroup (it`s testing virtual machine so i`m not worried about security ;)) so i don`t understand why permission denied.

      @Anonymous Monk As I mentioned earlier I`ve tried both way in '' and "" and both don`t work.

      But for different reasons. Using single quotes like that could never have worked, it would have never done what you are trying to do.

      Also, as system documents, using system or die is wrong, you need to use system(@args)==0 or die.

      or use autodie qw/ system /; and let autodie take care of the dying.

      This means the actual command you're trying to execute is wrong -- I see some backticks which looks like an error to me.

      What is the command you're trying to execute? What would it look like if you typed it in on the commandline, no variables, just the final text? Dumper it and see what you're trying to actually execute ( see

      Tutorials: Basic debugging checklist for Dumper)

      You might have better luck narrowing it down by giving system a list, as in

      use autodie qw/ system /; my @args = qw[ ./gbak -user sysdba -password masterkey -BACKUP_DATABAS +E ]; push @args, "localhost:$data$_" , "$tempdir$_.gbk"; use Data::Dumper; print "Trying to system(@args) ", Dumper(\@args ), "\n"; system @args;

      See systems for all the caveats, and use autodie, and when something doesn't work right, remember Basic debugging checklist

        Hello,
        By hand gbak command looks:
        ./gbak -user sysdba -password masterkey -BACKUP_DATABASE localhost:/opt/databases/demo.gdb /opt/backup/demo.gdb.gbk
        and works fine.
        Also in simple script:
        chdir ($fbbin); system("./gbak -user sysdba -password masterkey -BACKUP_DATABA +SE localhost:/opt/databases/demo.gdb /opt/databases/demo.gbk")==0 or +die "Failed to create backup file \n";

        I see where is the issue with loading details from variables to system command but i don`t have any idea how to fix it.
        See:
        foreach (@files) { chdir ($fbbin); print "./gbak -user sysdba -password masterkey -BACKUP_DATABAS +E localhost:$data$_ $tempdir$_.gbk \n";
        Gives me output:
        ./gbak -user sysdba -password masterkey -BACKUP_DATABASE localhost:/op +t/databases/simplemarketing.gdb /opt/backup/simplemarketing.gdb .gbk
        This output should be in one row not in three ;). It looks like enter pressed always after $_ variable loaded from @files table which contains databases filenames. Any ideas how to fix it?
Re: Firebird databases backup script
by Mery84 (Novice) on Mar 01, 2012 at 12:07 UTC
    @Anonymous Monk
    Once again thanks for your help. Glob solves line break issue but... brings another one problem.

    #Create database filenames table @files my @ext = ("fb", "gdb", "ib"); my $data = "/opt/databases"; foreach (@ext) { my $load = glob "$data*.$_"; push (@files, $load); } foreach (@files) { print "Found database: $_ \n"; }
    /opt/databases contains 5 files. Two with fb extension, three with gdb. Foreach loop should (as i think) push to @files table all filenames with extensions from @ext. Now this code works only for first extension on table @ext and second issue it inserts me in table @files first and last item empty. The execution result looks:
    Found database: Found database: /opt/databases/DEMO.fb Found database: /opt/databases/demo2.fb Found database:
    The first and last are unwanted, they breaks the script at gbak - it dies due to empty filename to backup.
    Second thing - why foreach loop breaks after first item from list and don`t push to @files other files as i think it should?
        Thank you. Now I see where I`m wrong. More than one result is output of glob but I insert them to variable but should be inserted to table.
        I`ve fixed it to @files
        foreach (@ext) { my @load = glob "$data*.$_"; push (@files, @load); }
        but still first element of @files table is empty.
        The output:
        2012-03-02-09-46-09: Found database: 2012-03-02-09-46-09: Found database: /opt/databases/DEMO.fb 2012-03-02-09-46-09: Found database: /opt/databases/demo2.fb 2012-03-02-09-46-09: Found database: /opt/databases/demo.gdb 2012-03-02-09-46-09: Found database: /opt/databases/demo2.gdb 2012-03-02-09-46-09: Found database: /opt/databases/demo3.gdb 2012-03-02-09-46-09: Found database: /opt/databases/simplemarketing.g +db 2012-03-02-09-46-09: Found database: /opt/databases/SimpleMarketing2. +gdb
        The script dies at first element because gbak can`t perform backup on empty file as source.
        For now to cut out the first empty element from @files i`ve just used  shift(@files); but I`m not sure is this a good idea. I don`t know why it push first element empty to @files and if in some conditions e.g. on other server the first element will not be empty the shift will be cutting out one of databases from backup.
        Is there a better way to check array for empty elements and if exist shift them? I have two ideas - insert if in foreach loop or do another one foreach loop for @files to remove the empty elements. In both ideas I don`t know how to correctly detect empty elements.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://956665]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (7)
As of 2024-03-28 22:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found