एक बैश स्क्रिप्ट कैसे बता सकती है कि इसे कैसे चलाया गया था?


11

मेरे पास एक बैश स्क्रिप्ट है जो मुझे छोटे बदलावों के बजाय एक जटिल आदेश को चलाने में मदद करने के लिए बनाने की कोशिश कर रहा था जो कि मुझे गूंज और पढ़ने के माध्यम से पूछेगा।

मुझे कमांड को निष्पादित करने के लिए टर्मिनल चलाने के लिए मजबूर करने के लिए समाधान मिला है, लेकिन मुझे इसमें कोई दिलचस्पी नहीं है। मैं ऐसा करना चाहूंगा, अगर मैं बाहर जाऊंगा और सिर्फ Nautilus में इसे दर्ज करूंगा (इसे रन सॉफ्टवेयर के साथ चलाऊंगा), तो यह बस एक सूचना को धीरे से कहेगा "कृपया इसे टर्मिनल से चलाएं।"

मैं ऐसा करने के लिए पॉपअप प्राप्त कर सकता हूं - जैसा कि मैं कमांड जानता हूं - लेकिन मुझे यह बताने के लिए बैश स्क्रिप्ट नहीं मिल सकती है कि क्या यह टर्मिनल के अंदर चलाया जा रहा है या नहीं, यह हमेशा ऐसा लगता है। क्या यह भी संभव है?

जवाबों:


10

व्यक्तिगत परीक्षा केman bash तहत :

-t fd  
    True if file descriptor fd is open and refers to a terminal.

मान लेना fd 1 मानक है, if [ -t 1 ]; thenआपके लिए काम करना चाहिए। उन्नत शैल स्क्रिप्टिंग गाइड दावा है कि -tइस तरह से इस्तेमाल किया विफल हो जाएगा ssh, और परीक्षण है कि (stdin का उपयोग कर, stdout नहीं) इसलिए किया जाना चाहिए:

if [[ -t 0 || -p /dev/stdin ]]

-pएक फ़ाइल मौजूद है और एक नामित पाइप है, तो परीक्षण। हालाँकि , मैं अनुभवात्मक रूप से यह नोट करूँगा कि यह मेरे लिए सही नहीं है: -p /dev/stdinदोनों सामान्य टर्मिनलों और ssh सत्रों के लिए विफल रहता है जबकि if [ -t 0 ](या -t 1) दोनों मामलों में काम करता है ( उन्नत शेल स्क्रिप्टिंग गाइड के उस सेक्शन में मुद्दों के बारे में नीचे दिए गए गाइल्स टिप्पणियां भी देखें )।


यदि प्राथमिक समस्या एक विशेष संदर्भ है, जिसमें आप स्क्रिप्ट को उस संदर्भ में उपयुक्त तरीके से व्यवहार करने के लिए कॉल करना चाहते हैं, तो आप इन सभी तकनीकीताओं को दरकिनार कर सकते हैं और एक आवरण और एक कस्टम चर का उपयोग करके अपने आप को कुछ उपद्रव से बचा सकते हैं:

!#/bin/bash

export SPECIAL_CONTEXT=1
/path/to/real/script.sh

इसे कॉल करें live_script.shया जो भी हो और इसके बजाय डबल क्लिक करें। आप निश्चित रूप से कमांड लाइन के तर्कों के साथ एक ही बात को पूरा कर सकते हैं, लेकिन एक जीयूआई फ़ाइल ब्राउज़र कार्य में बिंदु बनाने और क्लिक करने के लिए एक आवरण की आवश्यकता होगी।


5
यह सही उत्तर है - यह भी है कि कैसे POSIX कहता है कि एक शेल को पता लगाना चाहिए कि क्या यह इंटरएक्टिव है या नहीं।
mikeserv

2
@DanielAmaya - यदि आप इनपुट को पुनर्निर्देशित करते हैं तो स्क्रिप्ट को टर्मिनल पर नहीं चलाया जा रहा है। सवाल यह है कि कैसे पता लगाया जाए कि स्क्रिप्ट को टर्मिनल पर चलाया जा रहा है या नहीं।
mikeserv

