¿Cómo eliminar molestias al iniciar una GUI desde una terminal?

14

Prefiero iniciar aplicaciones GUI desde una ventana de terminal en lugar de usar un escritorio gráfico. Una molestia frecuente es que a menudo los desarrolladores no han anticipado este tipo de uso, por lo que la aplicación imprime muchos mensajes inútiles, crípticos o poco informativos en stdout o stderr. Se produce un mayor desorden en el terminal porque ejecutar el programa en segundo plano, con un &, genera informes de la creación y finalización del trabajo.

¿Cuál es la solución para estos problemas que aceptarán argumentos de la línea de comandos y manejarán el autocompletado?

Relacionado: /programming/7131670/make-bash-alias-that-takes-parameter

Ben Crowell
fuente

Respuestas:

15

Redirigir el error estándar de inmediato /dev/nulles una mala idea, ya que ocultará los primeros mensajes de error y las fallas pueden ser difíciles de diagnosticar. Sugiero algo como el siguiente start-appscript zsh:

#!/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 &

Solo ejecútalo con: start-app your_command argument ...

Este script generará como máximo 10 líneas de mensajes y durante un máximo de 5 segundos. Sin embargo, tenga en cuenta que si la aplicación falla inmediatamente (por ejemplo, debido a un error de segmentación), no verá ningún mensaje de error. Por supuesto, puede modificar este script de varias maneras para hacer lo que quiera ...

Nota: Para que las terminaciones funcionen start-appen zsh, es suficiente hacer:

compdef _precommand start-app

y en bash:

complete -F _command start-app

(copiado de uno para execy timeen /usr/share/bash-completion/bash_completion).

vinc17
fuente
66
Bonita idea, +1. Pero no estoy de acuerdo con que sea una mala idea en general redirigir stderr desde una aplicación GUI. El 99% de todos los usuarios lo invocarán desde un escritorio gráfico, por lo que nunca verían nada que fuera a stderr. El software está diseñado para informar errores a través de la GUI. Lo que ves en stdout y stderr es típicamente mensajes de depuración que los desarrolladores no se molestaron en sacar porque creían que nadie los vería.
Ben Crowell
@BenCrowell Estoy de acuerdo en que las aplicaciones GUI deben informar errores a través de la GUI, pero en algunos casos, puede suceder que la aplicación falle antes de iniciar la GUI. Esto ocurre en particular cuando la aplicación se invoca a través de un script de envoltura que analiza los argumentos (en general, esto no es un problema para los usuarios que inician la aplicación desde el escritorio, ya que en este caso, los argumentos deben ser correctos).
vinc17
@BenCrowell También pienso en el caso en el $DISPLAYque no está configurado (por ejemplo, si el usuario olvidó un -Xfor ssh) o un problema de autorización X como aquí: unix.stackexchange.com/questions/108679/…
vinc17
@mikeserv Creo que varios usuarios pueden estar interesados ​​en esta pregunta (no solo el OP), y pueden usar bash o zsh. Acabo de agregar una nota para completar en zsh y bash. Como puede ver, esto es simple.
vinc17
@mikeserv Tenga en cuenta que hay una prueba en la fecha. Más simple y más portátil, pero menos flexible si uno quiere agregar características: "$@" 2>&1 | { quit=$(($(date +%s)+5)); while read line && [ $(date +%s) -lt $quit ]; do printf "[%s] %s\n" "$(date +%T)" "$line"; done; } | head -n 10 &(el punto más importante fue la idea, no la implementación real).
vinc17
5

Esta respuesta es para bash. Como ejemplo, esto es lo que hago en mi .bashrc para hacer un comando conveniente evpara iniciar el visor de PDF Evince.

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

La primera línea define una función ev. El nombre de una función se reconocerá cuando la use en la línea de comando de esta manera:

ev foo.pdf

(Este es un mecanismo diferente que los alias, y tiene menor prioridad). La salida de Evince a stdin y stdout se envía al bitbucket (/ dev / null). El signo comercial pone el trabajo en segundo plano. Rodear el comando entre paréntesis hace que se ejecute en una subshell para que no imprima mensajes sobre la creación del trabajo en segundo plano o su finalización.

