किसी त्रुटि का सामना करने पर मैं एक बैच फ़ाइल कैसे समाप्त करूं?


290

मेरे पास एक बैच फ़ाइल है जो एक ही निष्पादन योग्य को अलग-अलग मापदंडों के साथ बुला रही है। यदि किसी एक कॉल में किसी भी स्तर का त्रुटि कोड दिया जाता है, तो मैं इसे तुरंत कैसे समाप्त कर सकता हूं?

मूल रूप से, मैं MSBuild के बराबर चाहता हूँ ContinueOnError=false


2
क्या कमांड शेल आपकी स्क्रिप्ट चला रहा होगा? DOS / Win9x का कमशॉट या Win2k + का cmd.exe? चूंकि यह अंतर की दुनिया बनाता है, क्या आप कृपया अपने प्रश्न को संपादित करने में स्पष्ट कर सकते हैं?
मिहाई लिम्बोअन

जवाबों:


299

errorlevelएक ifकथन की जाँच करें , और फिर 0 के अलावा मानों के लिए exit /b( केवल संपूर्ण cmd.exe प्रक्रिया नहीं, b atch फ़ाइल से बाहर निकलें )।

same-executable-over-and-over.exe /with different "parameters"
if %errorlevel% neq 0 exit /b %errorlevel%

यदि आप चाहते हैं कि आपकी बैच फ़ाइल के बाहर त्रुटिपूर्ण मान का प्रसार हो

if %errorlevel% neq 0 exit /b %errorlevel%

लेकिन अगर यह अंदर है तो forयह थोड़ा मुश्किल हो जाता है। आपको कुछ और की आवश्यकता होगी जैसे:

setlocal enabledelayedexpansion
for %%f in (C:\Windows\*) do (
    same-executable-over-and-over.exe /with different "parameters"
    if !errorlevel! neq 0 exit /b !errorlevel!
)

संपादित करें: आपको प्रत्येक कमांड के बाद त्रुटि की जांच करनी होगी। Cmd.exe / command.com बैच में निर्माण पर कोई वैश्विक "त्रुटि गोटो" प्रकार नहीं है। मैंने अपना कोड CodeMonkey के अनुसार भी अपडेट किया है , हालांकि मैंने XP या Vista पर अपने किसी भी बैच-हैकिंग में एक नकारात्मक त्रुटि का सामना नहीं किया है।


11
क्या संपूर्ण फ़ाइल के लिए एक बार इसे स्टेट करने का कोई तरीका है? "त्रुटि गोटो पर" या ऐसा ही कुछ?
जोश कोड्रॉफ़

3
नकारात्मक त्रुटि की जाँच के लिए +1। नकारात्मक परिणाम के कारण एक स्क्रिप्ट चुपचाप विफल रही।
devstuff

1
सावधान: सक्षम किया गया एक्सपेरिमेंटल क्रिटिकल है और यदि आवश्यक है तो किसी अन्य / या किसी अन्य ब्लॉक के लिए आवश्यक है
MarcH

1
@ सिस्टम-पीएयूएस पहले दो 'अगर' दिखाया गया है तो क्या कोई अंतर है?
सरल

1
विलंबित विस्तार सक्षम / अक्षम या कमांड एक्सटेंशन (के लिए आवश्यक neq) सक्षम / अक्षम if not errorlevel 1 exit /Bसमर्थन आलेख में Microsoft द्वारा बताए गए आदेश पुनर्निर्देशन ऑपरेटरों का उपयोग करके और if /?एक cmd विंडो में चलाने में मदद आउटपुट पर कोई फर्क नहीं पड़ता । वर्तमान त्रुटिवश (निकास कोड) बैच फ़ाइल के प्रसंस्करण से बाहर निकलने पर रखा जाता है exit /B। नोट: exitपैरामीटर के /Bलिए सक्षम कमांड एक्सटेंशन की आवश्यकता होती है, देखें GOTO कहां है: EOF पर लौटें?
मोफी

252

|| goto :labelप्रत्येक पंक्ति में जोड़ें , और फिर एक परिभाषित करें :label

उदाहरण के लिए, .cmd फ़ाइल बनाएँ:

@echo off

echo Starting very complicated batch file...
ping -invalid-arg || goto :error
echo OH noes, this shouldn't have succeeded.
goto :EOF

:error
echo Failed with error #%errorlevel%.
exit /b %errorlevel%

बैच फ़ाइल उप-पाठ से बाहर निकलने के बारे में भी देखें ।


4
अधिकांश शेल स्क्रिप्टिंग भाषाओं में यह एक बहुत ही सामान्य मुहावरा है, और यह अच्छी तरह से पढ़ता है: "ऐसा करो, या अगर यह विफल हो जाता है .."
Fowl

