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

In the following code i want to make myself a program that will make it easier for me to do simple system administration tasks. Obviously the script is going to get a lot bigger but you see what im trying to do, Now the problem is instead of the & at the end of the line sending my command into the background, the shell sits and waits for the program to finish. I dont want that. Im also up for any positive critisism But please keep in mind i just started with perl a few days ago.
#!/usr/bin/perl use warnings; use strict; print "What do you want me to do?\n"; my $work = <STDIN>; chomp $work; if ($work eq "permissions") { print `sh /root/scripts/security.sh&`; print "job sent into background\n"; } elsif ($work eq "apachelog") { print `perl /root/scripts/apachelog.pl&`; print "job sent into background.\n"; } exit

Replies are listed 'Best First'.
Re: Executing a program or series of programs in perl.
by graff (Chancellor) on May 09, 2003 at 04:11 UTC
    The problem with this:
    print `sh /root/scripts/security.sh&`;
    is that perl will decide that there is probably (possibly) output to be returned by the sub-shell, and since the backticks are being used to "capture" the output for use by the script, it has to wait for the process to finish, even though the shell is being backgrounded.

    The way around that is to run the script in such a way that perl will not decide that it needs to wait for the process to finish so it can capture the output. Either of the following two alternatives would do:

    • redirect output within the command string -- perl will figure this out, and realize that there won't be any output to capture:
      `sh /some/job.sh >/dev/null &`;
    • use "system()" instead of backticks -- perl isn't supposed to even try capturing output from system calls, just the exit status:
      $exit_status = system( "/some/job.sh &" );
      Thanks man works like a charm, i switched it to using system instead of backticks and added >/dev/null like you said. Thank you both for your help.
        If you're running system maintenance tasks, you might want to use something like "sh foo.sh >> /var/log/maint.log &" in case something fails. There's nothing like having no idea why something ran a "chown -R root.wheel /home; chmod 700 /home" ;)

        ----mhoward----
Re: Executing a program or series of programs in perl.
by djantzen (Priest) on May 09, 2003 at 03:42 UTC

    I take it you'd like to send one command off to do its work while you start another one? You should look at forking a new process for each task, or using threads to divy up the processing work. For instance, here's a quick and dirty start:

    use strict; use warnings; use threads; my ($thr, @threads); INPUT: print "What do you want me to do?\n"; my $work = <STDIN>; chomp $work; if ($work eq "permissions") { $thr = threads->create(sub { print `sh /root/scripts/security.sh` }) +; push(@threads, $thr); #keep track of the thread print "security.sh sent into background\n"; goto INPUT; } elsif ($work eq "apachelog") { $thr = threads->create(sub { print `perl /root/scripts/apachelog.pl` + }); push(@threads, $thr); #keep track of the thread print "apachelog.pl sent into background.\n"; goto INPUT; } elsif ($work eq "exit") { $_->join() for @threads; # cause threads to return home after finish +ing. exit 0; }

    Hope that helps.


    "The dead do not recognize context" -- Kai, Lexx
      "I take it you'd like to send one command off to do its work while you start another one?" Kind of. I want to be able to choose a task, (theres going to be several.) and while it performs it (in unix its known as sending the command to "the background") i want to pick a task and have it run but while it does, i want my shell back. Your comment did help a lot. so ill just take it from there using your code as a reference, thanks a lot. When im done with this script ill be sure and post it for all my fellow Unix junkies out there.. =]

        Hmm, Perl might well be overkill in that case. Why not just use aliases in your normal shell or symlinks?


        "The dead do not recognize context" -- Kai, Lexx
        code@labs ~>> perl thread.pl thread.pl line 3: This Perl hasn't been configured and built properly for the threads module to work. (The 'useithreads' configuration option hasn't been used.) Having threads support requires all of Perl and all of the XS modules in the Perl installation to be rebuilt, it is not just a question of adding the threads module. (In other words, threaded and non-threaded Perls are binary incompatible.) If you want to the use the threads module, please contact the people who built your Perl. Cannot continue, aborting. BEGIN failed--compilation aborted at /usr/local/lib/perl5/5.8.0/mach/threads.pm line 28. Compilation failed in require at thread.pl line 3. BEGIN failed--compilation aborted at thread.pl line 3. code@labs ~>> Damn. I am the "people who built my perl." lol. looks like i have a job to do. Gotta get thread support built in.