Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 05/02/2009, à 11:23

Crazyfaboo

[BASh]Récupérer des informations d'un programme en cours d'execution

Bonjour à tous,

Désolé pour le titre, mais je trouve pas plus court et plus précis pour expliquer brièvement ce que je cherche à faire...

Ce que je cherche à faire, c'est simple en fait : j'ai un logiciel type ffmpeg ou mencoder qui tourne dans mon terminal (donc encode) et je voudrais simplement récupérer les informations d'avancement de l'encodage.

Par exemple, dans ffmpeg, je veux récupérer cette ligne : size=  175101kB time=7471.0 bitrate= 192.0kbits/s
et ceci à chaque instant (i.e. à chaque fois qu'elle change)... Afin de pouvoir la réafficher à ma manière... et notamment virer tout le texte que ffmpeg affiche avant...
Idem pour mplayer...
La solution pour l'un de ces programmes me permet bien sûr de l'avoir pour l'autre...

Mon problème, c'est pas de faire un grep sur la commande... Çà je sais faire... Typiquement, çà donne quelque chose du genre :
ffmpeg -i file.wav -ac 2 -ab 112k file.ogg | grep -E -o "size=.*"

Mon problème c'est que ce grep n'a aucun effet... Ni pendant l'exécution, ni à la fin de l'exécution du programme...

Le problème ne vient pas de mon grep... Dans mon code, j'ai déjà fait une bonne vingtaine de grep pour récupérer diverses informations émanents de mplayer, je sais donc m'en servir... C'est juste que le pipe grep n'a aucun effet sur un programme qui ne se termine pas immédiatement...

Comment faire ?


EN BREF, avec ffmpeg comme exemple, j'ai ceci qui m'est donné par ffmpeg :

FFmpeg version r11872+debian_3:0.svn20080206-12ubuntu3, Copyright (c) 2000-2008 Fabrice Bellard, et al.
  configuration: --enable-gpl --enable-pp --enable-swscaler --enable-x11grab --prefix=/usr --enable-libgsm --enable-libtheora --enable-libvorbis --enable-pthreads --disable-strip --enable-libfaad --enable-libfaadbin --enable-liba52 --enable-liba52bin --enable-libdc1394 --enable-shared --disable-static
  libavutil version: 49.6.0
  libavcodec version: 51.50.0
  libavformat version: 52.7.0
  libavdevice version: 52.0.0
  built on Oct  3 2008 22:41:23, gcc: 4.3.2
Input #0, ac3, from './tmpen.ac3':
  Duration: 02:04:31.0, bitrate: 384 kb/s
    Stream #0.0: Audio: liba52, 48000 Hz, 5:1, 384 kb/s
Output #0, ac3, to './en.ac3':
    Stream #0.0: Audio: ac3, 48000 Hz, 5:1, 192 kb/s
Stream mapping:
  Stream #0.0 -> #0.0
Press [q] to stop encoding
size=  175101kB time=7471.0 bitrate= 192.0kbits/s

et je veux pouvoir récupérer les informations de la dernière ligne - qui évolue au cours de l'encodage - ou même une autre (comme la ligne Duration par exemple qui m'intéresse bien) pour pouvoir afficher un truc du genre :

Taille du fichier : 175101kB

Merci.

Dernière modification par Crazyfaboo (Le 05/02/2009, à 11:23)

Hors ligne

#2 Le 05/02/2009, à 11:41

Elemmire

Re : [BASh]Récupérer des informations d'un programme en cours d'execution

pourquoi ne pas utiliser la commande tee qui te permet de rediriger la sortie standart dans un fichier tout en l'affichant à l'écran (contrairement à la redirection > qui transfert tous dans un fichier)
par ex :

ls | tee -a fichier.log

ensuite tu peux utiliser tail et grep à ta convenance sur le fichier ...

Hors ligne

#3 Le 05/02/2009, à 11:52

Crazyfaboo

Re : [BASh]Récupérer des informations d'un programme en cours d'execution

Bonjour et merci de répondre aussi vite...

Je ne connaissais pas tee... ni tail d'ailleurs, mais çà n'est pas ce que je veux faire, et même si c'était ce que je voulais faire, çà ne marche pas...

