터미널에서 GUI를 시작할 때 성가심을 제거하는 방법은 무엇입니까?


14

그래픽 데스크탑을 사용하는 대신 터미널 창에서 GUI 응용 프로그램을 실행하는 것을 선호합니다. 빈번한 성가심은 종종 개발자가 이러한 유형의 사용을 예상하지 않았기 때문에 응용 프로그램이 쓸모없고, 암호가 있거나 정보가없는 메시지를 stdout 또는 stderr에 인쇄합니다. &를 사용하여 백그라운드에서 프로그램을 실행하면 작업 작성 및 종료에 대한 보고서가 생성되므로 터미널에서 더 혼란이 발생합니다.

명령 줄 인수를 허용하고 자동 완성을 처리하는 이러한 문제에 대한 해결 방법은 무엇입니까?

관련 : /programming/7131670/make-bash-alias-that-takes-parameter

답변:


15

표준 오류를 즉시 리디렉션 /dev/null하는 것은 초기 오류 메시지를 숨기고 실패를 진단하기 어려울 수 있으므로 좋지 않습니다. 다음 start-appzsh 스크립트 와 같은 것을 제안합니다 .

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

다음과 같이 실행하십시오. start-app your_command argument ...

이 스크립트는 최대 10 줄의 메시지와 최대 5 초 동안 출력합니다. 그러나 응용 프로그램이 즉시 충돌하는 경우 (예 : 분할 오류로 인해) 오류 메시지가 표시되지 않습니다. 물론, 원하는 방식으로이 스크립트를 다양한 방법으로 수정할 수 있습니다 ...

참고 : start-appzsh에서 완료 작업 을 수행하려면 다음을 수행하면됩니다.

compdef _precommand start-app

그리고 bash에서 :

complete -F _command start-app

( exectime에서 하나에서 복사 됨 /usr/share/bash-completion/bash_completion).


6
귀여운 생각, +1 그러나 일반적으로 stderr을 GUI 응용 프로그램에서 리디렉션하는 것은 나쁜 생각이라는 데 동의하지 않습니다. 모든 사용자의 99 %가 그래픽 데스크탑에서이를 호출하므로 stderr에 전달 된 내용은 절대 보지 못합니다. 이 소프트웨어는 GUI를 통해 오류를보고하도록 설계되었습니다. stdout 및 stderr에 표시되는 것은 일반적으로 개발자가 누군가가 보지 않을 것이라고 생각했기 때문에 개발자가 꺼내지 않아도되는 메시지를 디버깅하는 것입니다.
벤 크로 웰

@ BenCrowell GUI 응용 프로그램이 GUI를 통해 오류를보고해야한다는 데 동의하지만 경우에 따라 GUI를 시작하기 전에 응용 프로그램이 실패 할 수 있습니다. 이는 특히 인수를 구문 분석하는 랩퍼 스크립트를 통해 애플리케이션을 호출 할 때 발생합니다 (일반적으로이 경우에는 인수가 정확해야하므로 데스크탑에서 앱을 시작하는 사용자에게는 문제가되지 않습니다).
vinc17

@BenCrowell 또한 $DISPLAY설정되지 않은 경우 (예 : 사용자 -X가 ssh를 잊어 버린 경우 ) 또는 다음과 같은 X 인증 문제가 있다고
vinc17

@ mikeserv 다양한 사용자가 OP뿐만 아니라이 질문에 관심이 있고 bash 또는 zsh를 사용할 수 있다고 생각합니다. 방금 zsh와 bash에서 완료에 대한 메모를 추가했습니다. 보다시피, 이것은 간단합니다.
vinc17

@mikeserv 날짜에 대한 테스트가 있습니다. 기능을 추가하려는 경우 더 단순하고 휴대 가능하지만 유연성이 떨어집니다 "$@" 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 &(가장 중요한 구현은 실제 구현이 아니라 아이디어).
vinc17

5

이 대답은 bash입니다. 예를 들어, evPDF 뷰어 Evince를 시작 하는 편리한 명령 을 만들기 위해 .bashrc에서 수행하는 작업이 있습니다.

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

첫 번째 줄은 함수를 정의합니다 ev. 함수 이름은 다음과 같이 명령 행에서 사용할 때 인식됩니다.

ev foo.pdf

(이것은 별칭과 다른 메커니즘이며 우선 순위가 낮습니다.) stdin 및 stdout에 대한 Evince의 출력은 비트 버킷 (/ dev / null)으로 전송됩니다. 앰퍼샌드는 백그라운드에서 작업을 수행합니다. 명령을 괄호로 묶으면 명령이 서브 쉘에서 실행되어 백그라운드 작업 작성 또는 완료에 대한 메시지를 인쇄하지 않습니다.

