Newsgroup: it.comp.lang.perl
Titolo: grossi problemi di pipe!

Salve a tutti,
sto cercando di esportare i log di SQL server, che sono dei txt, ad un
demone syslog. Ho trovato un ottimo comando, klog, che consente tramite
un semplice pipe:
more log.txt | klog -h <ip> -i
di farmi mandare riga per riga il testo come fossero messaggi syslog.
Ho creato uno script banalissimo (considerato che sono circa 6 ore che
uso perl):
use File::Tail;
(my $name) = @ARGV;
$file=File::Tail->new(name=>$name, maxinterval=>1, adjustafter=>1);
open KLOG, "|klog.exe -h 192.168.100.120 -i";
while (defined($line=$file->read)) {
	print KLOG $line;
	print $line;
}
I due print finali sono per avere anche il risultato a schermo...
Ebbene, a schermo va, al demone non arriva nulla!
Considerate che se scrivo:
more C:/sql_server_logs/LOGPROVA.txt |klog.exe -h 192.168.100.120 -i
Sunziona perfettamente, come pure facendo:
dir /p |klog.exe -h 192.168.100.120 -i
Ho anche provato a fare:
use File::Tail;
(my $name) = @ARGV;
$file=File::Tail->new(name=>$name, maxinterval=>1, adjustafter=>1);
while (defined($line=$file->read)) {
	print $line;
}
Eppoi ad usare il pipe di windows:
prova2.pl
 C:/sql_server_logs/LOGPROVA.txt |klog.exe -h 192.168.100.120
-i
Ma non va!!!
Non capisco proprio dove stia il problema!
Grazie in anticipo a chiunque voglia aiutarmi...

 ha scritto nel messaggio
news:1152199520....@m73g2000cwd.googlegroups.com...


 :-)
...tacci tua... :)

 }
Ti consiglio prima di tutto di usare in ogni programma le due righe:
use strict;
use warnings;
La seconda è autoesplicativa. La prima (tra l'altro) ti impone di
dichiarare tutte le variabili che usi, per evitare gli errori quando
una variabile è dichiarata implicitamente. Non rientro negli altri
dettagli qui, ma anche qui "perldoc" è tuo amico.
Secondo, la forma (my $name) = @ARGV è errata per usare come
dichiarazione della variabile. Quando avrai un po' di tempo cerca di
documentarti sul contesto scalare e contesto di lista in Perl, qui non
mi dilungo molto. Usa semplicemente:
my $var1 = valore;  oppure
our $var2 = valore; (dipende dallo scope della variabile che vuoi
avere) e non puoi sbagliarti.
Se vuoi dichiarare più variabili mettile tra parentesi:
my( $var1, $var2, $var3 ); Tu hai messo tra le parentesi anche il "my".
Allora, un altro problema, come ti avevo accennato potrebbe essere il
mancato flushing del buffer. Vedi qui la spiegazione:
http://www.rocketaware.com/perl/perlfaq5/How_do_I_flush_unbuffer_a_fileha.htm
Ti conviene dunque, settare l'autoflush quando apri il filehandle KLOG.
Prova anche a settare il parametro "nowait" del modulo File::Tail (v.
perldoc File::Tail), in modo che non aspetti che arrivino i dati, ma se
non ci sono quello continua.
Fammi sapere se va.

 Ti conviene dunque, settare l'autoflush quando apri il filehandle KLOG.
MITTICO!!! :)
use File::Tail;
# $name = "C:/sql_server_logs/LOGPROVA.txt";
(my $name) = @ARGV;
$file=File::Tail->new(name=>$name, maxinterval=>1, adjustafter=>1);
open KLOG, "| klog.exe -h 192.168.100.120 -i";
KLOG->autoflush(1);
while (defined($line=$file->read)) {
	print KLOG $line;
	print $line;
}
Così va alla perfezione...
Il nowait in realtà mi complica un po' le cose, cioè rallenta di
molto. Ho preferito settare 1 secondo di tempo...

 molto. Ho preferito settare 1 secondo di tempo...
SI, infatti, era l'ultima cosa che ti avevo raccomandato. Andando alla
cieca senza poterlo testare ho sparato le supposizioni, ma ero quasi
sicuro che fosse il flushing del buffer il problema.
Controlla un po' come si comporta quando i file di log vengono rotati,
ma dovrebbe gestirlo bene.
Quando hai tempo studiati il "Picking up Perl" che ti ho raccomandato
nell'altro post su i.l.i. e poi perldoc perl e gli altri perldoc
riferiti da lì.
Benvenuto nel mondo di Perl.
P.S: Salutami la tua sorella. ;-)

 avere) e non puoi sbagliarti.