Çà marche en effet avec ls... mais pas avec ffmpeg :

ffmpeg -i piste.ogg -ac 2 -ab 80k p.ogg | tee -a f.log

Le fichier f.log restera toujours vide.

De plus, ce n'est pas ce que je veux faire car je veux totalement faire disparaitre ce qu'affiche ffmpeg pour le remplacer en temps réel par des données que j'aurai extraites de ce qu'il affichait...
Autrement dit, je veux reformater la sortie de ffmpeg (en élagant beaucoup au passage).

Dernière modification par Crazyfaboo (Le 05/02/2009, à 11:53)

Hors ligne

#4 Le 05/02/2009, à 11:57

Crazyfaboo

Re : [BASh]Récupérer des informations d'un programme en cours d'execution

Je crois que j'ai une piste...

Apparement ce con de ffmpeg n'écrit pas dans stdout mais stderr...
Pour preuve :

ffmpeg -i piste.ogg -ac 2 -ab 80k p.ogg > f.log

donne pour f.log

Alors que :

ffmpeg -i piste.ogg -ac 2 -ab 80k p.ogg >& f.log

donne pour f.log

FFmpeg version r11872+debian_3:0.svn20080206-12ubuntu3, Copyright (c) 2000-2008 Fabrice Bellard, et al.
  configuration: --enable-gpl --enable-pp --enable-swscaler --enable-x11grab --prefix=/usr --enable-libgsm --enable-libtheora --enable-libvorbis --enable-pthreads --disable-strip --enable-libfaad --enable-libfaadbin --enable-liba52 --enable-liba52bin --enable-libdc1394 --enable-shared --disable-static
  libavutil version: 49.6.0
  libavcodec version: 51.50.0
  libavformat version: 52.7.0
  libavdevice version: 52.0.0
  built on Oct  3 2008 22:41:23, gcc: 4.3.2
Input #0, ogg, from 'piste.ogg':
  Duration: 00:04:36.4, start: 2.245079, bitrate: 61 kb/s
    Stream #0.0: Audio: vorbis, 44100 Hz, stereo, 64 kb/s
Output #0, ogg, to 'p.ogg':
    Stream #0.0: Audio: flac, 44100 Hz, stereo, 80 kb/s
Stream mapping:
  Stream #0.0 -> #0.0
Press [q] to stop encoding
size=    5427kB time=54.9 bitrate= 810.4kbits/s   
size=   12452kB time=118.4 bitrate= 861.6kbits/s   
size=   18750kB time=175.2 bitrate= 876.6kbits/s   
size=   22814kB time=220.6 bitrate= 847.3kbits/s   
size=   28561kB time=269.8 bitrate= 867.2kbits/s   
size=   29259kB time=278.8 bitrate= 859.8kbits/s   
video:0kB audio:29074kB global headers:0kB muxing overhead 0.639119%

Hors ligne

#5 Le 05/02/2009, à 12:08

Totor

Re : [BASh]Récupérer des informations d'un programme en cours d'execution

Le problème est que ffmpeg ou encoder ne font pas de retour à la ligne lors de leur affichage de la progression. C'est pourquoi le grep ne trouve rien. Seul un \r est envoyé pour repositionner le curseur en début de ligne.
Il faut donc "ruser" avec un script qui va analyser le flux de caractères comme suit :

#!/bin/bash

uneligne=""
while read -n1 uncaractere
do
 if [ "${uncaractere}" = "\n" ]; then
   uneligne=""
 else
     if [ "${uncaractere}" = "\r" ]; then
      # ton traitement de réaffichage
   else
     uneligne="${uneligne}${uncaractere}"
   fi
 fi
done

puis de l'utiliser de la façon suivante :

ffmpeg <options>|nomScript

Note : je n'ai pas ffmpeg sous la main et je ne sais pas si ffmpeg se repositionne en début de ligne avant ou après l'affichage de l'évolution de l'encodage. Cela risque de changer l'algo ci-dessus. Mais bon, le principe est là.

Dernière modification par Totor (Le 05/02/2009, à 12:11)


-- Lucid Lynx --

Hors ligne

#6 Le 05/02/2009, à 12:38

Crazyfaboo

