Bir terminalden bir GUI başlatırken rahatsızlıklar nasıl ortadan kaldırılır?


14

GUI uygulamalarını grafiksel bir masaüstü kullanmak yerine bir terminal penceresinden başlatmayı tercih ediyorum. Sık sık bir sıkıntı, geliştiricilerin bu tür bir kullanım beklemedikleri, bu yüzden uygulama stdout veya stderr'e çok sayıda gereksiz, şifreli veya bilgilendirici mesaj yazdırıyor. Terminalde daha fazla karmaşa oluşması, programı arka planda çalıştırmanın bir & ile işin yaratılması ve sonlandırılması hakkında raporlar oluşturması nedeniyle oluşur.

Bu sorunlar için komut satırı bağımsız değişkenlerini kabul edecek ve otomatik tamamlamayı işleyecek geçici çözüm nedir?

İlgili: /programming/7131670/make-bash-alias-that-takes-parameter

Yanıtlar:


15

Standart hatayı derhal yeniden yönlendirmek /dev/nullkötü bir fikirdir çünkü erken hata mesajlarını gizleyecektir ve arızaların teşhis edilmesi zor olabilir. Aşağıdaki start-appzsh komut dosyası gibi bir şey önermek :

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

Sadece ile çalıştırın: start-app your_command argument ...

Bu komut dosyası en fazla 10 satır ve en fazla 5 saniye süreyle çıktı verecektir. Ancak, uygulama hemen kilitlenirse (örn. Bir segmentasyon hatası nedeniyle), herhangi bir hata mesajı görmeyeceğinizi unutmayın. Tabii ki, bu betiği istediğinizi yapmak için çeşitli şekillerde değiştirebilirsiniz ...

Not: Tamamlamaların start-appzsh ile çalışmasını sağlamak için:

compdef _precommand start-app

ve bash:

complete -F _command start-app

(için bir kopyalanır execve timeiçinde /usr/share/bash-completion/bash_completion).


6
Güzel fikir, +1. Ancak stderr'i bir GUI uygulamasından yönlendirmenin genel olarak kötü bir fikir olduğunu kabul etmiyorum. Tüm kullanıcıların% 99'u onu grafiksel bir masaüstünden çağırır, böylece stderr'a giden hiçbir şeyi görmezler. Yazılım, GUI aracılığıyla hataları rapor etmek için tasarlanmıştır. Stdout ve stderr'de gördüğünüz şey, geliştiricilerin almak için uğraşmadıkları mesajların hatalarını ayıklamaktır, çünkü kimsenin onları göreceğini düşünmediler.
Ben Crowell

@BenCrowell GUI uygulamalarının GUI aracılığıyla hata bildirmesi gerektiğini kabul ediyorum, ancak bazı durumlarda uygulamanın GUI'yi başlatmadan önce başarısız olabileceği düşünülebilir. Bu, özellikle uygulama bağımsız değişkenleri ayrıştıran bir sarıcı komut dosyası aracılığıyla çağrıldığında oluşur (genel olarak, bu durumda uygulamayı masaüstünden başlatan kullanıcılar için bu bir sorun değildir, çünkü argümanlar doğru olmalıdır).
vinc17

@BenCrowell Ayrıca $DISPLAYayarlanmamış durumda (örneğin, kullanıcı -Xssh için bir unutmuşsa ) veya burada olduğu gibi bir X yetkilendirme sorununu da düşünüyorum: unix.stackexchange.com/questions/108679/…
vinc17

@mikeserv Çeşitli kullanıcıların bu soru ile ilgilenebileceğini düşünüyorum (sadece OP değil) ve bash veya zsh kullanabilirler. Zsh ve bash'taki tamamlamalar için bir not ekledim. Gördüğünüz gibi, bu basit.
vinc17

@mikeserv Tarihte bir test olduğunu unutmayın. Daha basit ve daha taşınabilir, ancak özellik eklemek istiyorsa daha az esnek: "$@" 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 &(en önemli nokta, gerçek uygulama değil fikirdi).
vinc17

5

Bu cevap bash içindir. Örnek olarak, evPDF görüntüleyici Evince'yi başlatmak için bir kolaylık komutu yapmak için .bashrc dosyamda yaptığım şey .

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

İlk satır bir işlevi tanımlar ev. Bir işlevin adı, komut satırında şu şekilde kullanıldığında tanınır:

ev foo.pdf

(Bu takma adlardan farklı bir mekanizmadır ve önceliği daha düşüktür.) Evince'nin stdin ve stdout'a çıkışı bitbucket'e (/ dev / null) gönderilir. Ve işareti işi arka plana koyar. Komutun parantez içinde çevrilmesi, alt arka planda çalıştırılmasına neden olur, böylece arka plan işinin oluşturulması veya tamamlanmasıyla ilgili mesajlar yazdırmaz.