Ma perchè, facendo use strict:
(my $name) = @ARGV
funziona
my $name = @ARGV
mi restituisce:
Error opening 1: No such file or directory at
C:\Perl\tail\File-Tail-0.99.3\
perlogger.pl
 line 10
Questo non m'è molto chiaro... Passandogli lo stesso percorso completo
del file ovviamente, e hho provato sia con / che con \ per le
directory...
Ciao

C:\Perl\tail\File-Tail-0.99.3\
perlogger.pl
 line 10
Perché con
   (my $name) = @ARGV;
o, meglio, con
   my ($name) = @ARGV;
assegni a $name il valore del primo elemento di @ARGV.
Con
  my $name = @ARGV;
@ARGV viene interpretato in un contesto scalare, e resituisce il numero di
elementi @ARGV, che viene assegnato a $name. Quindi cerchi di aprire il
file "1".
Ciao.

 P.S: Salutami la tua sorella. ;-)
E pure il suo ragazzo? :)
grazie mille per l'aiuto, è stato molto utile...

 grazie mille per l'aiuto, è stato molto utile...
Di niente.

 (cut)
Ometto la risposta perché ti ha già risposto Giovanni Zezza, in modo
chiarissimo e correttissimo. Scusa, ma nella fretta di risponderti e
tornare a fare le cose che dovevo fare, ho fatto delle supposizioni -
sbagliate - che se avessi scritto
my $var1 = valore; che avresti capito che si trattasse di un singolo
valore (scalare), cioè per esempio, un numero o una stringa..
Comunque, dacci un'occhiata a quello che ti ho scritto sui diversi
contesti. Come promemoria puoi considerare che $var1 è uno scalare
("$" ricorda a "S"), e @var2 è una lista ("@" potrebbe ricordarti ad
"A"rray). Ci sono altri tipi di identificatori oltre ai scalari e alle
liste, e tu nel tuo programmino hai già usato alcuni
inconsapevolmente.(array associativi: parametri di File::Tail; o
bareword: filehandler KLOG). Ma non ti voglio mettere troppa carne sul
fuoco. Un po' per volta, che digerisci meglio.

 file "1".
Ok, tutto chiaro...
Ora uso:
if (!$ARGV[0]) {print "Right sintax is ikslogger FILENAME IP";}
my $name = $ARGV[0];
my $ip;
if (!$ARGV[1]) {$ip = "127.0.0.1";
		print "Using localhost as syslog daemon's ip\n"}
	else {  $ip = $ARGV[1];}
E funziona tutto benissimo
Grazie mille.

Messo in fase di test serio sto script ha dei problemi mica da poco,
mortacci...
Lo script definitivo è questo:
#!/usr/bin/perl
use strict;
use warnings;
use File::Tail;
use Net::Syslog;
# $name = "C:/sql_server_logs/LOGPROVA.txt";
print "IKSLOGGER 1.0\n";
my $line;
my $file;
my $s;
if (!$ARGV[0]) {print "Right sintax is ikslogger FILENAME IP";}
my $name = $ARGV[0];
my $ip;
if (!$ARGV[1]) {$ip = "127.0.0.1";
		print "Using localhost as syslog daemon's ip\n"}
	else {  $ip = $ARGV[1];}
$file=File::Tail->new(name=>$name, maxinterval=>1, adjustafter=>1);
$s=new Net::Syslog(Facility=>'local4',Priority=>'debug',
SyslogHost=>$ip,SyslogPort=>'514');
while (defined($line=$file->read)) {
	$s->send($line, Priority=>'info');
}
L'ho messo nel pc dove risiede sql server, nella cartella dei log. Ora
il logè grossetto, circa 13Mb in 4 giorni.
Lancio: ikslogger ERRORLOG 192.168.100.120 (ip della mia macchina, a
cui voglio arrivino i messaggi syslog) e parte dall'inizio del file di
log!!! Non dai cambiamenti. Dopo 15 minuti, arrivato alle ultime righe,
riparte da capo... Non è certo quel che voglio!
Mi chiedo: sarà forse sql server che ha un modo "strano" di scrivere
sul file di log, tale da imbrogliare il logger? Ho provato ad
analizzare il file di log dopo una mezzora, ma le prime righe erano
uguali!
Qualche idea su dove possa essere l'inghippo?

 Qualche idea su dove possa essere l'inghippo?
Mi autorispondo:
vado su cpan e leggo:
These are the test reports that we have for the CPAN distribution
File-Tail:
0.99.3 (1 FAIL, 17 PASSes)
* 245042 FAIL 5.8.5 on MSWin32 4.0 (MSWin32-x86-multi-thread)
=> WINDOWS DI MERDAAAAAAAAAAAAA  :(
Vabbè riprovo con un'altra strada...