Re : [BASh]Récupérer des informations d'un programme en cours d'execution

Bon après quelques tests, je vais plutôt faire çà comme cela :
Stocker la sortie de ffmpeg (stderr) dans un log...
Lire ce log (en même temps) avec more et le stocker dans une variable
Remplacer les Carriage Return
Faire un grep

Le seul truc qui me dérange c'est de remplacer les Carriage Return... Ca marche pas apparemment.

Voici mon code jusqu'ici :

ffmpeg -i en.ac3 -ac 2 -ab 112k en.ogg >& f.log
txt=$(more f.log)
txt=${txt/\r/} # Ne marche pas, ou ne change pas en tout cas l'affichage avec echo de txt
echo "$txt"

Des idées ?

Hors ligne

#7 Le 05/02/2009, à 12:50

Totor

Re : [BASh]Récupérer des informations d'un programme en cours d'execution

je pensais que tu voulais effectuer l'affichage en temps réel...
as-tu essayer :

txt=$(tr -d \r < f.log)


-- Lucid Lynx --

Hors ligne

#8 Le 05/02/2009, à 12:59

Crazyfaboo

Re : [BASh]Récupérer des informations d'un programme en cours d'execution

je pensais que tu voulais effectuer l'affichage en temps réel...

Ben avec un gros pipe, çà devrait toujours être possible non ? Écriture dans le f.log à gauche du pipe et lecture et affichage à droite...
Un truc du genre :
fonction_ecrire | fonction_lire_et_afficher

Quant à ceci :

txt=$(tr -d \r < f.log)

Çà ne marche pas...
Par contre, ceci marche :

txt=$(tr -d '\r' < f.log)

Par contre, t'aurais pas un truc pour faire un replace du \r par un \n ?

Merci beaucoup...

Hors ligne

#9 Le 05/02/2009, à 14:58

Totor

Re : [BASh]Récupérer des informations d'un programme en cours d'execution

Crazyfaboo a écrit :

Ben avec un gros pipe, çà devrait toujours être possible non ? Écriture dans le f.log à gauche du pipe et lecture et affichage à droite...
Un truc du genre :
fonction_ecrire | fonction_lire_et_afficher

oui, mais ce n'est pas la logique de ton script puisque tu n'auras accès à ton fichier f.log qu'une fois l'encodage terminé.

c'est pourquoi je t'ai proposé la solution du  while read -n1 .... pour lire caractère par caractère le flux émis par ffmpeg.
Mais normalement, il devrait être possible de préciser à l'instruction read le délimiteur mais je n'arrive pas à ce que ce soit \r...:/ je vais creuser car ce serait bien plus pratique que de lire caractère par caractère...

Crazyfaboo a écrit :

Par contre, t'aurais pas un truc pour faire un replace du \r par un \n ?

txt=$(tr '\r' '\n' < f.log)

-- Lucid Lynx --

Hors ligne

#10 Le 05/02/2009, à 16:18

Totor

Re : [BASh]Récupérer des informations d'un programme en cours d'execution

Totor a écrit :

Mais normalement, il devrait être possible de préciser à l'instruction read le délimiteur mais je n'arrive pas à ce que ce soit \r...:/ je vais creuser car ce serait bien plus pratique que de lire caractère par caractère...

Bon, j'ai trouvé :

#!/bin/bash
uncaractere=""
while [ "${uncaractere}" != $'\r' ]
do
  read -n1 uncaractere
done 

while read -d$'\r' uneligne
do
   # traitement d'affichage....
done

Note : pour lire la sortie d'erreur emise par ffmpeg, rajoute -u2 aux read où redirige ce flux ffmpeg vers la sortie standard.

EDIT : il faut rediriger le flux vers la sortie standard :

function affichage
{
uncaractere=""
while [ "${uncaractere}" != $'\r' ]
do
  read -n1 uncaractere  
done 

while read -d$'\r' uneligne
do
   # traitement d'affichage....
   printf "test - %s\n" "${uneligne}"
done
}
ffmpeg <options> 2>&1|affichage

Dernière modification par Totor (Le 05/02/2009, à 20:01)


-- Lucid Lynx --

Hors ligne

#11 Le 05/02/2009, à 20:49

