OVH Cloud OVH Cloud

trapper les écritures dans un filehandle (STDERR)

4 réponses
Avatar
Vincent Lefevre
Bonjour,

J'ai un script qui fait des écritures dans STDERR. Mais lorsque je
lance mon script en arrière-plan et qu'il est détaché du terminal,
je n'ai évidemment plus les erreurs dans ma console. Je voudrais
donc écrire dans un fichier tout ce qui va dans STDERR. Mais je ne
voudrais pas que ce fichier soit créé tant qu'il n'y a rien d'écrit.
Les redirections classiques ne fonctionnent donc pas (à moins qu'il
y ait quelque chose dont je ne sois pas au courant). Comment faire?
Une solution serait de trapper toutes ces écritures (via warn, die
et print STDERR) pour créer le fichier si besoin est, mais je ne
sais pas comment faire. Je voudrais éviter de faire un fork avec
pipe de STDERR juste pour cela.

Merci,

--
Vincent Lefèvre <vincent@vinc17.org> - Web: <http://www.vinc17.org/> - 100%
validated (X)HTML - Acorn Risc PC, Yellow Pig 17, Championnat International
des Jeux Mathématiques et Logiques, TETRHEX, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA

4 réponses

Avatar
Paul GABORIT
À (at) Fri, 5 Mar 2004 10:00:21 +0000 (UTC),
Vincent Lefevre <vincent+ écrivait (wrote):
J'ai un script qui fait des écritures dans STDERR. Mais lorsque je
lance mon script en arrière-plan et qu'il est détaché du terminal,
je n'ai évidemment plus les erreurs dans ma console. Je voudrais
donc écrire dans un fichier tout ce qui va dans STDERR. Mais je ne
voudrais pas que ce fichier soit créé tant qu'il n'y a rien d'écrit.
Les redirections classiques ne fonctionnent donc pas (à moins qu'il
y ait quelque chose dont je ne sois pas au courant). Comment faire?


Il existe peut-être des modules tout prêts pour cela mais je ne les connais
pas. En tous cas, plusieurs méthodes sont envisageables.

La première consiste effectivement à redéfinir quelques fonctions comme 'die',
'warn', 'print', etc. Mais dans l'absolu, on peut toujours imaginer un module
qui passe par une autre fonction d'écriture (du genre appel direct à la
méthode WRITE de STDERR ou une routine externe en C ou en C++).

Le plus sûr serait d'utiliser Tie::Handle pour créer un Handle qui n'ouvrirait
réellement le fichier que lors de la première écriture. Il suffit ensuite de
redirigier STDERR vers ce Pseudo Handle.

Tenez-nous au courant si vous trouvez la solution car cela peut intéresser du
monde...

--
Paul Gaborit - <http://www.enstimac.fr/~gaborit/>
Perl en français - <http://www.enstimac.fr/Perl/>

Avatar
Vincent Lefevre
Dans l'article ,
Paul GABORIT écrit:

Il existe peut-être des modules tout prêts pour cela mais je ne les
connais pas. En tous cas, plusieurs méthodes sont envisageables.


Vu qu'il s'agit d'un script que je lance sur diverses machines et que
je n'ai pas envie de faire d'installation, il faudrait que ce soit un
module installé en standard.

Le plus sûr serait d'utiliser Tie::Handle pour créer un Handle qui
n'ouvrirait réellement le fichier que lors de la première écriture.
Il suffit ensuite de redirigier STDERR vers ce Pseudo Handle.


OK, je vais voir cette solution.

--
Vincent Lefèvre - Web: <http://www.vinc17.org/> - 100%
validated (X)HTML - Acorn Risc PC, Yellow Pig 17, Championnat International
des Jeux Mathématiques et Logiques, TETRHEX, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA

Avatar
Paul GABORIT
À (at) Fri, 5 Mar 2004 15:59:22 +0000 (UTC),
Vincent Lefevre <vincent+ écrivait (wrote):
Vu qu'il s'agit d'un script que je lance sur diverses machines et que
je n'ai pas envie de faire d'installation, il faudrait que ce soit un
module installé en standard.


Mis à part les modules faisant appel à du code externe (non Perl), il est
toujours possible d'inclure les packages directement dans le script.

--
Paul Gaborit - <http://www.enstimac.fr/~gaborit/>
Perl en français - <http://www.enstimac.fr/Perl/>

Avatar
Vincent Lefevre
Dans l'article ,
Paul GABORIT écrit:

À (at) Fri, 5 Mar 2004 15:59:22 +0000 (UTC),
Vincent Lefevre <vincent+ écrivait (wrote):
Vu qu'il s'agit d'un script que je lance sur diverses machines et que
je n'ai pas envie de faire d'installation, il faudrait que ce soit un
module installé en standard.


Mis à part les modules faisant appel à du code externe (non Perl), il est
toujours possible d'inclure les packages directement dans le script.


C'est OK pour les packages qu'on écrit soi-même, sinon ce n'est pas
terrible.

Bon, concernant tie, le problème est que j'ai peu d'exemples (et pas
d'explications claires). Je n'ai jamais utilisé certaines choses comme
bless, alors je ne sais pas trop. Voilà par exemple, pour commencer:

------------------------------------------------------------
#!/usr/bin/env perl

use strict;

package NewHandle;
require Tie::Handle;
use FileHandle;

our @ISA = qw(Tie::Handle);

sub TIEHANDLE
{
my $fh;
bless $fh, $_[0];
}

sub OPEN
{
print "OPEN FH: $_[0]n";
}

sub PRINT
{
print "PRINT FH: $_[0]n";
unless (defined $_[0])
{
print "PRINT: new FH...n";
$_[0] = new FileHandle ">stderr.$$" or die;
}
print "PRINT: print ...n";
print { $_[0] } @_[1,-1];
print "PRINT: endn";
}

package main;

print "tie...n";
tie *STDERR, 'NewHandle';

print "print STDERR ...n";
print STDERR "Test printn";

print "OKn";
------------------------------------------------------------

J'ai pris un peu exemple sur /usr/share/perl/5.8.3/Tie/Handle.pm mais
ça reste très vague. Quand j'exécute mon script:

greux:~> ./tietest
tie...
print STDERR ...
PRINT FH: NewHandle=SCALAR(0x81841b0)
PRINT: print ...
PRINT FH: NewHandle=SCALAR(0x81841b0)
PRINT: print ...
Not a GLOB reference at ./tietest line 31.
zsh: exit 255 ./tietest

Une explication?
Pourquoi le filehandle n'est-il pas undef initialement?
Comme se fait-il que le print à l'intérieur rappelle PRINT?

--
Vincent Lefèvre - Web: <http://www.vinc17.org/> - 100%
validated (X)HTML - Acorn Risc PC, Yellow Pig 17, Championnat International
des Jeux Mathématiques et Logiques, TETRHEX, etc.
Work: CR INRIA - computer arithmetic / SPACES project at LORIA