Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Closing STDIO Caused Pipe Not To Work

by Anonymous Monk
on Aug 26, 2007 at 22:31 UTC ( [id://635173] : perlquestion . print w/replies, xml ) Need Help??

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

Dear Perl Monk,

A few days ago I posted a question "close STDOUT does not work, why?" at close STDOUT does not work, why?

and BrowserUK pointed out that I needed to close STDIN and STDERR as well and it made the redirection worked. However, when I tried to invoke an external program using PIPE later in my program, it failed. Below is a piece of code I wrote to demonstrate my problem. Any thoughts?

#!/usr/bin/perl use CGI qw(:standard); $| = 1; if (my $pid = fork) { #parent does close STDOUT; close STDIN; close STDERR; open STDIN, '<', '/dev/null'; open STDOUT, '>', '/dev/null'; my $err_file = "/var/www/html/cgi_data/error_log"; open STDERR, '>', $err_file; start_x(); } else { print header(), q~ <HTML> <HEAD> <META HTTP-EQUIV="Refresh" CONTENT="3; URL=/cgi_data/page1.html"> <TITLE>New Site notification</TITLE> </HEAD> <BODY>My homepage has moved to a new location. I am here</BODY></HTML> ~; exit; } sub start_x { $com = "./myprog 100"; open PIPE, "$com |"; $outfile1 = "../html/cgi_data/page2.html"; open OUT, ">$outfile1" or die "Can not open for write: $outfile"; while ($data = <PIPE>) { print OUT "$data\n"; } close OUT; }

The problem occurs at
open PIPE, "$com |";

I tried to put a print STDERR "I am here"; and noticed it does print to the error_log file if I put the print statement above the open PIPE but does not if I put the print statement after it. Any thoughts?
Thanks.

Code tags added by GrandFather

Replies are listed 'Best First'.
Re: Closing STDIO Caused Pipe Not To Work
by WalkingZero (Sexton) on Aug 27, 2007 at 04:35 UTC
    I will preface this by saying I have never used the PIPE command. That being said I just wanted to throw out a couple of observations. Things you may want to look into. 1) You are sending STDIN and STDOUT to devnull, what affect does this have on the bi-directional filehandles that PIPE is supposed to create?(I honestly don't know, I may be way off base with that one. If so I apologize) 2. PIPE uses IO buffering, have you tried forcing a flush of the buffer after you open the PIPE but before you write to the STDERR? (again,I'm kind of spitballing here. I hope you find it helpful, if not ignore me ;p )
      I think the script died when it encountered the open PIPE statement since I do not see the external program being invoked when I did I ps -aux on my linux box. However, no error is displayed anywhere even in my error_log file.
Re: Closing STDIO Caused Pipe Not To Work
by Anonymous Monk on Aug 27, 2007 at 05:23 UTC
    Got it working, thanks WalkingZero. It turns out I don't need these two statements:

    open STDIN, '<', '/dev/null';
    open STDOUT, '>', '/dev/null';

    not sure why on one of the node I found in Perl Monks, one of the monk said to reopen STDIN, and STDOUT otherwise when I open some file, it will get assign to file descriptor 0 and 1. Either way, thanks for your help.

      I am glad that you have your code working but I am confused. What does the current values of STDIN, STDOUT and STDOUT have to with opening a pipe or the pipe system call in general?

      If I run this code, it works exactly as expected, i.e. there is a file /tmp/err, containing the output of the ps command.

      #!/usr/bin/perl # vim: sw=4 use strict; use warnings; close STDIN; close STDOUT; close STDERR; open STDIN, "</dev/null"; open STDOUT, ">/dev/null"; open STDERR, ">/dev/null"; open my $pipe, "ps aux |" or die "pipe failed:$!\n"; open my $err, ">", "/tmp/err" or die "couldn't open /tmp/err :$!\n"; while (<$pipe>) { print $err $_; } close $err;
      I realise that the original code had re-opened STDERR to the apache error log.

      To answer the question regarding the need to close STDIN, STDOUT and STDERR. This usually done when you want to create a daemon or process that is intended to run in the background. I have never seen someone do it in the parent before. Normally it is done in the child so that the child will be owned by init etc.
      Here is a URL for a bit more info on writing a daemon in Perl if you are curious.

        This is a web application. You have to close these STDIO's to be able to disconnect your script from the web client. When you reopen them and send to NULL, I guess it won't allow you to do a PIPE for some reason. You have to run it from a web client to see the effect.
Re: Closing STDIO Caused Pipe Not To Work
by ysth (Canon) on Aug 27, 2007 at 04:44 UTC
    Check that your opens and closes all succeeded?
Re: Closing STDIO Caused Pipe Not To Work
by atemon (Chaplain) on Aug 27, 2007 at 02:48 UTC

    Did you ever tried a search with perlmonks ? Have a look at PerlMonks FAQ, The Perl Monks Guide to the Monastery for more information on how the Monastery works. How (Not) To Ask A Question will be a good guide. There are hundreds of thousands of posts here, Super Search is your friend. There are more than one postings available in the monastery regarding pipes.

    --VC



    There are three sides to any argument.....
    your side, my side and the right side.

      --. The question raised by the OP was entirely legitimate, presented clearly, with fairly complete code (except neglecting to say what the external command was), and with reference to an earlier question by the same poster. I see no fault in it other than a failure to use <code> tags which is not the most severe crime on the book.

      Moreover, there is not the slightest indication that this is a homework problem, nor is Anonymous Monk asking us to solve his or her problem from scratch, which is usually the hallmark of such questions.

      I should also add some that people have genuine and valid reasons for posting anonymously, and absent any other evidence, I would not question that in this case.

      Those links are great links to suggest to a person who asks vague, poorly worded, poorly formatted, code-free, etc. questions, but is inappropriate in this situation. And while it is true that there are "more than one postings available in the monastery regarding pipes" I don't get the impression you actually looked for any that relate even remotely to the OP's problem in this thread.

      Update: I should clarify that this node is, in part, in response to Re^3: Closing STDIO Caused Pipe Not To Work as well.

      I am the original poster of the question. Thanks for sending me around chasing the geese. I just spent 1 1/2 hours looking thru perl monks web site and only found posting

      http://www.perlmonks.org/?node_id=412947

      similar to mine with no solution. If you know where it is, why don't you just point me to it instead of being sarcastic.

      In other words, you don't know the answer but you think you can gain some XP by posting this crappy, useless piece of boiler plate.

        Hey monk, I don't know who you are. First I thought NOT to reply. But later I changed my mind thinking that, if I am NOT replying, others may think I agree with you. Sorry monks if its offending.

        Dear anonymous (?) why are you so frustrated and angry regarding reply ? We are here NOT to do homework for you. I was reading your posts Client Pull Not Working correctly and close STDOUT does not work, why? from the beginning. All the three (including this ) threads together looks like a homework done. I have my own working version of your program as I used to try & learn any useful code.

        Back to the problem.
        Whats the error you get when you open the pipe? You says that you have a problem at opening pipe and didn't mention anything about the error message you got. Did you try whats discussed at Why doesn't open() return an error when a pipe open fails? and perlipc

        isn't it a fact that you are afraid of loosing XP and thats the reason to post this "home work" as "Anonymous"? Please do not think that all monks out here are too much XP conscious. I know this post can bring me lots of -- XPs

        Update:
        http://www.perlmonks.org/?node_id=412947

        similar to mine with no solution. If you know where it is, why don't you just point me to it instead of being sarcastic.


        We are here NOT to do homework for others!

        Cheers !

        --VC



        There are three sides to any argument.....
        your side, my side and the right side.