कैसे बैश शेल स्क्रिप्ट में कमांड गूंजते हैं, लेकिन उन्हें निष्पादित नहीं करते हैं?


11

क्या कमांडों की गूंज के साथ एक शेल स्क्रिप्ट चलाने का एक तरीका है, लेकिन वास्तव में उन्हें निष्पादित कर रहा है?

मान लीजिए कि मेरे पास एक फाइल हटाने वाली स्क्रिप्ट है जिसका नाम एक चर में संग्रहीत है:

#!/bin/bash
set -v
FN="filename"
rm -f ${FN}

जोड़ने set -vसे पहले निम्नलिखित आदेशों की गूंज होगी:

$ ./scr.sh
FN="filename"
rm -f ${FN}

अब, मैं इस स्क्रिप्ट के प्रवाह को देखना चाहता हूं w / o वास्तव में फ़ाइल को हटा रहा है। IOW, मैं बाहरी वातावरण और फाइल सिस्टम पर किसी भी प्रभाव को रोकना चाहता हूं। क्या यह संभव है?

मैं एक echoकमांड के साथ सभी कमांड लपेट सकता था, लेकिन यह एक लंबी स्क्रिप्ट के लिए थकाऊ है।


मैं बैश-स्क्रिप्टिंग विशेषज्ञ नहीं हूं, लेकिन अगर मैं इसे किसी अन्य प्रोग्रामिंग भाषा के साथ लिखूंगा, तो मैं सभी कमांड को एक सरणी में संग्रहीत करूंगा। इस तरह से लूप के माध्यम से आसान होना चाहिए और या तो कमांड निष्पादित करें या प्रिंट आउट करें।
ह्यूगो डेर हुनग्रीगे

जवाबों:


8

स्क्रिप्ट के माध्यम से कदम रखने का कोई तरीका नहीं है यह देखने के लिए कि वास्तव में ऐसा किए बिना यह कैसे निष्पादित होगा। आपके उदाहरण में, कोई ifकथन या लूप नहीं हैं। लेकिन वास्तविक स्क्रिप्ट में, अक्सर बहुत सारे सशर्त बयान होते हैं। कौन सी शाखा मिलेगी, यह अक्सर इस बात पर निर्भर करेगा कि पिछले कमांड को चलाने के दौरान क्या हुआ था। यदि यह कमांड नहीं चलाता है, तो शेल के लिए यह पता लगाने का कोई तरीका नहीं है कि यह किस आउटपुट से उत्पन्न होगा या रिटर्न कोड क्या होगा, जो कि अगली सशर्त शाखा या असाइनमेंट स्टेटमेंट पर निर्भर हो सकता है।

यदि बिंदु यह है कि आप किसी स्क्रिप्ट की जांच करना चाहते हैं और यह जानते हैं कि इसे चलाने से पहले आप क्या करते हैं, तो यह एक बुरा विचार नहीं है। लेकिन वास्तविक, सबसे अच्छा तरीका है के बारे में वह यह है कि बस के साथ फ़ाइल ब्राउज़ कर ऐसा करने के लिए lessया viया कुछ इसी तरह।

जोड़ा गया

यदि आप एक स्क्रिप्ट विकसित कर रहे हैं और आप पहली बार इसके माध्यम से कदम रखना चाहते हैं, तो तर्क का परीक्षण करना लेकिन वास्तव में कोई नुकसान नहीं करना है अगर आपको बग मिला है, तो मैं अक्सर उपयोग करने में सक्षम समाधान केवल संशोधित करना है ऐसे बयान जो echoसामने वाले पर चिपक कर कोई भी नुकसान पहुंचा सकते हैं ।

यह अक्सर विशिष्ट वास्तविक जीवन की लिपियों में काम करता है क्योंकि (ए) उन वस्तुओं की सूची उत्पन्न करता है जिन्हें आप अधिक मात्रा में बदलेंगे या जिस मूल्य पर आप एक चर सेट करेंगे, वह अक्सर फाइल सिस्टम को बदले बिना उत्पन्न किया जा सकता है और (बी) यह आमतौर पर पर्याप्त होता है यह मान लें कि यदि आपने कमांड चलाया, तो यह सफल होगा।


