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

The RRDTool::OO module's graph method requires a file name in order to plot a graph (create a gif/png) I am trying to use this in a CGI, and would like to write to STDOUT, but cannot seem to figure out how to force this, or even if forcing it is possible. Setting 'image' to "-" results in:

malformed header from script. Bad header=GIF87a!!!: scriptname.cgi

When 'image' is "-" part of the gif prints before the HTTP header, and then the rest of the gif, which makes this even more bizzare, but explains the "Bad Header errror. Is making this module write to STDOUT possible? If so, how does one do it? Any thoughts? I'd really like to avoid Hitting the disk with a temp write,read.
print "Content-type: image/gif\nExpires: 0\n\n"; $rrd->graph( image => "-", vertical_label => 'My Salary', draw => { thickness => 2, color => 'FF0000', legend => 'Salary over Time', }, );

Replies are listed 'Best First'.
Re: Tricking a filename argument to use STDOUT
by tlm (Prior) on Jun 27, 2005 at 21:33 UTC

    The /dev/fd/1 trick works on Linux:

    use strict; use warnings; sub hello { my $filename = shift; open my $out, '>', $filename or die "Can't write to $filename: $!\n"; print $out "Hello world!\n"; close $out or die "Failure closing $filename: $!\n"; return; } hello( '/dev/fd/1' ); # use /dev/fd/1 as the filename for STDOUT print "Is STDOUT still open?\n"; __END__ Hello world! Is STDOUT still open?

    the lowliest monk

      Basically the same idea, /dev/stdout works in many OSs. In whatever flavor of linux I'm using at the time (don't know, don't care) /dev/stdout is a link to /proc/self/fd/1.
Re: Tricking a filename argument to use STDOUT
by ikegami (Patriarch) on Jun 27, 2005 at 21:38 UTC

    It sounds to me like the web server saw the image (since it gave you an error message containing part of the image), and the only way it could have seen the image is if it had been sent to STDOUT. Maybe you need to flush the header first?

    print "Content-type: image/gif\nExpires: 0\n\n"; { my $af=$|; $|=1; $|=$af; } # Flush output. $rrd->graph( image => "-", vertical_label => 'My Salary', draw => { thickness => 2, color => 'FF0000', legend => 'Salary over Time', }, );
      The output needed to be flushed. It was printing the content header in the middle of the image. Thanks to everyone who replied. Special thanks to ikegami.
Re: Tricking a filename argument to use STDOUT
by davidrw (Prior) on Jun 28, 2005 at 00:42 UTC
    be sure to try ikegami's method .. it does seem that '-' as the image name should work. Reference: RRDtool - rrdgraph (Make also check RRDTool::OO's source to see how directly it calls rrdgraph)
Re: Tricking a filename argument to use STDOUT
by jasonk (Parson) on Jun 28, 2005 at 13:51 UTC

    You need to flush the buffer after printing the headers, and before calling rrd. The easiest way is to set $| = 1 to enable autoflush, so the buffer will be flushed after each line, instead of in blocks. You should also read through Suffering from Buffering.


    We're not surrounded, we're in a target-rich environment!