बिना इसे चलाए मैं एक बैश लिपि की वाक्य रचना कैसे जाँच सकता हूँ?


267

क्या इसे निष्पादित किए बिना बैश स्क्रिप्ट सिंटैक्स की जांच करना संभव है?

पर्ल का उपयोग करके, मैं चला सकता हूं perl -c 'script name'। क्या बैश स्क्रिप्ट के लिए कोई समकक्ष आदेश है?


जवाबों:


380
bash -n scriptname

शायद एक स्पष्ट चेतावनी: यह सिंटैक्स को मान्य करता है लेकिन यह जांच नहीं करेगा कि क्या आपकी बैश स्क्रिप्ट एक कमांड को निष्पादित करने का प्रयास करती है जो आपके रास्ते में नहीं है, जैसे ech helloकि echo hello


9
बैश के मेनपेज में, "SHELL BUILTIN COMMANDS / set" के तहत, -n को प्रलेखित किया जाता है, और मैनपेज की शुरुआत के अनुसार, बैश सभी एकल-वर्ण विकल्पों की व्याख्या setकरता है जो करता है।
१०:५५

24
(मेरे लिए) गैर स्पष्ट चेतावनी में जोड़ने के लिए, यह भी एक लापता अंतरिक्ष की वजह से एक त्रुटि पकड़ नहीं होगा if ["$var" == "string" ]बजायif [ "$var" == "string" ]
Brynjar

