Comment éliminer les inconvénients lors du démarrage d'une interface graphique à partir d'un terminal?

Je préfère lancer des applications charts à partir d'une window de terminal plutôt que d'utiliser un bureau graphique. Un inconvénient fréquent est que souvent les développeurs n'ont pas prévu ce type d'utilisation, de sorte que l'application imprime beaucoup de messages inutiles, cryptiques ou non informatifs à stdout ou stderr. Un encombrement supplémentaire sur le terminal se produit parce que l'exécution du programme en arrière-plan, avec un &, génère des rapports sur la création et la fin du travail.

Qu'est-ce qu'une solution de contournement pour ces problèmes qui accepte les arguments de command line et gère l'autocomplétion?

Connexes: https://stackoverflow.com/questions/7131670/make-bash-alias-that-takes-parameter

Rediriger immédiatement l'erreur standard vers /dev/null est une mauvaise idée, car il masquera les premiers messages d'erreur, et les échecs peuvent être difficiles à diagnostiquer. Je suggère quelque chose comme le script zsh start-app :

 #!/usr/bin/env zsh coproc "$@" 2>&1 quit=$(($(date +%s)+5)) nlines=0 while [[ $((nlines++)) -lt 10 ]] && read -p -t 5 line do [[ $(date +%s) -ge $quit ]] && break printf "[%s] %s\n" "$(date +%T)" "$line" done & 

Il suffit de l'exécuter avec l' start-app your_command argument ...

Ce script affichera au plus 10 lignes de messages et pendant au plus 5 secondes. Notez cependant que si l'application se bloque immédiatement (par exemple en raison d'une erreur de segmentation), vous ne verrez aucun message d'erreur. Bien sûr, vous pouvez modifier ce script de différentes façons pour faire ce que vous voulez …

Remarque: Pour que les compléments fonctionnent avec start-app dans zsh, il suffit de faire:

 compdef _precommand start-app 

et dans bash:

 complete -F _command start-app 

(copié de celui pour exec et time dans /usr/share/bash-completion/bash_completion ).

Une autre possibilité est d'utiliser la command pour rétrograder l' exec d'un builtin spécial à un ancien builtin simple comme:

 alias shh='command exec >/dev/null 2>&1' 

Alors maintenant, vous pouvez faire:

 (shh; call some process &) 

Je viens de remarquer que la command ne fonctionne pas dans zsh (comme cela semble le faire dans la plupart des autres shells) , mais là où ça ne marche pas, vous pouvez le faire à la place:

 alias shh='eval "exec >/dev/null 2>&1"' 

… qui devrait fonctionner partout.

En fait, vous pourriez même faire:

 alias shh='command exec >"${O:-/dev/null}" 2>&1' 

Donc, vous pourriez faire:

 O=./logfile; (shh;echo can anyone hear &) O=; (shh; echo this\? &) cat ./logfile 

SORTIE

 can anyone hear 

Suite à une discussion de commentaire avec @ vinc17, il est intéressant de noter que presque toutes les sorties de la console d'une application graphique sont généralement destinées à la console tty de X Lorsque vous exécutez une application X partir d'un file .desktop , la sortie qu'elle génère est apathée vers le terminal virtuel de X , quel que soit le tty à partir duquel vous avez lancé X en premier lieu. Je peux adresser ce numéro de tty avec $XDG_VTNR .

Curieusement, et peut-être parce que je viens de commencer à utiliser startx , je n'arrive plus à écrire dans /dev/tty$XDG_VTNR . Cela peut également avoir un lien avec le changement très récent et radical implémenté avec Xorg v1.16 qui lui permet de s'exécuter sous une session user systemd plutôt que d'exiger des privilèges root .

Pourtant, je peux faire:

 alias gui='command exec >/dev/tty$((1+$XDG_VTNR)) 2>&1' (gui; some x app &) 

Maintenant, toutes les sorties de console de l' some x app sont apathées vers /dev/tty$((1+$XDG_VTNR)) plutôt que la pty de mon xterm . Je peux get la dernière page de ceci à tout moment comme:

 fmt </dev/vcs$((1+$XDG_VTNR)) 

Il est probablement préférable de dédier un terminal virtuel à la sortie de journalisation de toute façon. /dev/console est généralement déjà réservé pour cela, mais vous préférerez peut-être ne pas faire la chown qui est probablement nécessaire pour que vous puissiez écrire allègrement à cela. Vous pouvez avoir une fonction qui vous permet de faire un printk – qui est essentiellement l'printing de /dev/console – et pourrait donc l'utiliser comme je suppose.

Une autre façon de le faire serait de consacrer un pty à de tels buts. Vous pouvez par exemple garder une window xterm ouverte, save la sortie de tty lorsqu'elle est exécutée à partir d'une variable d'environnement et utiliser cette valeur comme destination pour la sortie de gui . De cette façon, tous les journaux seraient apathés vers une window de journal séparée, que vous pourriez ensuite faire défiler si vous le souhaitez.

J'ai déjà écrit une réponse sur la façon dont une chose similaire pourrait être fait avec l'histoire de bash , si vous êtes intéressé.

Cette réponse est pour bash. Par exemple, voici ce que je fais dans mon .bashrc pour faire une command de commodité ev pour démarrer le visualiseur PDF Evince.

 ev() { (evince "$1" 1>/dev/null 2>/dev/null &) } complete -f -o default -X '!*.pdf' ev 

La première ligne définit une fonction ev . Le nom d'une fonction sera reconnu lorsque vous l'utiliserez sur la command line comme ceci:

 ev foo.pdf 

(Il s'agit d'un mécanisme différent de celui des alias et a une priorité inférieure.) La sortie de Evince vers stdin et stdout est envoyée au bitbucket (/ dev / null). L'esperluette met le travail en arrière-plan. En entourant la command entre parenthèses, il est exécuté dans un sous-shell pour qu'il n'imprime pas les messages concernant la création du travail en arrière-plan ou son achèvement.

La deuxième ligne de mon file .bashrc utilise la fonction complète de bash pour dire à bash que l'argument de la command ev devrait être un file avec l'extension pdf. Cela signifie que si j'ai aussi des files foo.tex, foo.aux, etc., assis dans mon directory, je peux taper ev foo et ev foo sur la touche de tabulation, et bash saura compléter le file en tant que foo.pdf.