7
votes

Montrant les progrès en exécution d'une commande système () à Perl

J'ai un script Perl qui effectue des tâches, dont l'une est d'appeler une commande code> system code> sur "gar -cvf fichier.tar ....." code> .

Cela peut souvent prendre un peu de temps, je voudrais donc que la ligne de commande échoue à un indicateur de progression, quelque chose comme un # code> retour à l'écran tandis que le système code> L'appel est en cours. P>

Je fais des creuser et jeté sur Fourche code>. Est-ce la meilleure façon d'aller? Est-il possible de faire une fourchette de la commande code> system code>, puis créez une boucle tandis que vérifie le STAUS du $ pid code> renvoyé par la fourchette? P>

J'ai également vu des références à WaiterPID code> .... Je suppose que je dois l'utiliser aussi. P>

fork system("tar ... ")
while ( forked process is still active) {
    print #
    sleep 1
}


1 commentaires

La valeur de retour de Fourchette est l'ID de processus de l'enfant, s'il s'agit du parent, ou de 0 s'il s'agit de l'enfant, ou de la FUND si la fourche a échoué. Voir Perldoc -f Fourche.


6 Réponses :


1
votes

J'essaierais quelque chose comme ça

open my $tar, "tar -cvf file.tar..... 2>&/dev/null |"
    or die "can't fork: $!";
my $i = 0;
while (<$tar>) {
    if( i++ % 1000 == 0 ) print;
} 
close $tar or die "tar error: $! $?";


2 commentaires

Veuillez utiliser des lexicaux locaux pour vos poignées de fichier / processus, pas de globaux.


Mon Perl est un peu rouillé, je ne savais pas que cela est possible pour les charges de fichiers. Merci, je vais essayer la prochaine fois.



7
votes

Perl a une belle construction pour cela, appelée "pipe ouvre". Vous pouvez en savoir plus à ce sujet en tapant perdoc -f ouvert code> à une invite de shell.

  open(my $tar, '-|', 'tar', ...) or die "Could not run tar ... - $!";
  while (<$tar>) {
       print ".";
  }
  print "\n";
  close($tar);


4 commentaires

Bonjour Johan ... C'est exactement ce que je suis après! Merci beaucoup pour votre réponse et votre exemple. Je trouve toujours beaucoup plus facile lorsque vous voyez un code exemple. Cordialement John


La virgule n'est pas nécessaire, je l'ai retirée de l'exemple ;-)


:-) - Merci Johan. Une chose ... Cette méthode ne fonctionne-t-elle que sur des commandes qui écrivent quelque chose à STDOUT? Il semble fonctionner parfaitement lors de l'utilisation de Tar ZCVF, mais il y a une autre commande que j'utilise qui ne fait rien écho à STDOUT ..... quand j'essaie d'ouvrir un tuyau à cette commande, je ne vois pas l'impression " . " :(


@John Oui, cela ne fonctionne que si la commande écrit quelque chose. Si le processus d'enfant n'écrit rien, vous devez utiliser une construction différente, comme Fork / EXEC / non bloque waiterpid / / Dormez . @Johan Votre exemple de code serait meilleur avec un $ | ++ afin que les points soient imprimés immédiatement. :)



6
votes

Un exemple qui ne dépend pas du processus d'enfant qui écrit un type de sortie et imprime simplement un point environ une fois une seconde aussi longtemps que fonctionnant:

use POSIX qw(:sys_wait_h);
$|++;

defined(my $pid = fork) or die "Couldn't fork: $!";

if (!$pid) { # Child
  exec('long_running_command', @args) 
    or die "Couldn't exec: $!";
} else { # Parent
  while (! waitpid($pid, WNOHANG)) {
    print ".";
    sleep 1;
  }
  print "\n";
}


1 commentaires

Bonjour et merci pour votre aide à ce sujet. Je vais essayer cela aussi et voir quelle méthode les meilleures conversations. J'ai aimé votre caisse $ | ++ ci-dessus. Je fais un SELECT (stdout) puis $ | = 1



1
votes

Pour montrer des progrès lors d'une tâche longue en cours, vous trouverez


0 commentaires

2
votes
$|++;    
open(my $tar, 'tar ... |') or die "Could not run tar ... - $!";
      while ($file=<$tar>) {
           print "$file";
      }
      print "\n";
      close($tar);
This prints the filenames received from tar.

0 commentaires

0
votes

Développer sur les Hobbs fournis si vous souhaitez obtenir les données du processus enfant dans le processus parent, vous devez disposer d'un conduit externe. J'ai fini par utiliser les TEMPFS car il était simple comme un fichier, mais ne met pas de hashits io sur le disque.

** IMPORTANT ** Vous devez quitter le processus enfant, car sinon, le processus "enfant" se poursuivra le long du même script et vous obtiendrez DOUBLE Imprimer les déclarations . Donc, dans l'exemple ci-dessous foreach (@stdoutoutput) arriverait deux fois malgré seulement d'être dans le script une fois. xxx


0 commentaires