एक टर्मिनल से GUI शुरू करते समय झुंझलाहट को कैसे समाप्त करें?


14

मैं एक ग्राफ़िकल डेस्कटॉप का उपयोग करने के बजाय एक टर्मिनल विंडो से GUI एप्लिकेशन लॉन्च करना पसंद करता हूं। एक लगातार झुंझलाहट यह है कि अक्सर डेवलपर्स ने इस प्रकार के उपयोग का अनुमान नहीं लगाया है, इसलिए ऐप बहुत सारे बेकार, गुप्त, या बिना किसी सूचना के संदेश को stdout या stderr पर प्रिंट करता है। टर्मिनल पर और अव्यवस्था होती है क्योंकि पृष्ठभूमि में प्रोग्राम को चलाने के साथ, &, नौकरी के निर्माण और समाप्ति की रिपोर्ट उत्पन्न करता है।

इन समस्याओं के लिए एक वर्कअराउंड क्या है जो कमांड लाइन की दलीलों को स्वीकार करेगा और स्वतः पूर्णता को संभालेगा?

सम्बंधित: /programming/7131670/make-bash-alias-that-tat-the व्यास

जवाबों:


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

और बैश में:

complete -F _command start-app

(के लिए एक से नकल execऔर timeमें /usr/share/bash-completion/bash_completion)।


6
प्यारा विचार, १। लेकिन मैं असहमत हूँ कि यह GUI ऐप से stderr को पुनर्निर्देशित करने के लिए सामान्य रूप से एक बुरा विचार है। सभी उपयोगकर्ताओं में से 99% इसे एक ग्राफिकल डेस्कटॉप से ​​प्राप्त करेंगे, इसलिए उन्हें कभी भी ऐसा कुछ नहीं दिखाई देगा जो stderr में गया हो। सॉफ़्टवेयर को GUI के माध्यम से त्रुटियों की रिपोर्ट करने के लिए डिज़ाइन किया गया है। क्या आप stdout और stderr पर देखते हैं, आम तौर पर उन संदेशों को डीबग कर रहा है जो डेवलपर्स को बाहर निकालने के लिए परेशान नहीं करते थे क्योंकि उन्हें नहीं लगता था कि कोई भी उन्हें देखेगा।
बेन क्रॉवेल

@BenCrowell मैं मानता हूं कि GUI ऐप्स को GUI के माध्यम से त्रुटियों की रिपोर्ट करनी चाहिए, लेकिन कुछ मामलों में, ऐसा हो सकता है कि GUI प्रारंभ होने से पहले अनुप्रयोग विफल हो जाए। यह विशेष रूप से तब होता है जब एप्लिकेशन को एक रैपर स्क्रिप्ट के माध्यम से आमंत्रित किया जाता है जो तर्कों को पार्स करता है (सामान्य तौर पर, यह उन उपयोगकर्ताओं के लिए कोई समस्या नहीं है जो इस मामले में डेस्कटॉप से ​​ऐप शुरू करते हैं, तर्क सही होना चाहिए)।
vinc17

@BenCrowell मैं उस मामले के बारे में भी सोचता हूं जहां $DISPLAYसेट नहीं किया गया है (जैसे यदि उपयोगकर्ता -Xssh के लिए भूल गया है ) या एक एक्स प्राधिकरण समस्या यहाँ है: unix.stackexchange.com/questions/108679/…
vinc17

@mikeserv मुझे लगता है कि विभिन्न उपयोगकर्ताओं को इस सवाल में दिलचस्पी हो सकती है (न केवल ओपी), और वे या तो बैश या 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

यह जवाब बैश के लिए है। एक उदाहरण के रूप में, यहाँ मैं अपने .bashrc evमें पीडीएफ दर्शक इविसन को शुरू करने के लिए एक सुविधा कमांड बनाने के लिए क्या कर रहा हूँ ।

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

पहली पंक्ति एक फ़ंक्शन को परिभाषित करती है ev। किसी फ़ंक्शन का नाम तब पहचाना जाएगा जब आप इसका उपयोग कमांड लाइन पर इस तरह करते हैं:

