in reply to Firebird databases backup script

@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?

Replies are listed 'Best First'.
Re^2: Firebird databases backup script
by Anonymous Monk on Mar 02, 2012 at 01:00 UTC
      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.

        Hello!

        For now to cut out the first empty element from @files i`ve just used shift(@files);

        No, it's not a good idea, better make sure the path is valid before adding it, or at least before calling gbak.

        Using a file search and backup what it finds is also not a good idea for production code, maybe only as an learning exercise, for the reason you gave yourself, it may skip some databases without even noticing. Better to make a config with all databases to backup, check everything that you think (or even what you don't thing :) ) that it can go wrong and log the errors.

        use strict; use warnings; my @files; my @ext = (qw{fb gdb ib fdb}); my $data = "/opt/databases/"; # notice the final / foreach my $ext (@ext) { my @load = glob "$data*.$ext"; push (@files, @load); } foreach my $db (@files) { if (-f $db) { print "Found database: $db \n"; } else { print "skiping '$db'...\n"; } } # Alternatively: foreach my $ext (@ext) { my @load = glob "$data*.$ext"; foreach my $file (@load) { if (-f $file) { push (@files, $file); } else { print "Something is wrong, with '$file'!\n"; } } } foreach my $db (@files) { print "Found database: $db \n"; }

        Here is a piece from my backup script based on "IPC::Run3 - run a subprocess with input/ouput redirection", learned from Re^3: Using SYSTEM2 on Windows, thanks to ikegami :)

        use strict; use warnings; use IPC::Run3 qw( run3 ); my $FBUSER = 'SYSDBA'; my $FBPASS = 'masterkey'; # this is secret ;) my $gbak = 'gbak'; my $host = 'localhost'; my $db = '/opt/databases/test.fdb'; my $bk = '/opt/databases/backup/test.fbk'; # Backup the database on remote (or local) server my $cmd = qq{$gbak -backup -service "$host:service_mgr" "$db" "$bk" -u +ser "$FBUSER" -pass "$FBPASS"}; run3 $cmd, undef, \my @out, \my @err; print "STDOUT: $_" for @out; if (scalar @err > 0) { print "\n--- Errors ---------------------------------------------- +---\n"; print " $_" for @err; print "----------------------------------------------------------- +-\n\n"; } else { print " Backup completed successfully.\n"; }

        Regards, Ştefan

        Update: refactored code that was silently skipping elements from the list.