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

Statement to do something if <> calls $remove.
if ($remove) { $remove = lc($remove); my $removeq = $remove; my %remove_cmd = ( remove => "rmquedev -d $removeq -q $removeq" ); print "Are you sure you want to remove print queue \"$removeq\" [Y +/n]?"; $_ = <>; chomp($_); $_ = "Y" if ( length($_) == 0 ); if ( $_ =~ /[Yy]/ ) { # Wait for user-input system( $remove_cmd {'remove'} ); print "Prepairing to remove \"$removeq\" from the CC_print.printers file.\n" +; sleep 2; &clean_the_file(); } else { die "You chose NOT to remove queue \"$removeq\"\n"; } }

Sub-process being called
sub clean_the_file { my $sourcefile = "/u/ccsys/CC_print.printers"; # Keep a dedicated backup of CC_print.printers if ( !-t "/root/CC_print.printers.bkp" ) { system("touch /root/CC_print.printers.bkp"); system("cp -R $sourcefile /root/CC_print.printer.bkp"); } if ( -t "/root/CC_print.printers.bkp" ) { system("cp -R $sourcefile /root/CC_print.printer.bkp"); # grab the sourcefile and the string to remove as the first and second + arguments my ( $sourcefile, $removeq ) = @_; # create a temporary file system("touch /u/ccsys/CC_print.printers.bkp_mkpq"); my $tempfile = "/u/ccsys/CC_print.printers.bkp_mkpq"; # extract lines from $sourcefile which do NOT have the string to + remove # note that the \' inserts ticks so that strings with spaces can + work, too `grep -v $removeq $sourcefile > $tempfile`; sleep 1; print "Waiting to unlink..\n"; # delete source file, then rename working file unlink($sourcefile); rename( $tempfile, $sourcefile ); system("rm -rf $tempfile"); } }


Program is dying as the sub(); is being called with nothing telling me why!

I'm using Strict and Warnings, could anyone offer some insight?

UPDATE!!
The data I was trying to parse looks like this
#CC:'queue-01':ps|2|-5|1.0|1.0:tp'
#CC:'queue-02':ps|2|-5|1.0|1.0:tp'
#CC:'queue-03':ps|2|-5|1.0|1.0:tp'
#CC:'queue-04':ps|2|-5|1.0|1.0:tp'
#CC:'queue-05':ps|2|-5|1.0|1.0:tp'
#CC:'queue-06':ps|2|-5|1.0|1.0:tp'
#CC:'queue-07':ps|2|-5|1.0|1.0:tp'
#CC:'queue-08':ps|2|-5|1.0|1.0:tp'
#CC:'queue-09':ps|2|-5|1.0|1.0:tp'

I have changed my code and now I can execute which printer needs to be deleted from the file successfully, while maintaining a dedicated backup of the file before it was changed :).
sub cleanthefile { my @filehandles; # Keep varibles in same order as they were passed to the sub-routi +ne my ( $removeq, $sourcefile, $tempfile, $backup ) = @_; # Keep a dedicated backup of CC_print.printers if (-e "$_[3]" ) { system ( "cp -R $_[1] $_[3]" ); # create a temporary file if ( !-e "$_[1]") { system("touch $_[2]"); } # extract lines from $sourcefile which do NOT have the string to + remove # note that the \' inserts ticks so that strings with spaces can + work, too if ( -e "$_[1]") { # system ("cat $sourcefile \| grep -v $removeq $sourcefile > $ +tempfile"); system ( "grep -v $_[0] $_[1] > $_[2]" ); sleep 1; print "Waiting to unlink..\n"; # delete source file, then rename working file unlink($_[1]); rename( $_[2], $_[1] ); system("rm -rf $_[2]"); } } else { system("touch $_[3]"); system("cp -R $_[1] $_[3]"); } }

Command that was run mkpq -r queue-03

As you can see, the queue-03 is gone!
#CC:'queue-01':ps|2|-5|1.0|1.0:tp'
#CC:'queue-02':ps|2|-5|1.0|1.0:tp'
#CC:'queue-04':ps|2|-5|1.0|1.0:tp'
#CC:'queue-05':ps|2|-5|1.0|1.0:tp'
#CC:'queue-06':ps|2|-5|1.0|1.0:tp'
#CC:'queue-07':ps|2|-5|1.0|1.0:tp'
#CC:'queue-08':ps|2|-5|1.0|1.0:tp'
#CC:'queue-09':ps|2|-5|1.0|1.0:tp'

Thanks again everyone!

Replies are listed 'Best First'.
Re: Program unsuspectingly dies with no reason why.
by kyle (Abbot) on Feb 13, 2008 at 20:56 UTC

    Here are the relevant lines:

    &clean_the_file(); sub clean_the_file { my ( $sourcefile, $removeq ) = @_; `grep -v $removeq $sourcefile > $tempfile`; }

    You're calling clean_the_file with no arguments, and passing those (no) arguments on to grep, which is going to hang waiting for input.

    That's my guess.

      I think I'm going to have to agree with Kyle. Does anyone think I should remove the grep -v function from backticks and have Perl handle it with the system(); call? I think I'm going to try it this way, so far not much luck with the issue. Thanks for all of the replies so far!

        Backticks are for when you want to capture the output of some shell command. In this case, you're redirecting output to a file, so backticks won't do that. Your backticks also don't give you anything in a void context.

        That said, putting the same thing in system won't help either. It's the underlying grep that's hanging.

        I think that grep needs to get some arguments. You could do this, minimally:

        `grep -v $removeq $sourcefile /dev/null /dev/null > $tempfile`;

        That won't hang, but it also won't work until $removeq and $sourcefile are right. You probably ought to be passing them in initially:

        &clean_the_file( $sourcefile, $removeq );

        I can't tell what $sourcefile should be, though.

        Hope this helps.

        I think you missed Kyle's point. Using system instead of backticks to call grep should not matter here.

        To illustrate Kyle's point, add these lines just before your grep line:

        print "removeq = $removeq\n"; print "sourcefile = $sourcefile\n";

        I suspect these variables will not contain what you expect them to.

Re: Program unsuspectingly dies with no reason why.
by starX (Chaplain) on Feb 13, 2008 at 20:41 UTC
    It might have something to do with the line &clean_the_file(); The & denotes a function reference, but you're not calling the function via a reference. If you use clean_the_file(); I think it'll take care of the issue.

    Update: Never mind, I'm a loser.

      Errm, no. Something like \&clean_the_file would be a reference. While calling subs with the leading sigil does have an effect, it's not going to stop &clean_the_file() from being called in any sane circumstance. See perlsub.

      (Of course if someone has created just such a circumstance then they deserve what they get for using prototypes where they shouldn't :)

      The cake is a lie.
      The cake is a lie.
      The cake is a lie.

      Actually, &foo() is a call to the sub foo. To take a reference to the sub, use \&foo.

      sub foo { print "foo: ", $_[0], "\n" } &foo( 'called with &' ); foo( 'called with no &' ); my $foo_ref = \&foo; $foo_ref->( 'called via reference' ); &$foo_ref( 'called via & and reference' ); __END__ foo: called with & foo: called with no & foo: called via reference foo: called via & and reference

      The only special thing about &foo() vs. foo() is that the former will disable any prototypes the sub may have.