Newsgroup: it.comp.www.php
Titolo: catturare lo standard output

ob_start();
fwrite(STDOUT, "standard output  \n");
echo 'abc';
$output = ob_get_clean();
 
echo "OUTPUT CATTURATO: $output  \n";
 
 
Il problema è che viene catturato solo 'abc'.
Per catturare anche 'standard output'?


"echo" e "print" vanno sul flusso fopen("php://output", "wb") che viene gestito in modo speciale per gestire l'invio dell'header HTTP, quindi se provi questo:
 
fwrite(fopen("php://output", "wb"), "standard output  \n");
 
funziona. Invece STDOUT, che coincide con fopen("php://stdout, "wb"), è più
primitivo e aggira il normale controllo del flusso di output del linguaggio.
 
Per come l'ho capita io, eh!
 
 
Ciao,
 ___ 
/_|_\  Umberto Salsi
\/_\/  
www.icosaedro.it
 
 


Quindi non c'è modo di catturare ciò che viene scritto su STDERR?
 
 

Quindi non c'è modo di catturare ciò che viene scritto su STDERR?
 
Su Unix o Windows? Nel secondo caso mi sa che non ci sia un modo pratico. Ma,
'sendo che l'IOSS di PHP su Unix e' POSIX compliant...
 
...traduco una sconcezza dal C a PHP:
 
// Chiudo lo stream di stderr. Ci sta che fclose($STDERR) funzioni uguale.
// Forse. eio_close() funziona di sicuro >:-D
 
eio_close(2);
 
// Creo una FIFO vtile per scambiare i dati
posix_mkfifo("error.log", 0644);
 
// Riapro lo stream
$STDERR = fopen('error.log', 'wb');
 
// Da qui in poi STDERR __DOVREBBE__ 
fwrite(STDERR, "Error stream\n");
 
print "Finished.\n";
 
// Ora rileggo i dati
$datum  = file_get_contents("error.log");
print "Output: '{$datum}'\n";
 
Se non c'e' eio (ma prima prova fclose: hai visto mai).
 
# pecl install eio # eio eio
 
# echo 'extension=eio.so' > /etc/php5/conf.d/eio.ini
 
# service apache2 restart
 
 
Leonardo
 
-- 
 
Questi non hanno speranza di morte; e la lor cieca vita e' tanto bassa,
Che 'nvidiosi son d'ogne altra sorte. Fama di loro il mondo esser non lassa;
Misericordia e Giustizia li sdegna; non ragioniam di lor, ma guarda e passa.

 Quindi non c'è modo di catturare ciò che viene scritto su STDERR?
 
Puoi catturare STDERR con un filtro, ma e' materia un po' esoterica perche'
poco documentata e, pur essendo un oggetto, non funziona come dovrebbe
funzionare un oggetto (il costruttore non viene chiamato...):
 
 
/**
 * Stream filter che cattura l'output in una stringa.
 */
class StreamTap extends php_user_filter {
 
    // Buffer di cattura.
    public static $buf;
 
 
    function filter($in, $out, &$consumed, $closing) {
        do {
            if( $closing ){
                // gestione evento chiusura
            }
            $bucket = stream_bucket_make_writeable($in);
            if( $bucket === NULL )
                break;
 
            // catturo:
            self::$buf .= $bucket->data;
 
            // event. propago al filtro seguente:
            stream_bucket_append($out, $bucket);
            $consumed += $bucket->datalen;
 
        } while(true);
        return PSFS_PASS_ON;
    }
 
}
 
// Registra il filtro di cattura stream:
if( ! stream_filter_register("StreamTap", "StreamTap") )
    die("Failed to register filter");
 
// mi attacco a STDERR:
stream_filter_append(STDERR, "StreamTap", STREAM_FILTER_WRITE, null);
 
// questo msg finisce in StreamTap::$buf, oltre che su STDERR:
fwrite(STDERR, "bla bla bla");
 
 
Purtroppo, quanto sopra non funziona con i messaggi prodotti da
error_log(), die() e in generale proprio con gli errori di runtime,
che seguono un'altra strada...
 
 
Un altro modo e' definire il file di destinazione dello stderr in
error_log.  Questo lo puoi definire in php.ini, oppure per ciascun script:
 
ini_set("error_log", __DIR__ . "/stderr.txt");
 
Nel file i messaggi vengono appesi indefinitamente, e in qualche modo si
possono poi andare a recuperare.  Questo funziona ma il file e' unico e
vengono messi degli header per ogni riga con la data, e poi bisogna in
qualche modo svuotare il file periodicamente.



 
Comunque sono soluzioni diaboliche :D