.Bashrc dosyamdaki ikinci satır, bash'ye ev komutunun argümanının pdf uzantılı bir dosya olması beklendiğini söylemek için bash işlevini kullanır. Bu, eğer dizinimde oturan foo.tex, foo.aux, vb. Dosyaları varsa, ev footab tuşuna basabilir ve vurabilirim ve bash dosya adını foo.pdf olarak tamamlayacağını bilir.


1
Ben, bilirsiniz, bu işlevi biraz abartıyor olabilirsiniz. Hiçbir suç anlamına geliyordu - bu harika bir cevap ve q & a'yı oylayan ilk kişi oldum, ama ... düşününev() (evince "$@" >&2 &) 2>/dev/null
mikeserv

Veyaev() (evince "$@" &>/dev/null $)
glenn jackman

@glenn: Önerinizdeki sondan bir önceki karakterin bir olması gerektiğine inanıyorum &.
G-Man, 'Monica'yı Yeniden Başlat' diyor

Evet, oldukça doğru.
glenn jackman

5

Bir başka olasılık kullanmaktır commanddemote için execbir gelen özel gibi bir düz eski yerleşiğinin yerleşiğini:

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

Şimdi şunları yapabilirsiniz:

(shh; call some process &)

Ben sadece commandişe yaramadı fark ettim zsh (diğer kabuklarda olduğu gibi ) , ama işe yaramazsa bunun yerine yapabilirsiniz:

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

... her yerde çalışmalı.

Aslında, şunları da yapabilirsiniz:

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

Böylece şunları yapabilirsiniz:

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

ÇIKTI

can anyone hear

@ Vinc17 ile bir yorum tartışmasının ardından, bir GUI uygulamasının konsol çıktısının neredeyse tümünün genellikle X'tty - konsolu için tasarlandığını belirtmek gerekir. Bir dosyayı bir Xuygulamadan çalıştırdığınızda, X .desktopoluşturduğu çıktı ilk olarak Xbaşlattığınız her tür tty'nin sanal terminaline yönlendirilir X. İle bu tty numarasını ele alabilirim $XDG_VTNR.

Garip bir şekilde - ve belki de kullanmaya yeni başladığım için startx- artık yazamıyorum /dev/tty$XDG_VTNR. Bu aynı zamanda (daha muhtemel olduğunu düşündüğüm gibi)Xorg v1.16 ile uygulanan ve kök ayrıcalıkları systemdyerine bir kullanıcı oturumu altında çalışmasına izin veren çok yeni ve köklü değişiklikle ilgili bir şey olabilir .

Yine de yapabilirim:

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

(gui; some x app &)

Şimdi tüm some x appkonsol çıkışı /dev/tty$((1+$XDG_VTNR))benim xtermpty yerine yönlendiriliyor . Bunun gibi herhangi bir zamanda son sayfasını alabilirsiniz:

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

Bazı sanal terminalleri çıktıyı yine de günlüğe ayırmak muhtemelen en iyi uygulamadır. /dev/consolegenel olarak bunun için ayrılmıştır, ancak buna chownaçıkça yazmanız için gerekli olanı yapmamayı tercih edebilirsiniz . printkTemelde baskı yapan /dev/console- ve sanırım bu şekilde kullanabileceğiniz bir işleve sahip olabilirsiniz.

Bunu yapmanın başka bir yolu da bu tür amaçlara bir pty ayırmak olacaktır. Örneğin, bir xtermpencereyi açık tutabilir tty, oradan çalıştırıldığında çıktısını bir ortam değişkeninde kaydedebilir ve bu değeri guiçıktı için hedef olarak kullanabilirsiniz . Bu şekilde, tüm günlükler ayrı bir günlük penceresine yönlendirilir ve daha sonra isterseniz kaydırabilirsiniz.

İlgileniyorsanız, bir zamanlar tarihle benzer bir şeyin nasıl yapılabileceği hakkında bir cevap yazdım bash.


1
Ben echo $?işe yaramaz bilgi ekler ve bash bir hata dayanmaktadır, çünkü çıktı hakkında yorumunuzu kaldırmanızı öneririz, burada az önce rapor: lists.gnu.org/archive/html/bug-bash/2014- 08 / msg00081.html ve Debian BTS'de
vinc17

@ vinc17 yup - sanırım bunu garip olan bash'de yapmalıydım - çünkü o kabuğu hiç kullanmam. sanırım sadece bu cevap için.
mikeserv
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.