3
मैं लाइन नंबर का मैन्युअल ट्रैक रखने के लिए एक SET का उपयोग करता हूं:command || (SET ErrorLine=102 && goto :error)
SandRock

1
@MarcelValdezOrozco मुझे लगता है कि यह वही है जो ||पहली बार में बनाया गया था। हो सकता है कि विशेष रूप से गोटो न हो, लेकिन "प्रयास करें, यह त्रुटि पर करें" जैसा कि फाउल ने उल्लेख किया है। मेरा सवाल यह है कि यह सभी गैर-शून्य निकास कोड के लिए काम करता है? केवल सकारात्मक?
jpmc26

3
@ jpmc26 यह करता है, इसे अपने आप को साबित करें - cmd /k exit -1 && echo success || echo fail- प्रिंट विफल।
फोजल

2
तुम भी कुछ के साथ लेबल से बच सकते हैं जैसेcommand || exit /b %errorlevel%
जोहान्स ब्रोडवॉल

95

सबसे छोटा:

command || exit /b

यदि आपको आवश्यकता है, तो आप बाहर निकलने का कोड सेट कर सकते हैं:

command || exit /b 666

और आप लॉग इन भी कर सकते हैं:

command || echo ERROR && exit /b

4
क्या एग्जिट / बी ऑप्सन से मूल फेलिंग एग्जिट कोड वापस आ जाता है?
फ्रैंक श्वेतेरमैन

5
@FrankSchwieterman, हां, %ERRORLEVEL%जब आप कॉल करते हैं exit /b, तो अछूता रहता है , इसलिए त्रुटि कोड अग्रेषित किया जाता है
बेनोइट ब्लैंचॉन

24

एक मामूली अद्यतन, आपको "यदि त्रुटि 1" के लिए चेक को निम्नलिखित में बदलना चाहिए ...

IF %ERRORLEVEL% NEQ 0 

ऐसा इसलिए है क्योंकि XP ​​पर आप त्रुटियों के रूप में नकारात्मक संख्या प्राप्त कर सकते हैं। 0 = कोई समस्या नहीं, कुछ और समस्या है।

और ध्यान रखें कि डॉस "IF ERRORLEVEL" परीक्षणों को संभालता है। यह सच है अगर आप जिस नंबर के लिए जाँच कर रहे हैं, वह संख्या या उससे अधिक है, तो यदि आप विशिष्ट त्रुटि संख्याओं की तलाश कर रहे हैं, तो आपको 255 से शुरू करने और नीचे काम करने की आवश्यकता है।


1
Windows मानक आंतरिक और बाह्य कमांड में से कोई भी नकारात्मक मान के साथ कभी भी बाहर नहीं निकलता है। माइक्रोसॉफ्ट किसी भी कार्यक्रम लेखक के बारे में MSDN लेख पर उदाहरण के लिए, एक नकारात्मक मूल्य के साथ बाहर निकलने के लिए चेतावनी दी है Environment.ExitCode संपत्ति । वास्तव में यह हमेशा पता लगाना चाहिए कि सफलता के आवेदन पर कौन सा एग्जिट कोड इस्तेमाल किया जाता है और कौन-कौन सी विभिन्न त्रुटियों पर, एचटीएमएल हेल्प वर्कशॉप त्रुटि को सफलतापूर्वक देखने के बाद संकलित करता है। उपयोगकर्ता की अपेक्षाओं पर नकारात्मक एमएस उदाहरण के लिए .mm फ़ाइल
मोफी

17

यहां BASH और Windows CMD के लिए एक पॉलीग्लॉट प्रोग्राम है जो कई कमांड चलाता है और उनमें से कोई भी विफल होने पर बाहर निकलता है:

#!/bin/bash 2> nul

:; set -o errexit
:; function goto() { return $?; }

command 1 || goto :error

command 2 || goto :error

command 3 || goto :error

:; exit 0
exit /b 0

:error
exit /b %errorlevel%

मैंने कई प्लेटफ़ॉर्म निरंतर एकीकरण स्क्रिप्ट के लिए अतीत में इस प्रकार की चीज़ का उपयोग किया है ।


10

मैं आदेश के OR रूप को पसंद करता हूं, क्योंकि मैं उन्हें सबसे अधिक पठनीय लगता हूं (जैसा कि प्रत्येक आदेश के बाद होने पर विरोध किया जाता है)। हालांकि, ऐसा करने की भोली तरह, command || exit /b %ERRORLEVEL%है गलत

