यह निर्धारित करने का कोई मूर्खतापूर्ण तरीका नहीं है कि आपकी स्क्रिप्ट से STDIN, STDOUT, या STDERR को पाइप किया जा रहा है, मुख्यतः जैसे कार्यक्रमों के कारण ssh
।
चीजें जो "सामान्य रूप से" काम करती हैं
उदाहरण के लिए, निम्नलिखित बैश समाधान एक इंटरैक्टिव शेल में सही ढंग से काम करता है:
[[ -t 1 ]] && \
echo 'STDOUT is attached to TTY'
[[ -p /dev/stdout ]] && \
echo 'STDOUT is attached to a pipe'
[[ ! -t 1 && ! -p /dev/stdout ]] && \
echo 'STDOUT is attached to a redirection'
लेकिन वे हमेशा काम नहीं करते
हालांकि, जब इस कमांड को नॉन-टीटीवाई कमांड के रूप में निष्पादित किया जाता है ssh
, तो एसटीडी स्ट्रीम हमेशा ऐसा लगता है जैसे उन्हें पाइप किया जा रहा है। इसे प्रदर्शित करने के लिए, STDIN का उपयोग करना क्योंकि यह आसान है:
# CORRECT: Forced-tty mode correctly reports '1', which represents
# no pipe.
ssh -t localhost '[[ -p /dev/stdin ]]; echo ${?}'
# CORRECT: Issuing a piped command in forced-tty mode correctly
# reports '0', which represents a pipe.
ssh -t localhost 'echo hi | [[ -p /dev/stdin ]]; echo ${?}'
# INCORRECT: Non-tty mode reports '0', which represents a pipe,
# even though one isn't specified here.
ssh -T localhost '[[ -p /dev/stdin ]]; echo ${?}'
यह क्यों मायने रखता है
यह एक बहुत बड़ी बात है, क्योंकि इसका तात्पर्य है कि एक बैश स्क्रिप्ट के लिए यह बताने का कोई तरीका नहीं है कि एक गैर-टट्टी ssh
कमांड को पाइप किया जा रहा है या नहीं। ध्यान दें कि यह दुर्भाग्यपूर्ण व्यवहार तब पेश किया गया था जब हाल के संस्करणों ssh
ने गैर-टीटीवाई STDIO के लिए पाइप का उपयोग करना शुरू कर दिया था। पूर्व संस्करणों में सॉकेट्स का उपयोग किया जाता था, जिसे COULD का उपयोग करके बैश के भीतर से विभेदित किया जाता है [[ -S ]]
।
जब यह मायने रखता है
यह सीमा आम तौर पर समस्याओं का कारण बनती है जब आप एक बश स्क्रिप्ट लिखना चाहते हैं जिसमें संकलित उपयोगिता के समान व्यवहार होता है, जैसे cat
। उदाहरण के लिए, cat
विभिन्न इनपुट स्रोतों को एक साथ संभालने में निम्नलिखित लचीले व्यवहार की अनुमति देता है, और यह निर्धारित करने के लिए पर्याप्त स्मार्ट है कि क्या गैर-टीटीवाई या मजबूर-टीटीवाई ssh
का उपयोग किए बिना यह पाइप इनपुट प्राप्त कर रहा है:
ssh -t localhost 'echo piped | cat - <( echo substituted )'
ssh -T localhost 'echo piped | cat - <( echo substituted )'
आप केवल ऐसा कुछ कर सकते हैं यदि आप मज़बूती से निर्धारित कर सकते हैं कि पाइप शामिल हैं या नहीं। अन्यथा, एक कमांड निष्पादित करना जो STDIN को पढ़ता है जब पाइप या पुनर्निर्देशन से कोई इनपुट उपलब्ध नहीं होता है, तो स्क्रिप्ट को लटका दिया जाएगा और STDIN इनपुट की प्रतीक्षा की जाएगी।
अन्य चीजें जो काम नहीं करती हैं
इस समस्या को हल करने की कोशिश में, मैंने कई तकनीकों पर ध्यान दिया है जो इस समस्या को हल करने में विफल हैं, जिनमें शामिल हैं:
- SSH पर्यावरण चर की जांच करना
stat
/ dev / stdin फ़ाइल डिस्क्रिप्टर पर उपयोग करना
- के माध्यम से इंटरैक्टिव मोड की जांच
[[ "${-}" =~ 'i' ]]
tty
और के माध्यम से tty स्थिति की जांचtty -s
- के
ssh
माध्यम से स्थिति की जांच[[ "$(ps -o comm= -p $PPID)" =~ 'sshd' ]]
ध्यान दें कि यदि आप एक OS का उपयोग कर रहे हैं जो /proc
वर्चुअल फाइलसिस्टम का समर्थन करता है , तो आपको यह निर्धारित करने के लिए STDIO के प्रतीकात्मक लिंक के बाद किस्मत हो सकती है कि क्या पाइप का उपयोग किया जा रहा है या नहीं। हालांकि, /proc
एक क्रॉस-प्लेटफॉर्म नहीं है, POSIX- संगत समाधान।
मैं इस समस्या को हल करने में बेहद दिलचस्प हूं, इसलिए कृपया मुझे बताएं कि क्या आप किसी अन्य तकनीक के बारे में सोचते हैं जो काम कर सकती है, अधिमानतः पोसिक्स आधारित समाधान जो लिनक्स और बीएसडी दोनों पर काम करते हैं।