내 .bashrc의 두 번째 줄은 bash의 complete 함수를 사용하여 bash에게 ev 명령의 인수가 확장자가 pdf 인 파일이 될 것이라고 bash에 알려줍니다. 즉, 디렉토리에 foo.tex, foo.aux 등의 파일이 있으면 ev foo탭 키를 입력 하고 누르면 bash가 파일 이름을 foo.pdf로 완성한다는 것을 알 수 있습니다.


1
벤, 아시다시피, 기능을 약간 과도하게 사용하고있을 수 있습니다. 그것은 좋은 대답 나는 Q & A를 upvote에하는 첫번째이었다,하지만 ... 고려 - 나쁜 뜻은 의미가 없다ev() (evince "$@" >&2 &) 2>/dev/null
mikeserv

또는ev() (evince "$@" &>/dev/null $)
glenn jackman

@glenn : 나는 당신이 당신의 제안에서 두 번째 문자가을 의미한다고 생각합니다 &.
G-Man, 'Reinstate

네 맞습니다.
glenn jackman

5

또 다른 가능성은 특수 내장에서 일반 내장으로 command강등 exec하는 데 사용할 수 있습니다 .

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

이제 할 수 있습니다 :

(shh; call some process &)

방금 command작동하지 않는 zsh 것으로 나타났습니다 (대부분의 다른 쉘 에서처럼) 작동하지 않는 곳에서 대신 할 수 있습니다.

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

... 어디서나 작동해야합니다.

실제로, 당신은 할 수도 있습니다 :

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

그래서 당신은 할 수 있습니다 :

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

산출

can anyone hear

@ vinc17에 대한 의견 토론에 이어 거의 모든 GUI 응용 프로그램의 콘솔 출력이 일반적으로 tty-콘솔을위한 것임을 주목할 가치가 X있습니다. 파일에서 X앱 을 실행하면 X .desktop생성 된 출력이 X의 가상 터미널로 라우팅됩니다 X. 이것은 처음부터 시작한 것이 무엇이든 tty 입니다. 이 tty 번호를로 해결할 수 있습니다 $XDG_VTNR.

이상하게도-아마 사용하기 시작했기 때문에 startx더 이상 쓸 수없는 것 같습니다 /dev/tty$XDG_VTNR. 이것은 또한 할 수있다 (좀 더 가능성이 생각하는) 으로 구현 된 매우 최근의 급격한 변화와 함께 할 수있는 뭔가가 Xorg그것에서 실행 할 수 있습니다 v1.16 systemd오히려 필요없이 사용자 세션 루트 권한을.

여전히, 나는 할 수 있습니다 :

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

(gui; some x app &)

이제 모든 some x app콘솔 출력이 /dev/tty$((1+$XDG_VTNR))xtermpty 가 아닌 라우팅됩니다 . 다음과 같이 언제든지 마지막 페이지를 얻을 수 있습니다.

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

어쨌든 출력을 기록하기 위해 일부 가상 터미널을 전용으로 사용하는 것이 가장 좋습니다. /dev/console일반적으로 이미 예약되어 있지만, chown글을 쓰는 데 필요한 작업을 수행하지 않는 것이 좋습니다. 당신은 당신이 할 수있는 기능을 가지고 있습니다 printk-기본적으로 인쇄하는 것입니다 /dev/console-그래서 내가 생각하는 방식으로 사용할 수 있습니다.

이를 수행하는 또 다른 방법은 pty 를 그러한 목적으로 바치는 것 입니다. 예를 들어, xterm창을 열어 두고 tty환경 변수에서 실행될 때 의 출력을 저장하고 해당 값을 gui의 출력 대상으로 사용할 수 있습니다. 이러한 방식으로 모든 로그가 별도의 로그 창으로 라우팅되어 원하는 경우 스크롤 할 수 있습니다.

나는 당신이 관심이 있다면, 역사 와 비슷한 일을 어떻게 할 수 있는지에 대한 답을 한 번 썼습니다 bash.


1
echo $?쓸모없는 정보를 추가하고 bash의 버그를 기반으로 한 결과에 대한 언급을 제거하는 것이 좋습니다 . list.gnu.org/archive/html/bug-bash/2014- 08 / msg00081.html 및 데비안 BTS : bugs.debian.org/cgi-bin/bugreport.cgi?bug=758969
vinc17

@ vinc17 yup-나는 bash에서 그렇게해야한다고 생각합니다. 왜냐하면 나는 그 쉘을 사용하지 않기 때문입니다. 이 답변에 대한 것 같아요.
mikeserv
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.