Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

Error using system() and tar with several options

by gctaylor1 (Hermit)
on Apr 13, 2009 at 21:16 UTC ( #757281=perlquestion: print w/replies, xml ) Need Help??
gctaylor1 has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to replace a working bash script that uses tar and ssh, with a perl script using system() and the OS(Linux) provided tar and ssh, and am having trouble getting all of the options to work.

I'm trying to piece it together one step at a time and so far this is all I can get working:

my @args = ("/bin/tar", "czvf", $storageLocation.$archiveName, $arc +hiveDir ); system(@args) == 0 or die "system @args failed: $?";
If I try adding things like --exclude-from=$localdir I get various errors depending on where I put the--exclude-from.

Here's the line from the working bash script I'm trying to copy.

tar -czvf - -g $BACKEDUP --index-file $INDEXFILE --exclude-from $MYEX +CLUDES --totals /home/user1/ | ssh remote_machine "cat > /mnt/mount_p +oint/dir1/$FILENAME"
At this point I haven't tried to get the other options working as I thought this would be the simplest. I suspect piping the output to ssh will be a challenge as well and am saving that for last.

In the process of trying to get this working with system() I wondered if I should really be using Archive::Tar and Net::SSH::Perl? My primary reason for using the OS provided tar and ssh is that I thought it would be simpler and provides behavior that I'm familiar with. Then once I had this working I could switch to the more complex(?) task of using Archive::Tar and Net::SSH:Perl.

Any advice or pointers?

And to keep this all in perspective, I'm doing this project for learning purposes. I've been working my way through Perl books but am tired of doing exercises and want something useful to do.

Here's the full script:

#!/usr/bin/perl use strict; use warnings; my $excludes = "/home/user1/scripts/perl/backup/excluded_files.txt"; my $storageLocation = "/mnt/mount_point/dir1/"; my $archiveName = "backup.tar.gz"; my $archiveDir = "/home/user1/temp"; my @args = ("/bin/tar", "czv --exclude-from=$excludes -f", $storageL +ocation.$archiveName, $archiveDir ); system(@args) == 0 or die "system @args failed: $?";
Which produces the error:
/bin/tar: Old option `b' requires an argument. Try `/bin/tar --help' or `/bin/tar --usage' for more information. system /bin/tar czv --exclude-from=/home/user1/scripts/perl/backup/excluded_files.txt -f /mnt/mount_point/dir1/backup.tar.gz /home/user1/temp failed: 5 12 at /tmp/ line 12.

Replies are listed 'Best First'.
Re: Error using system() and tar with several options
by Crackers2 (Parson) on Apr 13, 2009 at 21:38 UTC

    When using the multi-argument form of system, the arguments get passed directly to the binary so there's no implicit split on whitespace. So your tar command sees the "czv --exclude-from=$excludes -f" as one big parameter and tries to interpret each character as a short option.

    Do this instead:

    my @args = ("/bin/tar", "czv", "--exclude-from=$excludes", "-f", $st +orageLocation.$archiveName, $archiveDir );
Re: Error using system() and tar with several options
by Tanktalus (Canon) on Apr 13, 2009 at 21:36 UTC

    What you probably should do, for learning purposes of course, is save this script as mytar:

    #!/usr/bin/perl use strict; use warnings; for (0..$#ARGV) { print "$_:[$ARGV[$_]]\n"; }
    And then see what comes out when you run mytar instead of tar.

    What you'll find is that "csv --exclude-from=$excludes -f" become one parameter, not individual parameters. However, if you change your system call to be system("mytar czv --exclude-from -f $storageLocation$archiveName $archiveDir"), you'll notice they're separate flags. That's because system (ok, the shell) will split the parameters on spaces if you pass in a single parameter, but not if you pass in multiple parameters. This makes it easy to pass in flags with spaces without having to worry about the shell's quoting rules inside perl's quoting rules.

    So, the fix? Keep separate flags separate:

    my @args = ( qw(/bin/tar czv), "--exclude-from=$excludes", qw(-f), $storageLocati +on.$archiveName, $archiveDir );
    That should help. :-)

Re: Error using system() and tar with several options
by linuxer (Curate) on Apr 13, 2009 at 21:34 UTC

    I wonder, why you want to replace a bash script with a perl script for this job?

    If the bash script is doing the job, why do you want to replace it?

    Even for learning purposes I don't see much use of doing such things.

    Did you try to separate each option in @args?

    my @args = ("/bin/tar", "-czv", "--exclude-from=$excludes", "-f", $s +torageLocation.$archiveName, $archiveDir ); system(@args) == 0 or die "system @args failed: $?";

    I am still wondering about which "old option 'b'" your tar is complaining... Crackers2's answer helped

Re: Error using system() and tar with several options
by gctaylor1 (Hermit) on Apr 13, 2009 at 23:36 UTC
    I swear I tried separating the arguments (and a million other things)before asking. But obviously did something wrong. :) Thanks for the responses! That works.
Re: Error using system() and tar with several options
by Utilitarian (Vicar) on Apr 14, 2009 at 09:04 UTC
    my @args = ("/bin/tar", "czv --exclude-from=$excludes -f ", $storage +Location.$archiveName, $archiveDir ); system(@args) == 0 or die "system @args failed: $?";
    The logical reason for tar choking on this is that it sees a -b flag, the logical reason for this is that you have an effective call to
    tar -czv -fbackup.tar.gz
    Put a space after the -f flag to resolve, that said, why are you replacing the shell script by having Perl spawn shells instead?
      This may seem odd, but I'm desperate for a project to work on and this seemed like something to do. Being a novice it's hard to find a project to jump in on.

      I'm burned out from doing book exercises and never really liked doing random exercises just for the sake of doing exercises. So this is practical from a project point of view even if it is impractical from a resource usage point of view.

      I do have this book on order Perl Testing: A Developer's Notebook and am reading Programming Perl but again, I need something to gain experience with and is practical.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://757281]
Approved by kyle
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (4)
As of 2018-05-25 20:55 GMT
Find Nodes?
    Voting Booth?