La segunda línea de mi .bashrc usa la función completa de bash para decirle a bash que se espera que el argumento del comando ev sea un archivo con la extensión pdf. Esto significa que si también tengo archivos foo.tex, foo.aux, etc., en mi directorio, puedo escribir ev fooy presionar la tecla de tabulación, y bash sabrá completar el nombre de archivo como foo.pdf.

Ben Crowell
fuente
1
Ben, para que lo sepas, podrías estar exagerando un poco la función. Sin ofender, es una gran respuesta y fui el primero en votar las preguntas y respuestas, pero ... consideraev() (evince "$@" >&2 &) 2>/dev/null
mikeserv el
O bienev() (evince "$@" &>/dev/null $)
Glenn Jackman
@glenn: Creo que te referías al penúltimo personaje en tu sugerencia de ser un &.
G-Man dice 'reinstalar a Monica' el
Si, muy bien.
Glenn Jackman
5

Otra posibilidad es usar commandpara degradar execde una construcción especial a una construcción simple como:

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

Entonces ahora puedes hacer:

(shh; call some process &)

Acabo de notar que commandno funciona zsh (como parece hacerlo en la mayoría de los otros shells) , pero donde no funciona, puede hacerlo:

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

... que debería funcionar en todas partes.

De hecho, incluso podrías hacer:

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

Entonces podrías hacer:

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

SALIDA

can anyone hear

Después de una discusión de comentarios con @ vinc17, vale la pena señalar que casi toda la salida de la consola de una aplicación GUI generalmente está destinada a Xsu consola. Cuando ejecuta una Xaplicación desde un X .desktoparchivo, la salida que genera se enruta a Xla terminal virtual, que es cualquier cosa desde la que se inició Xen primer lugar. Puedo abordar este número tty con $XDG_VTNR.

Aunque parezca extraño, y tal vez porque recién comencé a usarlo startx, parece que ya no puedo escribirle /dev/tty$XDG_VTNR. Esto también puede (como creo que es más probable) tener algo que ver con el cambio muy reciente y drástico implementado con Xorgv1.16 que le permite ejecutarse bajo una systemdsesión de usuario en lugar de requerir privilegios de root .

Aún así, puedo hacer:

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

(gui; some x app &)

Ahora toda some x appla salida de la consola se enruta en /dev/tty$((1+$XDG_VTNR))lugar de la de mi xtermpty. Puedo obtener la última página de esto en cualquier momento como:

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

Probablemente sea la mejor práctica dedicar algún terminal virtual para registrar la salida de todos modos. /dev/consolegeneralmente ya está reservado para esto, aunque es posible que prefiera no hacer lo chownque es probable que tenga que escribir alegremente. Es posible que tenga alguna función que le permita hacer printk, que básicamente es imprimir en/dev/console , y, por lo tanto, podría usarlo de esa manera, supongo.

Otra forma de hacer esto sería dedicar una piedad a tales propósitos. Podría, por ejemplo, mantener una xtermventana abierta, guardar la salida de ttycuando se ejecuta desde allí en una variable de entorno y usar ese valor como destino paragui la salida de. De esa manera, todos los registros se enrutarían a una ventana de registro separada, que luego podría desplazarse si lo desea.

Una vez escribí una respuesta sobre cómo se podría hacer algo similar con la bashhistoria, si estás interesado.

mikeserv
fuente
1
Sugiero que elimine su comentario sobre la salida de, echo $?ya que agrega información inútil y se basa en un error en bash, que acabo de informar aquí: lists.gnu.org/archive/html/bug-bash/2014- 08 / msg00081.html y en Debian BTS: bugs.debian.org/cgi-bin/bugreport.cgi?bug=758969
vinc17
@ vinc17 sí, supongo que debo haberlo hecho en bash, lo cual es extraño, porque nunca uso ese shell. Supongo que solo por esta respuesta.
mikeserv