Contenu | Rechercher | Menus

Annonce

DVD, clés USB et t-shirts Ubuntu-fr disponibles sur la boutique En Vente Libre

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 31/10/2020, à 18:54

ft

[GJS] lancer une commande bash asynchrone

Salut,

Je développe l'extension Snap Manager pour Gnome Shell :
https://extensions.gnome.org/extension/ … ap-manager

Elle fonctionne bien, en tout cas pour ce que j'en attendais. J'ai implémenté une vérification initiale (au lancement de session) des mises à jour des snaps :
https://github.com/fthx/snap-manager/bl … on.js#L101
Le code est fonctionnel, la notif Gnome est bien affichée, mais je me rends compte que la commande bash est exécutée en bloquant le fil d'exécution principal. (Bouger la souris sur les items du menu système avant et pendant les 10 secondes de délai avant que le pop-up s'affiche pour s'en rendre compte.)

Bref, j'ai besoin d'exécuter en asynchrone une commande bash. Je sais qu'il existe la commande :
https://developer.gnome.org/glib/stable … line-async
mais elle ne me renvoie pas la sortie de la commande. Comment puis-je donc exécuter cette commande async tout en récupérant sa sortie ? Visiblement mes tentatives de débutant sur les promises/await/async ne remplissent pas leur mission, ma commande GLib.spawn_command_line_sync semble tourner malgré tout en synchrone.

Help needed ! Merci !


Thinkpad T480s, Ubuntu GNOME 20.04

Hors ligne

#2 Le 31/10/2020, à 20:37

Vobul

Re : [GJS] lancer une commande bash asynchrone

Je ne suis pas spécialiste de gnome, mais je pense qui si la version async ne permet pas d'avoir l'output, c'est qu'il y a une raison. Peux-être peux-tu contourner le problème en mettant l'output dans un fichier de /tmp et en allant chercher son contenu une fois la promise resolved.


Vobul

Hors ligne

#3 Le 31/10/2020, à 20:45

abakkk

Re : [GJS] lancer une commande bash asynchrone

Ça tombe bien, j'ai un wrapper assez générique tout prêt sous la main (que j'utilise avec youtube-dl ici):

// Callback parameters: ok(Boolean), standart_output(String), standart_error(String), exit_status(Number)
const spawnCommandLineAsync = function(commandLine, callback) {
    let success_, argv, pid, stdin, stdout, stderr;

    try {
        [success_, argv] = GLib.shell_parse_argv(commandLine);
        [success_, pid, stdin, stdout, stderr] = GLib.spawn_async_with_pipes(null, argv, null, GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD, null);
    } catch (e) {
        logError(e);
        callback(false);
        return;
    }

    GLib.close(stdin);
    let outUnixStream = new Gio.UnixInputStream({ fd: stdout, close_fd: true });
    let errUnixStream = new Gio.UnixInputStream({ fd: stderr, close_fd: true });
    let outDataStream = new Gio.DataInputStream({ base_stream: outUnixStream, close_base_stream: true });
    let errDataStream = new Gio.DataInputStream({ base_stream: errUnixStream, close_base_stream: true });

    let read = (dataStream, array) => {
        dataStream.read_line_async(GLib.PRIORITY_LOW, null, (dataStream, res) => {
            let [line, length_] = dataStream.read_line_finish_utf8(res);
            if (line !== null) {
                array.push(line);
                read(dataStream, array);
            } else {
                dataStream.close(null);
            }
        });
    };

    let outputs = [];
    let errors = [];

    read(outDataStream, outputs);
    read(errDataStream, errors);

    GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, (pid, status) => {
        GLib.spawn_close_pid(pid);
        callback(true, outputs.join('\n'), errors.join('\n'), status);
    });
};

Pour ce genre d'api un peu complexe, il peut-être utile de regarder la documentation en Javascript: gjs-docs.gnome.org.

Il doit être possible de "promisifier" la chose. Il y a des développeurs de GJS qui s'amusent à le faire.

Dernière modification par abakkk (Le 31/10/2020, à 21:04)

Hors ligne

#4 Le 01/11/2020, à 22:04

abakkk

Re : [GJS] lancer une commande bash asynchrone

A tout hasard, Snap n'a pas de service DBus? Ça serait plus simple.

Hors ligne

#5 Le 01/11/2020, à 22:45

ft

Re : [GJS] lancer une commande bash asynchrone

Ok désolé pour le retard, mais les mails de notif ont été traités comme des spams par Yahoo et donc non redirigés. C'est nouveau, ça... Bref.

Merci pour les réponses !

Pour DBus, je sais juste qu'il y a une histoire pour les snaps, mais pour la commande snap c'est en orbite géostationnaire au-dessus de mes connaissances.
Du coup j'ai procédé à peu près comme @Vobul le suggérait. Je fais un appel async à une commande qui écrit dans un fichier du dossier de l'extension, puis j'attends pour être sûr que ça se fait, puis je lis le fichier. C'est con mais je n'ai observé aucun mini-blocage de GNOME Shell.
https://github.com/fthx/snap-manager/bl … on.js#L104


Thinkpad T480s, Ubuntu GNOME 20.04

Hors ligne

#6 Le 02/11/2020, à 00:50

Vobul

Re : [GJS] lancer une commande bash asynchrone

Si c'est con mais que ça marche, alors c'est pas con wink


Vobul

Hors ligne

#7 Le 02/11/2020, à 07:49

ft

Re : [GJS] lancer une commande bash asynchrone

Ah mais attention, j'y avais pensé avant de lire ta suggestion ! (Puisque je ne savais pas qu'il y avait des réponses à mes soucis !)
Donc le "con" était pour moi, preum's !
tongue

Au passage, la toute nouvelle version de l'extension a été reviewée cette nuit par Andy Holmes (qui est super efficace) :
https://extensions.gnome.org/extension/ … p-manager/
(elle informe 30s après le démarrage de la situation des màj des snaps, dans une notif GS). Si vous avez des remarques, je prends.

Puisque je vous tiens, voilà ce que j'aimerais faire pour la suite :

- Pour le moment, l'appli utilise GNOME Terminal pour son interface principale. J'aimerais créer des boîtes de dialogue zolies natives GNOME pour demander des infos à l'utilisateur, puis sortir des infos dans de zolies boîtes GNOME aussi. Vous avez une référence ou davantage pour ce faire ?

- Pour le moment, j'attends 20 s après le démarrage de session pour faire les vérif de màj, afin d'attendre le réseau dans les cas leeeeeents. Mais évidemment j'aimerais plutôt attendre que ledit réseau soit établi, tout simplement. Il doit y avoir moyen, mais la question c'est : lequel ?


Thinkpad T480s, Ubuntu GNOME 20.04

Hors ligne