धन्यवाद। यह एक आश्चर्य की बात है अगर वहाँ एक तरीका है, बिल्कुल कारण आप उल्लेख किया है, लेकिन मैं इसे वैसे भी एक कोशिश देने का फैसला किया। इसका कारण यह है कि मैं एक स्क्रिप्ट विकसित कर रहा हूं जो एक नेटवर्क में कई मशीनों में फ़ाइलों को स्थानांतरित करता है और दूरस्थ मेजबानों पर कुछ क्रियाएं करता है। मैं वास्तव में फाइल सिस्टम में बदलाव करने से पहले स्क्रिप्ट का प्रवाह देखना चाहता हूं। यह फ़ाइल त्रुटियों को ठीक करने के लिए सभी दूरस्थ मशीनों पर जाने के लिए बस थकाऊ होगा ...
ysap

1
एक अतिरिक्त: स्क्रिप्ट के माध्यम से कदम रखने के लिए, आप उस स्क्रिप्ट को शुरू कर सकते हैं trap read debugजिसके साथ हर निष्पादित लाइन के बाद एक रीडिंग होगी, और फिर आप इसे धीरे-धीरे प्रवेश के साथ आगे बढ़ा सकते हैं (यह उपयोगी है यदि आपके पास वास्तव में लंबी स्क्रिप्ट है और परीक्षण करना चाहते हैं यह पहली बार)।
netigger

8

मुझे लगता है कि आपको प्रतिध्वनि होने वाली है - हालांकि यदि आप कमांड को एक चर में रखते हैं तो आप इसे चालू और बंद कर सकते हैं। इसके अलावा, कमांड एक फ़ंक्शन हो सकता है और जितना आप चाहते हैं उतना परिष्कृत हो सकता है।

#!/bin/bash
echo 'Debug'
  D=echo
  :>| testy
  ls -l testy
  $D rm -f testy
  ls -l testy
echo $'\n\nLive'
  D=
  :>| testy
  ls -l testy
  $D rm -f testy
  ls -l testy

!$ > ./conditional.sh
Debug
-rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy
rm -f testy
-rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy

Live -rw-rw-r-- 1 nobody nobody 0 2013-01-18 15:28 testy ls: cannot access testy: No such file or directory


मुझे इको / न-इको कमांड में उद्धरणों की आवश्यकता थी, और फिर D=evalलाइव भाग में उपयोग करना था । लेकिन अच्छा जवाब!
जैस्पर

5

आप बैश के लिए -x विकल्प का उपयोग करके प्रवाह का पता लगाते हैं, लेकिन यह अभी भी कमांड को निष्पादित करेगा।

आप जो सबसे अच्छा कर सकते हैं, वह है सिर्फ इको लगाना या उस कमांड को कमेंट करना, जिसमें आरएम जैसे बाहरी प्रभाव हों। कम से कम आपको हर पंक्ति नहीं बदलनी होगी।


धन्यवाद। मैंने अपने प्रश्न में उस विकल्प का उल्लेख किया है, लेकिन यह वास्तव में मेरी समस्या का समाधान नहीं करता है।
19

क्षमा करें, मैंने सोचा था कि आप प्रत्येक पंक्ति को प्रतिध्वनित कर रहे थे, -x इसे कुछ आदेशों तक कम कर देगा और आपको मूल्यांकन दिखाएगा।
पार्किड्र

4

मुझे ड्राई रन के लिए कोई विशेष विधि नहीं पता है, लेकिन हम अज्ञात स्क्रिप्ट को समझने के लिए कुछ सावधानियों का उपयोग कर सकते हैं।

  1. अपने डिबग स्क्रिप्ट को चलाने के लिए किसी क्रोकेट वातावरण का उपयोग करें । यह एक सैंडबॉक्स के रूप में कार्य करेगा और मुख्य सिस्टम फ़ाइलों को हटाने / संशोधित करने के खिलाफ सुरक्षा प्रदान करेगा।
  2. वाक्यविन्यास जाँच केbash -n <script> लिए उपयोग करें । ग्नू बाश मैनुअल से https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html

