Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Trying to understand the System function

by mifflin (Curate)
on Jul 28, 2003 at 17:54 UTC ( [id://278518]=perlquestion: print w/replies, xml ) Need Help??

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

When I run the following script I get errors when I use the list form if the system call. Why is this?
system('rm test?.out 2> /dev/null'); print " ------\n test 1\n"; $rc = system('/usr/bin/ps', '>' , 'test1.out', '&'); print ' rc=',$rc,"\n"; print " test1.out not created\n" unless -e 'test1.out'; print " ------\n test 2\n"; $rc = system('/usr/bin/ps > test2.out &'); print ' rc=',$rc,"\n"; print " test2.out not created\n" unless -e 'test2.out'; print " ------\n test 3\n"; $rc = system('/usr/bin/ps', '>' , 'test3.out'); print ' rc=',$rc,"\n"; print " test3.out not created\n" unless -e 'test3.out';
The output is...
------ test 1 usage: ps [ -aAdeflcjLPy ] [ -o format ] [ -t termlist ] [ -u userlist ] [ -U userlist ] [ -G grouplist ] [ -p proclist ] [ -g pgrplist ] [ -s sidlist ] 'format' is one or more of: user ruser group rgroup uid ruid gid rgid pid ppid pgid sid ta +skid pri opri pcpu pmem vsz rss osz nice class time etime stime f s c lwp nlwp psr tty addr wchan fname comm args projid proje +ct rc=256 test1.out not created ------ test 2 rc=0 ------ test 3 usage: ps [ -aAdeflcjLPy ] [ -o format ] [ -t termlist ] [ -u userlist ] [ -U userlist ] [ -G grouplist ] [ -p proclist ] [ -g pgrplist ] [ -s sidlist ] 'format' is one or more of: user ruser group rgroup uid ruid gid rgid pid ppid pgid sid ta +skid pri opri pcpu pmem vsz rss osz nice class time etime stime f s c lwp nlwp psr tty addr wchan fname comm args projid proje +ct rc=256 test3.out not created
As you can see only Test 2 is successful. Why is this? Is there a correct way to execute a statement with an ampersand as the last char using the list form if system?

These tests were done on a Sun box using Perl 5.8.

edited: Mon Jul 28 18:28:33 2003 by jeffa - code tags

Replies are listed 'Best First'.
Re: Trying to understand the System function
by sauoq (Abbot) on Jul 28, 2003 at 18:01 UTC
    When I run the following script I get errors when I use the list form if the system call.

    You are using shell redirection (via '>') and backgrounding (via '&'). When you use the system LIST form, a shell is not started. The ps command doesn't know what to do with the '>' and '&' arguments you are giving it.

    -sauoq
    "My two cents aren't worth a dime.";
    
      So if we forget the redirection (via >) right now, how would I execute a command in background using the list form of the system command?
      Is this possible?

        Don't use system. Just fork and exec instead.

        -sauoq
        "My two cents aren't worth a dime.";
        
Re: Trying to understand the System function
by blue_cowdawg (Monsignor) on Jul 28, 2003 at 18:18 UTC

        Is there a correct way to execute a statement with an ampersand as the last char using the list form if system?

    My first question is why you want to background this process when the first thing you are doing is checking for the existance of the output file. It is concievable that your process execution will not happen in time before Perl does its test for the file.

    My next observation is that the reason your "ps" is failing is system thinks you are passing the ">", "test1.out" and "&" as arguments to "ps;" versus redirecting the output of "ps" to "test1.out".

    is probably more in line with what you have in mind or if you are really intent on backgrounding the "ps" command.

    Yet another way instead of using system would be as follows:

      my $pid=spawn("/usr/bin/ps","test1.out"); waitpid($pid,0); print "test1.out not created" if not -e "test1.out"; # # More code # sub spawn { my($cmd,$redirect)=@_; my $pid=fork(); return $pid if $pid > 0; if ( $pid == 0 ) { # Child process exec sprintf("%s > %s",$cmd,$redirect) or die "Could not exec $cmd:$!"; } else { # uh-oh... could not fork die "Could not fork $cmd : $!"; } }
    This way you background the process and wait for it before you do your test for file creation. YMMV based on how waitpid is implemented on your local system.

    There are lots of other ways of doing this, but this is my (current) favorite.

    References:

    • perldoc -f fork
    • perldoc -f exec
    • perldoc -f waitpid


    Peter @ Berghold . Net

    Sieze the cow! Bite the day!

    Test the code? We don't need to test no stinkin' code! All code posted here is as is where is unless otherwise stated.

    Brewer of Belgian style Ales

      What's the advantage of the spawn function over just using system?

        Done in that way, there is no difference: exec will start a shell, just as system does.

        What the OP wants is:

        • fork, then in the child process:
        • open the output file and attach it to STDOUT
        • exec with the list of parameters (it will not invoke a shell)
        • meanwhile, in the parent process, you can wait for the child to finish

        For more info, you can look at "perlipc" and the "fork" entry in "perlfunc"

        -- 
                dakkar - Mobilis in mobile
        

        Most of my code is tested...

        Perl is strongly typed, it just has very few types (Dan)

Re: Trying to understand the System function
by cleverett (Friar) on Jul 28, 2003 at 17:58 UTC
    Doesn't the ampersand as the last char put the command you're trying to execute into the background?

    If that's what you really want, perhaps you should be looking at fork().

    UPDATE: feh, I sould have said, are you trying to run this thing in the background? In any case, '&' is certainly not the way to do that.

      Yes, the & does mean run in background.
      I want that there because I don't want to wait for the command to finish. I want to execute it and continue immediately regardless of how long the command will take.
      P.S. Don't let the 'ps' command in the example cloud the issue. The command I send is not important. What is important is that I am able to execute a command and get a response back to the user that it was started, not that it finished. I was hoping to use the list form of system to get rid of any 'shell' issues with quoting or any other special chars. Maybe & is a special shell char?

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (3)
As of 2024-04-24 02:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found