ev foo.pdf

(यह उपनाम की तुलना में एक अलग तंत्र है, और इसकी प्राथमिकता कम है।) स्टड और स्टडआउट के लिए एवियन का आउटपुट बिटबकेट (/ देव / नल) को भेजा जाता है। एम्परसैंड पृष्ठभूमि में काम करता है। कोष्ठक में कमांड को घेरने से यह सब-सब्स्क्राइब में चला जाता है ताकि यह बैकग्राउंड जॉब के निर्माण या इसके पूरा होने के बारे में संदेश न छापे।

मेरे .bashrc की दूसरी पंक्ति bash को बताने के लिए bash के संपूर्ण फंक्शन का उपयोग करती है कि ev कमांड के तर्क में एक्सटेंशन पीडीएफ के साथ फाइल होने की उम्मीद है। इसका मतलब यह है कि अगर मेरे पास फ़ाइल foo.tex, foo.aux इत्यादि भी हैं, तो मेरी निर्देशिका में बैठकर, मैं ev fooटैब कुंजी को टाइप और हिट कर सकता हूं , और bash को foo.pdf के रूप में फ़ाइलनाम पूरा करना होगा।


1
बेन, जैसा कि आप जानते हैं, आप फ़ंक्शन को थोड़ा अधिक कर सकते हैं। कोई अपराध का मतलब नहीं था - यह एक महान जवाब है और मैं q & a को ev() (evince "$@" >&2 &) 2>/dev/null
उभारने

याev() (evince "$@" &>/dev/null $)
बजे ग्लेन जैकमैन

@glenn: मेरा मानना ​​है कि आप अपने सुझाव में पारंगत चरित्र के लिए थे &
जी-मैन का कहना है कि मोनिका '

हाँ, बिलकुल सही।
ग्लेन जैकमैन

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 ऐप के कंसोल आउटपुट आम तौर पर X'tty -' कंसोल के लिए अभिप्रेत है। जब आप Xकिसी X .desktopफ़ाइल से कोई ऐप चलाते हैं, तो वह जो आउटपुट उत्पन्न करता है, उसे Xवर्चुअल टर्मिनल पर रूट किया जाता है - जो कुछ भी ऐसा है, जिससे आप Xपहले स्थान पर लॉन्च हुए थे। मैं इस 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- और इसलिए मैं इसे इस तरह से उपयोग कर सकता हूं कि मुझे लगता है।

ऐसा करने का एक और तरीका यह होगा कि इस तरह के उद्देश्यों के लिए एक पैसा समर्पित किया जाए । उदाहरण के लिए, आप एक xtermखिड़की को खुला रख सकते हैं, ttyजब पर्यावरण चर में वहां से चलाए जा रहे आउटपुट को बचा सकते हैं , और उस मान का उपयोग गंतव्य के guiआउटपुट के रूप में कर सकते हैं । इस तरह से सभी लॉग को एक अलग लॉग विंडो में भेजा जाएगा, जिसे आप पसंद करने के बाद स्क्रॉल कर सकते हैं।

मैंने एक बार इस बारे में एक उत्तर लिखा था कि bashयदि आप रुचि रखते हैं तो इतिहास के साथ एक समान कैसे किया जा सकता है ।


1
मेरा सुझाव है कि आप अपनी टिप्पणी को निकाल दें echo $?क्योंकि यह बेकार की जानकारी को जोड़ता है और यह एक बग पर आधारित है, जिसे मैंने अभी-अभी यहाँ रिपोर्ट किया है: lists.gnu.org/archive/html/bug-bash/2014- 08 / msg00081.html और डेबियन बीटीएस में: bugs.debian.org/cgi-bin/bugreport.cgi?bug=758969
vinc17

@ vinc17 yup - मुझे लगता है कि मैंने ऐसा किया होगा, जो कि अजीब है - क्योंकि मैं उस शेल का उपयोग कभी नहीं करता। लगता है मैं सिर्फ इस जवाब के लिए।
मोकेसर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.