-n Read commands but do not execute them; this may be used to check a script for syntax errors. This option is ignored by interactive shells.

  1. कम से कम एक बार स्क्रिप्ट पढ़ें। आप डिबग के लिए इको स्टेटमेंट का उपयोग कर सकते हैं जैसा कि user191016 द्वारा उत्तर में दिया गया है
    • संदिग्ध या खतरे प्रवण कोड के लिए देखें।
    • जैसे rm से संबंधित, कमांड / देव / sda आदि को प्रभावित करने वाले
  2. हमेशा स्क्रिप्ट को सामान्य उपयोगकर्ता के रूप में चलाने की कोशिश करें, अज्ञात स्क्रिप्ट को रूट के रूप में चलाने से बचें।
  3. आप अपनी स्क्रिप्ट के प्रारंभ में इंटरैक्टिव के रूप में फ़ाइलों को संशोधित करने के लिए उपनाम को परिभाषित कर सकते हैं। उदाहरण के alias rm="rm -i" alias cp="cp -i" alias mv="mv -i" लिए, स्ट्रीम जैसे संपादकों के लिए- sed -i(मैं जगह में फ़ाइल को संशोधित करता है -इसे यह sed के लिए एक सूखा रन करता है, विवरण के लिए मैन पेज की जांच करें) पूरा कमांड कॉपी कर सकते हैं और चला सकते हैं। वास्तविक कमांड के ठीक पहले यह स्क्रीन पर आउटपुट दिखाएगा और फिर उपयोगकर्ता इनपुट जारी रखने के लिए प्रतीक्षा करने के लिए कमांड का उपयोग करेगा। उदाहरण के sed -i <pattern> साथ इसे बदलें sed <pattern> read -p "Press any key..." sed -i <pattern>

यह भी सुझाव है कि आपके सिस्टम में बैकअप बिंदुओं को रखने के लिए हमेशा सुझाव दिया जाता है ताकि आपातकालीन डेटा को बहाल किया जा सके।


3

करो set –n, या nअपने मौजूदा set –vआदेश को आगे बढ़ाओ । लेकिन चूंकि यह शेल किसी भी कमांड का मूल्यांकन नहीं करने का कारण बनता है, यहां तक ​​कि ifया नहीं while, आपको परिचालन प्रवाह का एक अच्छा दृश्य भी नहीं मिल सकता है।


धन्यवाद। यह एक अच्छी शुरुआत है, लेकिन जैसा कि आपने उल्लेख किया है, यह मुझे वास्तविक प्रवाह को देखने की अनुमति नहीं देता है - जहां मेरी वास्तविक स्क्रिप्ट में मुझे दूरस्थ मेजबान की सूची में एक लूप मिला है।
यसप १६'१३

3

यहाँ एक छोटा सा निर्माण है जिसका मैं उपयोग करना चाहता हूँ:

#!/bin/sh

verbose=false
really=true

# parse arguments
while [ $# -ge 1 ]
do
  case "$1" in
    -v) verbose=true ;;
    -n) really=false; verbose=true ;;
  esac
  shift
done

doCmd() {
  if $verbose; then echo "$@"; fi
  if $really; then "$@"; fi
}

doCmd make foo
doCmd rm -rf /tmp/installdir
doCmd mkdir /tmp/installdir
doCmd whatever
doCmd blah blah

2

यदि आप संशोधनों को होने से रोकना चाहते हैं, तो आप स्क्रिप्ट को बिना विशेषाधिकार के उपयोगकर्ता के रूप में चला सकते हैं:

sudo -u nobody ./scr.sh

आपके उदाहरण में, यह FN="filename"हमेशा की तरह निष्पादित होगा । हालांकि यह तकनीकी rm -f ${FN}रूप से कमांड को निष्पादित करता है , लेकिन कुछ भी नहीं होगा यदि किसी के पास फ़ाइल को हटाने के लिए आवश्यक अनुमति नहीं है।

बेशक, यह सशर्त वर्कफ़्लो के साथ समस्याएं पैदा करेगा। तथ्य यह है कि rmकमांड विफल हो गया स्क्रिप्ट के आगे के हिस्सों को प्रभावित कर सकता है।


चीजें जो हम कभी नहीं समझ पाएंगे: क्यों जड़ को किसी के रूप में चलाने की आवश्यकता है ...
mjohnsonengr

उपयोगकर्ता "कोई नहीं" ओएस के लिए स्थानिक नहीं है, लेकिन आप sudoers फ़ाइल में एक प्रविष्टि जोड़ सकते हैं जो "कोई नहीं" के लिए पासवर्ड रहित sudo की अनुमति देता है।
डेनिस

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