ऐसा इसलिए होता है क्योंकि जब कोई लाइन पहली बार पढ़ी जाती है, तो वे एक्सपैरीबल वैरिएबल का उपयोग करती हैं, बजाय इसके कि वे कब उपयोग किए जा रहे हैं। इसका मतलब यह है कि यदि commandऊपर की लाइन में विफल रहता है, तो बैच फ़ाइल ठीक से बाहर निकल जाती है, लेकिन यह रिटर्न कोड 0 से बाहर निकलता है, क्योंकि %ERRORLEVEL%लाइन के शुरू में यही था। जाहिर है, यह हमारी स्क्रिप्ट में अवांछनीय है, इसलिए हमें विलंबित विस्तार को सक्षम करना होगा , जैसे:

SETLOCAL EnableDelayedExpansion

command-1 || exit /b !ERRORLEVEL!
command-2 || exit /b !ERRORLEVEL!
command-3 || exit /b !ERRORLEVEL!
command-4 || exit /b !ERRORLEVEL!

यह स्निपेट 1-4 आदेशों को निष्पादित करेगा, और यदि उनमें से कोई भी विफल रहता है, तो यह उसी निकास कोड के साथ बाहर निकलेगा जैसा कि विफल कमांड ने किया था।


1

हम हमेशा ERRORLEVEL पर निर्भर नहीं रह सकते हैं, क्योंकि कई बार बाहरी प्रोग्राम या बैच स्क्रिप्ट एक्ज़िट कोड नहीं देते हैं।

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

IF EXIST %outfile% (DEL /F %outfile%)
CALL some_script.bat -o %outfile%
IF NOT EXIST %outfile%  (ECHO ERROR & EXIT /b)

और अगर प्रोग्राम कुछ कंसोल के लिए आउटपुट करता है, तो हम इसे भी जांच सकते हैं।

some_program.exe 2>&1 | FIND "error message here" && (ECHO ERROR & EXIT /b)
some_program.exe 2>&1 | FIND "Done processing." || (ECHO ERROR & EXIT /b)

1

कोई फर्क नहीं पड़ता कि मैं कैसे की कोशिश की, त्रुटि हमेशा 0 रहता है जब भी msbuild विफल रहा। इसलिए मैंने अपना वर्कअराउंड बनाया:

प्रोजेक्ट बनाएँ और लॉग को बिल्ड.log में सहेजें

SET Build_Opt=/flp:summary;logfile=Build.log;append=true

msbuild "myproj.csproj" /t:rebuild /p:Configuration=release /fl %Build_Opt%

बिल्ड लॉग में "0 त्रुटि" स्ट्रिंग की खोज करें, परिणाम को var पर सेट करें

FOR /F "tokens=* USEBACKQ" %%F IN (`find /c /i "0 Error" Build.log`) DO (
    SET var=%%F
)
echo %var%

अंतिम वर्ण प्राप्त करें, जो इंगित करता है कि खोज स्ट्रिंग में कितनी पंक्तियाँ हैं

set result=%var:~-1%

echo "%result%"

यदि स्ट्रिंग नहीं मिली, तो त्रुटि> 0, बिल्ड विफल

if "%result%"=="0" ( echo "build failed" )

उस समाधान को मेकफ्लैश के पोस्ट से प्रेरित किया गया था कि कैसे बैच फ़ाइल में एक चर के रूप में कमांड आउटपुट सेट करें

और https://ss64.com/nt/syntax-substring.html


1
केवल दस की तुलना में मायने रखता है के लिए काम करता है। बेहतर; for /f %%F in ('type build.log^|find /c /i "0 Error") do set result=%%F। नोट: find "0 Error"भी मिलेगा 10 Errors
Stephan

-2
@echo off

set startbuild=%TIME%

C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe c:\link.xml /flp1:logfile=c:\link\errors.log;errorsonly /flp2:logfile=c:\link\warnings.log;warningsonly || goto :error

copy c:\app_offline.htm "\\lawpccnweb01\d$\websites\OperationsLinkWeb\app_offline.htm"

del \\lawpccnweb01\d$\websites\OperationsLinkWeb\bin\ /Q

echo Start Copy: %TIME%

set copystart=%TIME%

xcopy C:\link\_PublishedWebsites\OperationsLink \\lawpccnweb01\d$\websites\OperationsLinkWeb\ /s /y /d

del \\lawpccnweb01\d$\websites\OperationsLinkWeb\app_offline.htm

echo Started Build: %startbuild%
echo Started Copy: %copystart%
echo Finished Copy: %TIME%

c:\link\warnings.log

:error

c:\link\errors.log

4
कृपया अपने उत्तर में और जानकारी जोड़ें। बस कोड का एक ब्लॉक बहुत मददगार नहीं है।
PoweredByOrange

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