2
आप के उपयोग के बारे में सुनिश्चित हैं ||भीतर [ … ]इस तरह? यदि आप उपयोग करते हैं [[ … ]]तो यह ठीक होगा, लेकिन आम तौर पर ||इसका उपयोग अलग-अलग आदेशों के लिए किया जाता है, और [ -t 0यह एक गलत आह्वान है [क्योंकि इसका अंतिम ]गायब है। आमतौर पर कोई कमांड -pनहीं है। मैं एक टर्मिनल के लिए परीक्षण से सहमत हूं; शायद ऐसा करने का तरीका है। यह सिर्फ़ वाक्य-विन्यास है जिसकी मुझे चिंता है।
जोनाथन लेफलर

1
@JonathanLeffler राइट; शेल सिंटैक्स त्रुटि उत्पन्न करनी चाहिए, क्योंकि शेल ऑपरेटर ||को आवश्यक अंतिम ]तर्क से पहले देखा जाता है [
१ner

3
उन्नत बैश-स्क्रिप्टिंग गाइड के उस खंड में कई त्रुटियां हैं। PS1यह बताने के लिए एक विश्वसनीय परीक्षण नहीं है कि क्या शेल इंटरैक्टिव है। "यदि एक स्क्रिप्ट को यह जांचने की आवश्यकता है कि क्या यह एक इंटरैक्टिव शेल में चल रहा है" भी भ्रामक है: यह होना चाहिए कि क्या कुछ कोड को परीक्षण करने की आवश्यकता है - एक स्क्रिप्ट आमतौर पर एक इंटरैक्टिव शेल में नहीं चल रही है (लेकिन यह हो सकता है, अगर यह खट्टा हो) । के लिए परीक्षण iमें $-परीक्षण करने के लिए सही तरीका है, तो खोल इंटरैक्टिव है। परीक्षण -t 0या -t 2यह बताने का सही तरीका है कि क्या स्क्रिप्ट टर्मिनल में चल रही है, जो कि इंटरैक्टिव होने से अलग है।
गिल्स एसओ- बुराई को रोकना '

0

शेल नेस्टिंग के स्तर का पता लगाने के लिए bash $ SHLVL वैरिएबल का उपयोग करें। डबल-क्लिक करके एक स्क्रिप्ट रन 'रॉ' में यह 1 होगा, एक टर्मिनल के भीतर चलने वाली स्क्रिप्ट में यह 2 होगा।

#!/bin/bash
if (( SHLVL < 2 )) ; then
    echo "Please run this from a terminal."
    read -p "Press <Enter> to close this window"
    exit 1
fi
# rest of script

0

हालांकि गोल्डीलॉक्स का उत्तर संभवतः विशिष्ट मामले में सही है, लेकिन ऐसा लगता है कि किनारे के मामले हैं। अपने स्वयं के मामले में, मेरे xserver को स्टार्ट करने के लिए कॉन्फ़िगर किया गया है tty1और यह कभी भी उस tty को नहीं छोड़ता है। अगर Xorg's stdoutTTY है तो ऐसा लगता है कि ग्राहकों के पास यह होगा कि TTY डिफ़ॉल्ट रूप से उनकी फ़ाइल डिस्क्रिप्टर से जुड़ा हो।

यहां बताया गया है कि मैंने अपना मुद्दा कैसे हल किया:

#!/bin/bash
isxclient=$( readlink /dev/fd/2 | grep -q 'tty' && [[ -n $DISPLAY ]] ; echo $? )
if [[ ! -t 2  || $isxclient == "0" ]]; then
        notify-send "Script wasn't started from an interactive shell"
else
        echo "Script was started from an interactive shell"
fi

मैंने यह देखने के लिए परीक्षण नहीं किया है कि क्या यह अधिक मानक X कॉन्फ़िगरेशन पर काम करता है, और मुझे यह भी बहुत संदेह है कि यह एकमात्र किनारे का मामला है। यदि किसी को अधिक आम तौर पर लागू होने वाला समाधान मिल जाता है, तो कृपया वापस आकर हमें बताएं।


-2

एक अन्य, बैश विकल्पों का उपयोग करके आंतरिक चर सेट करें $-

से .bashrc,

# If not running interactively, don't do anything
case $- in
    *i*) ;;
    *) return;;
esac

एक इंटरैक्टिव शेल एक टर्मिनल से जुड़ा जरूरी नहीं है। जबकि एक कि कनेक्शन के साथ शुरू स्वचालित रूप से इंटरैक्टिव शुरू कर दिया है, यह भी संभव है cmd | sh -i | cmd:।
15

इस कोड को एक स्क्रिप्ट में निष्पादित किया जा रहा है। यह एक टर्मिनल में चल रहा है, भले ही यह इंटरैक्टिव नहीं होगा।
गाइल्स का SO- बुराई पर रोक '20:
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.