Como eliminar aborrecimentos ao iniciar uma GUI a partir de um terminal?

13

Eu prefiro lançar aplicativos GUI a partir de uma janela de terminal, em vez de usar uma área de trabalho gráfica. Um aborrecimento freqüente é que muitas vezes os desenvolvedores não previram esse tipo de uso, então o aplicativo imprime muitas mensagens inúteis, enigmáticas ou não informativas para stdout ou stderr. Mais confusão no terminal ocorre porque a execução do programa em segundo plano, com um & gera relatórios da criação e término do trabalho.

O que é uma solução alternativa para esses problemas que aceitarão argumentos de linha de comando e manipularão a autocompletar?

Relacionados: link

    
por Ben Crowell 18.08.2014 / 01:46

3 respostas

15

Redirecionar o erro padrão imediatamente para /dev/null é uma má idéia, já que ele oculta as mensagens de erro antecipadas e as falhas podem ser difíceis de diagnosticar. Sugiro algo como o seguinte script start-app 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 &

Basta executá-lo com: start-app your_command argument ...

Este script produzirá no máximo 10 linhas de mensagens e no máximo 5 segundos. No entanto, observe que, se o aplicativo falhar imediatamente (por exemplo, devido a uma falha de segmentação), você não verá nenhuma mensagem de erro. Claro, você pode modificar este script de várias maneiras para fazer o que quiser ...

Observação: para que as conclusões funcionem com start-app no zsh, basta:

compdef _precommand start-app

e no bash:

complete -F _command start-app

(copiado daquele para exec e time em /usr/share/bash-completion/bash_completion ).

    
por 18.08.2014 / 02:47
4

Esta resposta é para bash. Por exemplo, aqui está o que eu faço no meu .bashrc para fazer um comando de conveniência ev para iniciar o visualizador de PDF Evince.

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

A primeira linha define uma função ev . O nome de uma função será reconhecido quando você a usar na linha de comando da seguinte forma:

ev foo.pdf

(Este é um mecanismo diferente de aliases, e tem menor prioridade.) A saída do Evince para stdin e stdout é enviada para o bitbucket (/ dev / null). O e comercial coloca o trabalho em segundo plano. Rodear o comando entre parênteses faz com que seja executado em um subshell para que ele não imprima mensagens sobre a criação do job em background ou sua conclusão.

A segunda linha do meu .bashrc usa a função completa do bash para dizer ao bash que o argumento do comando ev deve ser um arquivo com a extensão pdf. Isto significa que se eu também tiver arquivos foo.tex, foo.aux, etc, sentados em meu diretório, eu posso digitar ev foo e apertar a tecla tab, e o bash saberá completar o nome do arquivo como foo.pdf. / p>     

por 18.08.2014 / 01:46
4

Outra possibilidade é usar command para rebaixar exec de um especial incorporado para um antigo interno como:

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

Agora você pode fazer:

(shh; call some process &)

Acabei de notar que command não funciona em zsh (como parece na maioria dos outros shells) , mas onde não funciona você pode fazer:

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

... que deve funcionar em todos os lugares.

Na verdade, você pode até fazer:

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

Então você poderia fazer:

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

OUTPUT

can anyone hear

Continuando com uma discussão de comentários com @ vinc17, vale a pena notar que quase toda a saída do console de um aplicativo GUI é geralmente destinada ao console de X - seu console. Quando você executa um aplicativo X a partir de um arquivo X .desktop , a saída que gera é roteada para o terminal virtual X - que é o tty de onde você iniciou X em primeiro lugar. Eu posso endereçar este número tty com $XDG_VTNR .

Estranhamente - e talvez porque comecei a usar startx - não consigo mais escrever apenas em /dev/tty$XDG_VTNR . Isso pode também (como acho mais provável) ter algo a ver com a mudança muito recente e drástica implementada com Xorg v1.16 que permite que ele seja executado sob uma sessão de usuário systemd do que exigir privilégios root .

Ainda assim, posso fazer:

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

(gui; some x app &)

Agora, todas as saídas do console de some x app estão sendo roteadas para /dev/tty$((1+$XDG_VTNR)) , em vez de minha xterm 's pty. Eu posso pegar a última página disso a qualquer momento como:

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

Provavelmente, é uma prática recomendada dedicar algum terminal virtual para registrar a saída de qualquer maneira. O /dev/console geralmente já é reservado para isso, embora você possa preferir não fazer o chown que provavelmente será necessário para que você possa escrever com atenção. Você pode ter alguma função que permite fazer um printk - que é basicamente imprimir em /dev/console - e assim poderia usá-lo dessa forma, suponho.

Outra maneira de fazer isso seria dedicar um pty a esses propósitos. Você poderia, por exemplo, manter uma janela xterm aberta, salvar a saída de tty quando executada a partir de lá em uma variável de ambiente e usar esse valor como destino para a saída de gui . Dessa forma, todos os logs seriam roteados para uma janela de log separada, que você poderia percorrer se quisesse.

Uma vez eu escrevi uma resposta sobre como uma coisa semelhante poderia ser feita com a história bash , se você está interessado.

    
por 18.08.2014 / 02:50