Newsgroup: it.comp.lang.perl
Titolo: Svezzare una cgi

Vorrei chiedere qualche suggerimento su un problemino che non riesco a
risolvere. E' un problema un po' in bilico tra perl, cgi e unix, forse piu'
cgi e unix che perl, ma insomma, spero che non mi sbatterete fuori dal ng...
Mi trovo a volte a voler far lanciare delle operazioni piuttosto lunghe,
tipo creare qualche decina di migliaia di pagine html elaborando un
database, o caricare filettoni sql appena uploadati, o fare le statistiche
su un log. Le vorrei far lanciare da una cgi, in modo che lo possa fare un
utente che non sappia avventurarsi in telnet.
In pratica il mio problema e' quello di far lanciare il processo dalla cgi e
poi far rientrare e morire la cgi lasciando il processo a lavorare
felicemente. Immagino che per un esperto di unix sia una bazzeccola, in
effetti sono deboluccio in questo settore. Al momento la risolvo facendo
scrivere un comando alla cgi che poi viene eseguito da un cron che passa di
li' ogni tanto, ma e' *bruttissimo*...
bye
silvio

 posponi '&' al comando eseguito con `...`, e lo lasci in background.
Grazie, e' la prima cosa che ho provato, ma non funziona.
La cgi (o Apache, immagino) aspetta comunque che sia terminato il processo
figlio prima di "dichiararsi conclusa".
bye
silvio

 processo "detached".
Ho provato tanto con system (che pero' aspetta il termine del processo
figlio per rientrare) che con exec (che non aspetta e chiude il processo
padre).
Stesso risultato.
Probabilmente esiste anche per unix qualche modulo come quello che hai usato
per enneti'.
bye
silvio

 esegue comando&
Bel suggerimento. Provato.
Ok, questo mi ha permesso di dimostrare che il problema non sta nel perl.
Anche con la shell succede la stessa cosa:
#!/bin/sh
/www/misc/cgi-bin/prova/do.sh &
/www/misc/cgi-bin/prova/perl.cgi
aspetta la conclusione di do.sh prima di eseguire perl.cgi.
Quindi mollo il lama e vado a spulciare il cavallo...
bye
silvio

 meglio.
Io  farei una cosa di questo tipo.
Metto in crontab:
*/5 * * * *     root    /mio/
script.pl
in 
script.pl
if (-e '/control/file') {
#tutto il lavoro
unlink ('/control/file');
}
il cgi:
open (CRT,''/control/file');
print CRT 'control file\n';
close CRT;
Eventualmente usando /contrl/file per passare anche qualche paramentro.
Bisognerebbe anche studiare un "attento" sistema di locking dei file per 
evitare problemi di accessi contemporanei, Magari cambianto il cgi con 
open (CRT,"/control/file.$$");
e lo script
foreach $file in ("/control/file.*') {....}
-- 
Saluti,
Giancarlo

 Io  farei una cosa di questo tipo.
Grazie, come avevo detto nel messaggio iniziale e' proprio la "soluzione"
che ho adottato.
bye
silvio 

Silvio Sosio wrote:

Mi ero "perso" quel pezzo del primo post..... personalmente non lo trovo 
pero' bruttissimo.
Gli altri modi li vedo invece molto critici e complicati, rischi di creare 
degli zombies, di lanciare processi e di perderne poi il controllo, mentre 
se lo fai fare a cron "pensa" lui a tutto, l'unica cosa che perdi e' 
l'eseguzione real time, ma mi sembrava non fosse importante.
-- 
Saluti,
Giancarlo

 Grazie, e' la prima cosa che ho provato, ma non funziona.
Non e' vero, funziona. Se stoppi la sessione http dopo che il figlio e'
stato lanciato in background il padre muore, ma il figlio resta vivo.
Il motivo per cui il processo padre rimane vivo e' solo un problema di
flushing dell'output del figlio.
Per chiudere la sessione in modo pulito basta redirigere lo stdout del
figlio su un file (o dove ti pare) e in questo modo il padre esegue e muore
subito.
Ecco il mio esempio:
Processo padre:
[CODE]
  !/usr/bin/perl
  $cheoresono = localtime();
  print <<ENDHEAD;
  Content-type: text/plain
  Sono le $cheoresono
  Io sono il processo padre e ora lancio un
  processo figlio che va avanti per diversi secondi
  ENDHEAD
  #Ora lancio l'altro processo, che ha un timer
  #system "nohup ./processofiglio &";
  system "./altroprocesso &";
  $cheoresono = localtime();
  print <<ENDFOOT;
  Ok, l'altro processo e' stato lanciato...
  Esco dal processo padre
  alle $cheoresono
  --------------------------------------------------------
  ENDFOOT
  exit;
[/CODE]
Processo figlio:
[CODE]
  #!/usr/bin/perl
  $log = "./log";
  open STDOUT,">$log";
  $| = 1;
  $cheoresono = localtime();
  print <<ENDHEAD;
  Sono le $cheoresono
  Io sono il processo figlio che viaggia detached.
  Ora macino per un tot di secondi....
  ENDHEAD
  foreach (1..10) {
        print "Sono passati $_ secondi ...\n";
        sleep 1;
  }
  $cheoresono = localtime();
  print <<ENDFOOT;
  ...E poi esco.
  alle $cheoresono
  ENDFOOT
  close STDOUT;
  exit;
[/CODE]
L'output sul browser di questo esempio e':
[OUT]
Sono le Sat Nov 18 01:14:22 2000
Io sono il processo padre e ora lancio un
processo figlio che va avanti per diversi secondi
Ok, l'altro processo e' stato lanciato...
Esco dal processo padre
alle Sat Nov 18 01:14:22 2000
--------------------------------------------------------
[/OUT]
Il contenuto del file di log (lo STDOUT rediretto del processo figlio
invece):
[LOG]
Sono le Sat Nov 18 01:14:22 2000
Io sono il processo figlio che viaggia detached.
Ora macino per un tot di secondi....
Sono passati 1 secondi ...
Sono passati 2 secondi ...
Sono passati 3 secondi ...
Sono passati 4 secondi ...
Sono passati 5 secondi ...
Sono passati 6 secondi ...
Sono passati 7 secondi ...
Sono passati 8 secondi ...
Sono passati 9 secondi ...
Sono passati 10 secondi ...
...E poi esco.
alle Sat Nov 18 01:14:32 2000
[/LOG]
Confronta gli orari di inizio/fine dei processi.
Ciao, marco
--
Marco Cacchiani                                
e-mail:ma...@sirius.pisa.it
Public pgp key:         
http://www.sirius.pisa.it/marco/pgp_public_key.asc
Sirius Servizi Informatici                     e-mail: 
in...@sirius.pisa.it
Parco Teatro Pasolini, 1                       Phone:  +39 (50) 865120
I-56019 - Vecchiano                            Fax:    +39 (50) 860260
(Pisa - ITALIA)                                
http://www.sirius.pisa.it/

 subito.
Capperonzoli funziona davvero!
Complimenti e grazie infinite!
bye
silvio