Crazyfaboo

Re : [BASh]Récupérer des informations d'un programme en cours d'execution

MERCI BEAUCOUP !
Ta dernière réponse était la bonne...

Bon, vu qu'il fallait également que je récupère l'élément Duration: qui était affiché par ffmpeg, j'ai un peu modifier ton code et çà donne finalement :

readndisplay()
{
	while read -d $'\r' uneligne
	do
		 # traitement d'affichage....
		 echo "$uneligne" | grep -E -o "Duration:.*,"
		 echo "$uneligne" | grep -E -o "size=.*"
	done
}

ffmpeg -i en.ac3 -ac 2 -ab 112k en.ogg 2>&1 | readndisplay

Encore Merci !!! big_smile

Hors ligne

#12 Le 05/02/2009, à 21:48

Totor

Re : [BASh]Récupérer des informations d'un programme en cours d'execution

Je te propose quelques trucs pour éviter la création de processus inutilement :

#!/bin/code
readndisplay()
{
    while read -d $'\r' uneligne
    do
         # traitement d'affichage....
         egrep -o "Duration:.*," <<< "${uneligne}"
         egrep -o "size=.*" <<< "${uneligne}"
    done
}

ffmpeg -i en.ac3 -ac 2 -ab 112k en.ogg 2> >(readndisplay)

-- Lucid Lynx --

Hors ligne

#13 Le 05/02/2009, à 23:23

Crazyfaboo

Re : [BASh]Récupérer des informations d'un programme en cours d'execution

C'est quoi la nuance ? C'est une alternance de boucles dans un unique Thread plutôt que des Threads séparés ?

J'essairai çà... ^^

Hors ligne

#14 Le 06/02/2009, à 10:39

Totor

Re : [BASh]Récupérer des informations d'un programme en cours d'execution

Crazyfaboo a écrit :

C'est quoi la nuance ? C'est une alternance de boucles dans un unique Thread plutôt que des Threads séparés ?

J'essairai çà... ^^

La notation <<< est appelée "here-string" et c'est l'équivalent de "here-document" mais pour un mot. Cela permet de passer le texte qui suit les 3 chevrons dans l'entrée standard de la commande. Cela évite de créer 2 processus inhérents à l'utilisation du pipe.

L'utilisation de la substitution de processus (<(...) ou (...)>) a le même objectif que le pipe mais présente un avantage non négligeable : la modification de variable dans le processus recevant le flux est conservée puisque l'environnement d'exécution est celui du script.
Pour exemple :

i=5
echo -e "1\n2\n3"|while read ligne
do
  i=${ligne}
done

echo $i

on pourrait s'attendre à ce que le résultat soit 3 mais en fait c'est 5 car le while s'exécute dans son propre environnement.

Maintenant :

while read ligne
do
i=$ligne
done < <(echo -e "1\n2\n3")
echo $i

le résultat est bien 3.
(Note la notation here-string aurait pu être utilisée ce cas aussi)

D'ailleurs, ton script pourrait aussi s'écrire de la façon suivante :

while read -d $'\r' uneligne
    do
         # traitement d'affichage....
         egrep -o "Duration:.*," <<< "${uneligne}"
         egrep -o "size=.*" <<< "${uneligne}"
    done < <(ffmpeg -i en.ac3 -ac 2 -ab 112k en.ogg 2>&1)

-- Lucid Lynx --

Hors ligne

#15 Le 22/02/2011, à 12:53

Hizoka

Re : [BASh]Récupérer des informations d'un programme en cours d'execution

salut,

merci beaucoup pour ce topic !!

mais il se trouve que je rencontre encore un soucis...

http://forum.ubuntu-fr.org/viewtopic.ph … 9#p4009929

merci si vous avez une idée...


KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github

Hors ligne

#16 Le 11/04/2011, à 01:04

Hizoka

Re : [BASh]Récupérer des informations d'un programme en cours d'execution

je relance le topic car je suis face à un logiciel qui pose un petit soucis smile

bien que la 3/4 fonctionne arrivé un moment, pouff ca bloque alors que dans le retour console, il continue d'afficher des points (mais beaucoup plus lentement).

une idée ?


KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github

Hors ligne