• [^] # Re: Mais pourquoi est-il aussi méchant ?

    Posté par . En réponse au message zenity : processus père/fils, fifo,.... Évalué à 1.

    Bon, pas d'autre améliorations ?

    Aller, je ne résiste pas à faire une nouvelle proposition ! :-)

    Voilà, c'est assez complet, avec tout plein de commentaires, tous les cas tordus auxquels j'ai pensé sont pris en compte, le ménage est fait.

    Ne reste plus qu'à remplacer la boucle for par le vrai boulot à faire, abstraire un peu pour le rendre générique et réutilisable (au cas où il y ai besoin de plusieurs progress dans le même script), etc..

    Je l'ai fait en Anglais, car je vais me le mettre de côté, çui-ci... :-)

    Enjoy !

    #!/bin/bash
    # (C) 2011 "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
    # License: GPLv2
    # In case the user cancels, we want to be notified
    cancelled=n
    # Create the fifo
    # Note! If the witer comes and goes (eg. multiple open()
    # and close() of the fifo), the reader seems to get a
    # SIGPIPE. So we just open the fifo once using FD#6, see below.
    # Original idea by "Tonton Benoit" <xmpp:maxime@neurone-network.org>
    fifo_dir="$( mktemp -d )"
    fifo="${fifo_dir}/fifo"
    mkfifo "${fifo}"
    # Print progress, and catch cancel
    # There is a slight race here, as we can get cancelled
    # between the check and the printf, but as we are emptying
    # the fifo (see below), we can still print into it.
    report_progress() {
     if [ "${cancelled}" = "n" ]; then
    printf "%s\n" "${1}" >&6 2>/dev/null
     else
     return 1
     fi
    }
    # Catch cancel:
    # - set global variable
    # - empty the fifo so we don't block in report_progress, above
    # Need to do that before running zenity, or there is
    # a slight race window where the user could cancel, and us
    # not having our trap set yet.
    # Note: when we finally remove the fifo, 'cat' will die. We
    # don't care about this, but we want it to be silent
    trap_cancel() {
     cancelled=y
     cat "${fifo}" >/dev/null 2>&1 &
    }
    trap trap_cancel SIGHUP
    # Start the progress report
    # Consign output to oblivion, as there is a race window
    # in case we were to remove the fifo just while zenity
    # was not yet finished (ie. on its dying path, but not
    # yet dead)
    zenity --progress --title="Test" \
     --text="progression..." \
     --percentage=0 \
     --auto-close \
     --auto-kill \
     >/dev/null 2>&1 \
     <"${fifo}" &
    progress_pid="${!}"
    # In case we are ourselves killed (think Ctrl-C!), we need
    # to kill zenity, and leave it no chance to bite us back.
    # Yes, there is a slight race window here, too, in case the
    # user kills us between the moment we launch zenity, and
    # the moment we set up the trap. But we can't set the trap
    # before we know the PID of zenity... This is unavoidable... :-(
    trap_int() {
     kill -9 ${progress_pid}
     exec 6>&-
     rm -rf "${fifo_dir}"
     printf 'Argh, user killed us... :-(\n'
     exit 1
    }
    trap trap_int SIGINT
    # Opening FD#6 for writing earlier than that seems
    # to hang?!?... OK, anyway we only need it now...
    exec 6>"${fifo}"
    # Start our job, now...
    for(( i=0; i<=100; i++ )); do
    sleep 0.1
     report_progress "${i}" || break;
    done
    # We end up here for two reasons:
    # 1- the job finished, so zenity (in auto-close) is now
    # about to die by itself, so will no longer bug us
    # 2- the job was cancelled, so zenity is about to die
    # by itself as well, so won't bother us either
    # So, we no longer have a valid reason to trap
    trap - SIGHUP SIGINT
    # The fifo is of no use, now. Close FD#6 first.
    exec 6>&-
    rm -rf "${fifo_dir}"
    if [ "${cancelled}" = "y" ]; then
    printf "Argh, user cancelled us... :-(\n"
    fi
    printf "Now, i='%s'\n" "${i}"
    

    Hop,
    Moi.