Ssh के माध्यम से कमांड प्रतिस्थापन के मूल्यांकन पर गलत निकास स्थिति?


1

मेरे पास निम्नलिखित सरल शेल कमांड हैं जो मैं विफल होने की उम्मीद कर रहा हूं और यह मेरे स्थानीय पर करता है:

$ DIR=$(false) && echo ok || echo fail
fail
$ sh -c 'DIR=$(false) && echo ok || echo fail'
fail

लेकिन जब मैं ssh के माध्यम से इस कमांड को पास कर रहा हूं, तो यह अब अपेक्षा के अनुरूप काम नहीं करता है:

$ ssh user@host sh -c 'DIR=$(false) && echo ok || echo fail'
ok

इसलिए मुझे यकीन नहीं है कि समस्या कहां है। मैं पहले से ही apostrophe का उपयोग कर रहा हूं, बहुत जल्दी चर विस्तार से बचने के लिए ।

चर असाइनमेंट से लौटे एक्जिट कोड के आधार पर सही ढंग से काम करने के लिए कमांड का प्रतिस्थापन कैसे करें और कैसे करें?


एक और विसंगति मुझे निम्नलिखित उदाहरण से मिली है:

$ ssh user@host sh -c 'echo 1; echo 2;'

2

जो 1 और 2 दोनों को प्रिंट करने के बजाय केवल 2 को प्रिंट कर रहा है।

जवाबों:


2

मुझे लगता है कि समस्या यह है कि इसमें तीन गोले शामिल हैं:

  1. स्थानीय शेल जो sshकमांड को प्रोसेस करता है ;
  2. दूरस्थ शेल जो sshलक्ष्य होस्ट में कमांड को संसाधित करने के लिए कहता है;
  3. sh -cदूरस्थ कमांड द्वारा लागू अतिरिक्त शेल ।

उद्धरण दो काम करते हैं:

  • वे स्थानीय शेल (1) में किसी भी चर का मूल्यांकन करने वाले स्थानीय शेल को रोकते हैं;
  • वे सुनिश्चित करते हैं कि रिमोट के लिए एक ही पैरामीटर है sh -c

इस प्रकार ssh: चार मापदंडों देखता है user@host, sh, -cऔर आवश्यक आदेश। हालांकि, चौथे पैरामीटर का निर्माण करते समय उद्धरण छीन लिए जाते हैं और जब रिमोट शेल (2) अपने मापदंडों को प्राप्त करता है तो यह $(false)स्वयं की व्याख्या करता है, और पूरा कोड सब-कॉल (3) को कॉल करने से पहले अपने स्वयं के वातावरण में सेट किया जाता है।

अतिरिक्त शेल (3) इस प्रकार देखता है DIR= && echo ok || echo failऔर DIR=पूरी तरह से मान्य, त्रुटि रहित कमांड है, इसलिए okशाखा।

आप उसी प्रभाव को देख सकते हैं:

sh -c 'sh -c "DIR=$(false) && echo ok || echo not"'

या:

sh -c "sh -c 'DIR=$(false) && echo ok || echo not'"

दोनों मामलों में यह "ठीक से" काम करता है यदि आप \पहले डालते हैं $, क्योंकि यह दूसरे शेल को विस्तार से रोकता है $(false)। मैंने तंत्रों को स्पष्ट करने के लिए दोहरे उद्धरण चिह्नों का उपयोग किया - यदि आप चाहें तो वहाँ यातनापूर्ण है:

sh -c 'sh -c '\''DIR=$(false) && echo ok || echo not'\'

रिचर्ड का उदाहरण काम करता है, क्योंकि सभी विस्तार एकल रिमोट शेल में किया जाता है, और एक प्रारंभिक false;का बाद की कमांड पर कोई प्रभाव नहीं पड़ता है। उसके लिंक पर चर्चा किए गए विषय से इसका कोई लेना-देना नहीं है।


धन्यवाद, यह काम करता है। देखें: एकल उद्धरण वाले स्पष्टीकरण के भीतर एकल उद्धरण सहित एकल उद्धरणों में वर्णों को जोड़ना
kenorb

1
आपके संपादित पोस्ट में नया उदाहरण बिल्कुल वही समस्या है: उद्धरण खो जाते हैं और दूरस्थ शेल देखता है sh -c echo 1; echo 2। केवल पहले पैरामीटर echoका उपयोग किया जाता है sh -c, जो अतिरिक्त नई-लाइन ( 1एक अति सूक्ष्म पैरामीटर के रूप में अनदेखा किया गया है) की व्याख्या करता है; और अर्ध-उपनिवेश shकमांड का परिसीमन करता है , जिससे कि echo 2रिमोट शेल द्वारा निष्पादित किया जाता है, उप-शेल नहीं। क्योंकि कोई पैरामीटर विस्तार नहीं है, आप दोनों प्रकार के उद्धरण का उपयोग कर सकते हैं, ताकि ssh user@host sh -c "'echo 1; echo 2;'"आप अपेक्षा के अनुरूप काम करें।
AFH

1

यह उम्मीद के अनुसार काम करना चाहिए:

ssh user@host 'DIR=$(false) && echo ok || echo fail'

ऐसा प्रतीत होता है कि जब शेल पाइपलाइन में पहले बयान के ऊपर लागू किया जाता है तो यह काम नहीं करेगा यदि यह एक चर असाइनमेंट है।

अजीब तरह से, यह भी उम्मीद के मुताबिक काम करता है:

ssh user@host sh -c 'false; DIR=$(false) && echo ok || echo fail'

मैं 100% निश्चित नहीं हूं कि यहां क्या हो रहा है, लेकिन यह इस सवाल से संबंधित हो सकता है: https://unix.stackexchange.com/questions/126938/why-is-setting-a-variable-before-a-command- कानूनी-इन-बैश

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.