11
@Brynjar ऐसा इसलिए है क्योंकि यह सिर्फ वाक्यविन्यास जाँच है। ओपन ब्रैकेट सिंटैक्स नहीं है, जो चलाने के लिए फ़ंक्शन का नाम है। type ["[एक शेल बिल्डिन है"। यह अंततः testकार्यक्रम को दर्शाता है , लेकिन यह एक समापन ब्रैकेट की भी उम्मीद करता है। तो यह ऐसा है if test"$var", जो ऐसा नहीं है कि लेखक का क्या मतलब है, लेकिन वाक्यगत रूप से मान्य है (कहते हैं कि $ var का मूल्य "a" है, तो हम "bash: testa: command not found") देखेंगे। बिंदु यह है कि वाक्यात्मक रूप से, कोई लापता स्थान नहीं है।
जोशुआ चीक

2
@JoshuaCheek: [यदि खाली स्ट्रिंग$var का विस्तार करने के लिए होता है, तो केवल इस मामले में निर्मित किया जाता है । यदि कोई गैर-रिक्त स्ट्रिंग में फैलता है , तो उस स्ट्रिंग के साथ सम्‍मिलित किया जाता है और बैश द्वारा कमांड नाम ( फ़ंक्शन नाम नहीं ) के रूप में व्याख्या की जाती है , और, हाँ, यह वाक्यात्मक रूप से मान्य है, लेकिन, जैसा कि आप कहते हैं, स्पष्ट रूप से इरादा नहीं है। यदि आप इसके बजाय उपयोग करते हैं , भले ही एक शेल कीवर्ड (एक बिल्डिन के बजाय) है, तो आपको एक ही परिणाम मिलेगा, क्योंकि अनपेक्षित स्ट्रिंग कॉन्सेप्टन अभी भी कीवर्ड की मान्यता को ओवरराइड करता है। $var[[[[[[
mklement0

2
@JoshuaCheek: बैश अभी भी है वाक्य रचना यहाँ -checking: यह जांचता है सरल-आदेश मंगलाचरण वाक्य रचना: ["$var"है वाक्य रचना एक वैध कमांड नाम अभिव्यक्ति; इसी तरह, टोकन ==और "$string"मान्य कमांड तर्क हैं । (आम तौर पर, निर्मित [साथ पार्स किया गया है आदेश वाक्य रचना, जबकि [[- एक खोल के रूप में कीवर्ड - अलग ढंग से पार्स किया गया है।) खोल निर्मित [करता नहीं सौंपने "के testकार्यक्रम" (बाह्य उपयोगिता): bash, dash, ksh, zshसभी builtin दोनों संस्करणों [औरtest, और वे अपने बाहरी-उपयोगिता समकक्षों को नहीं बुलाते हैं।
mklement0

127

समय सब कुछ बदल देता है। यहां एक वेब साइट है जो शेल स्क्रिप्ट के लिए ऑनलाइन सिंटैक्स चेकिंग प्रदान करती है।

मैंने पाया कि यह सामान्य त्रुटियों का पता लगाने में बहुत शक्तिशाली है।

यहां छवि विवरण दर्ज करें

शेलचेक के बारे में

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

Haskell source कोड GitHub पर उपलब्ध है!


5
महान टिप; पर OSX तुम अब भी shellcheck.net CLI स्थापित कर सकते हैं, shellcheck, के माध्यम से Homebrew : brew install shellcheck
mklement0

3
डेबियन और दोस्तों पर भी:apt-get install shellcheck
वह अन्य लड़का

उबंटू भरोसेमंद के लिए इस पैकेज से स्थापित होना चाहिए trusty-backports
पीटरिनो

जैसा कि ऊपर उल्लेख किया गया है, भरोसेमंद निर्भरता की आवश्यकता है, और इसे नीचे के रूप में ubuntu 14.04 में स्थापित कर सकते हैं: sudo apt-get -f install, फिर: sudo sudo apt-get install shellcheck
zhihong

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

38

मैं कुछ अतिरिक्त जाँच करने के लिए प्रत्येक बैश स्क्रिप्ट पर 'u' विकल्प को भी सक्षम करता हूँ:

set -u 

यह निम्नलिखित स्क्रिप्ट 'check_init.sh' की तरह, एकतरफा वैरिएबल के उपयोग की सूचना देगा।

#!/bin/sh
set -u
message=hello
echo $mesage

स्क्रिप्ट चलाना:

$ check_init.sh

निम्नलिखित की रिपोर्ट करेंगे:

./check_init.sh [४]: मेसेज: पैरामीटर सेट नहीं है।

टाइपो को पकड़ने के लिए बहुत उपयोगी है


4
मैं इन झंडों को हमेशा अपनी बैश लिपियों में सेट करता हूँ, अगर यह इनसे गुजरता है, तो "सेट -o एरेक्सिट" "सेट -ओ संज्ञा" "सेट -ओ पिपीफेल"
μολὼν.λα

+1 के लिए set -uयद्यपि यह वास्तव में प्रश्न का उत्तर नहीं देता है, क्योंकि आपको त्रुटि संदेश प्राप्त करने के लिए स्क्रिप्ट को चलाना होगा। bash -n check_init.shउस चेतावनी को भी नहीं दिखाता है
rubo77

23
sh  -n   script-name 

इसे चलाओ। यदि स्क्रिप्ट में कोई सिंटैक्स त्रुटियां हैं, तो यह वही त्रुटि संदेश देता है। यदि कोई त्रुटि नहीं है, तो यह बिना कोई संदेश दिए निकलता है। आप तुरंत जांच कर सकते हैं echo $?, जो वापस आ जाएगी0 बिना किसी गलती के सफल होने की पुष्टि ।

इसने मेरे लिए अच्छा काम किया। मैं लिनक्स ओएस, बैश शेल पर भागा।


1
हालांकि बैश सिंटैक्स चेक से संबंधित नहीं है - पूरी स्क्रिप्ट या स्क्रिप्ट के अनुभागों को डीबग करने के लिए सेट -x और सेट + x का उपयोग करना काफी उपयोगी है
गुरुग्राम

इसके लिए धन्यवाद पता नहीं था -n के बारे में पता नहीं था, लेकिन जो मैं चाहता था वह @GuruM> sh -x test.sh था क्योंकि यह स्क्रिप्ट के उत्पन्न आउटपुट को प्रदर्शित करता है
zzapper

1
हाँ। मैं यह उल्लेख करना भूल गया कि आप निम्न कार्य कर सकते हैं: 1) bash -x test.sh #this पूरी स्क्रिप्ट को 'डिबग मोड' 2) सेट + x में चलाता है; bash test.sh; सेट -x #set डिबग मोड स्क्रिप्ट चलाने से पहले / बाद में / बंद: स्क्रिप्ट में: a) #! / bin / bash -x #add 'debug mode' स्क्रिप्ट के शीर्ष पर b) सेट + x; कोड; set -x #add 'डिबग मोड' स्क्रिप्ट के किसी भी भाग के लिए
गुरुग्राम

sh -nशायद जांच नहीं करेगा कि स्क्रिप्ट मान्य बैश स्क्रिप्ट है। यह गलत नकारात्मक दे सकता है। shकुछ बॉर्न शेल वैरिएंट है जो आमतौर पर बैश नहीं होते हैं। उदाहरण के लिए उबंटू में लिनक्स realpath -e $(command -v sh)/ बिन / डैश देता है
jarno

4

मैं वास्तव में सभी bash स्क्रिप्ट को वर्तमान dir में सिंटैक्स त्रुटियों के लिए जाँचता हूँ, बिना findटूल का उपयोग किए उन्हें चलाने के बिना :

उदाहरण:

find . -name '*.sh' -exec bash -n {} \;

यदि आप इसे एकल फ़ाइल के लिए उपयोग करना चाहते हैं, तो फ़ाइल के नाम के साथ वाइल्डकार्ड को संपादित करें।


3

null कमांड [कोलोन] जब वेरिएबल के वैल्यू को देखने के लिए डिबगिंग भी उपयोगी है

set -x
for i in {1..10}; do
    let i=i+1
    : i=$i
done
set - 

यह पैरामीटर विस्तार का उपयोग करता है
mug896

यह काम करता है, क्योंकि set -xनिष्पादित होने से पहले हर पंक्ति को दिखाता है
rubo77

1

नहीं है BashSupport प्लगइन के लिए IntelliJ विचार जो चेक वाक्य रचना।


लेकिन यह काम नहीं करेगा अगर आपकी फाइलें .shबैश स्क्रिप्ट से जुड़े या अन्य एक्सटेंशन के साथ समाप्त नहीं होती हैं, जो कि अगर आप ईआरबी जैसे कुछ टेम्प्लेटिंग टूल का उपयोग करके स्क्रिप्ट उत्पन्न करते हैं (तब वे समाप्त होते हैं .erb)। यदि आप इसे तय करना चाहते हैं, तो कृपया youtrack.jetbrains.com/issue/IDEA-79574 पर वोट करें !
ग्रेग डबकी

1

यदि आपको एक चर में सभी फाइलों की वैधता एक निर्देशिका (git प्री-कमिट हुक, बिल्ड लिपि स्क्रिप्ट) की आवश्यकता है, तो आप "sh -n" या "bash -n" कमांड के stderr आउटपुट को पकड़ सकते हैं (अन्य देखें) उत्तर) एक चर में, और उसके आधार पर एक "अगर / और" है

bashErrLines=$(find bin/ -type f -name '*.sh' -exec sh -n {} \;  2>&1 > /dev/null)
  if [ "$bashErrLines" != "" ]; then 
   # at least one sh file in the bin dir has a syntax error
   echo $bashErrLines; 
   exit; 
  fi

अपनी आवश्यकताओं के आधार पर "बैश" के साथ "श" बदलें

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