শেল স্ক্রিপ্টটি বাতিল করা যদি কোনও কমান্ড একটি শূন্য-মান না দেয়?


437

আমার কাছে বাশ শেল স্ক্রিপ্ট রয়েছে যা বেশ কয়েকটি কমান্ডের আবেদন করে। আমি শেল স্ক্রিপ্টটি স্বয়ংক্রিয়ভাবে 1 এর একটি রিটার্ন মান সহ প্রস্থান করতে চাইলে যদি কমান্ডগুলির মধ্যে কোনও শূন্য-না মান দেয়।

প্রতিটি কমান্ডের ফলাফল সুস্পষ্টভাবে পরীক্ষা না করেই কি এটি সম্ভব?

যেমন

dosomething1
if [[ $? -ne 0 ]]; then
    exit 1
fi

dosomething2
if [[ $? -ne 0 ]]; then
    exit 1
fi

8
উপরন্তু করতে set -e, এছাড়াও না set -u(অথবা set -eu)। -uআপনি যে কোনও অস্তিত্বের পরিবর্তনশীল অ্যাক্সেস করতে পারবেন এবং কোনও ডায়াগনস্টিকস ছাড়াই একটি ফাঁকা মান উত্পাদন করতে পারবেন এমন বোকামি, বাগ-লুকানোর আচরণের অবসান ঘটায়।
কাজ

উত্তর:


742

স্ক্রিপ্টের শুরুতে এটি যুক্ত করুন:

set -e

যদি কোনও সাধারণ কমান্ড ননজারো প্রস্থান মূল্য দিয়ে প্রস্থান করে তবে এটি শেলটি তত্ক্ষণাত্ প্রস্থান করবে। একটি সরল কমান্ড হ'ল কোনও আদেশ হ'ল যদি এর অংশ না হয় তবে, পরীক্ষা করা অবধি, অথবা একটি অ্যান্ড অ্যান্ড অ্যান্ড || তালিকা।

দেখুন ব্যাশ (1) man পৃষ্ঠা আরো বিস্তারিত জানার জন্য "তে সেট" অভ্যন্তরীণ কমান্ড করেন।

আমি ব্যক্তিগতভাবে প্রায় সমস্ত শেল স্ক্রিপ্ট "সেট-ই" দিয়ে শুরু করি। মাঝামাঝি কিছু ব্যর্থ হয় এবং স্ক্রিপ্টের বাকী অংশের জন্য অনুমানগুলি ভেঙে যখন একটি স্ক্রিপ্ট জেদীভাবে চালিয়ে যাওয়া সত্যিই বিরক্তিকর হয়।


36
এটি কার্যকর হবে তবে আমি "#! / Usr / bin / env বাশ" ব্যবহার করতে পছন্দ করি কারণ আমি প্রায়শই / বিন ছাড়া অন্য কোথাও বাশ চালাই run এবং "#! / Usr / bin / env bash -e" কাজ করে না। তদুপরি, আমি যখন ডিবাগিংয়ের জন্য ট্রেসিং চালু করতে চাই তখন "সেট-এক্সে" পড়ার জন্য সংশোধন করার জায়গা পেয়ে ভাল লাগে।
ভিল লৌড়িকারি

48
এছাড়াও, কোনও স্ক্রিপ্ট চলার সাথে সাথে শেবাং লাইনের পতাকাগুলি উপেক্ষা করা হবে bash script.sh
টম অ্যান্ডারসন

27
কেবলমাত্র একটি দ্রষ্টব্য: আপনি যদি ব্যাশ স্ক্রিপ্টের ভিতরে ফাংশনগুলি ঘোষণা করেন তবে যদি আপনি এই কার্যকারিতাটি প্রসারিত করতে চান তবে ফাংশনগুলির ফাংশন বডিটির অভ্যন্তরে সেট -e পুনরায় ঘোষিত হওয়া আবশ্যক।
জিন কিম

8
এছাড়াও, আপনি যদি আপনার স্ক্রিপ্টটি উত্স করেন তবে শেবাং লাইনটি অপ্রাসঙ্গিক হবে।

4
@ জিনকিম এটি বাশ ৩.২.৪৮-তে দেখা যাচ্ছে না। একটি স্ক্রিপ্ট ভিতরে নিম্নলিখিত চেষ্টা করুন: set -e; tf() { false; }; tf; echo 'still here'। এমনকি set -eশরীরের অভ্যন্তরে ছাড়াও tf()মৃত্যুদণ্ড বাতিল করা হয়। সম্ভবত আপনি বলতে চেয়েছিলেন যে সাবশেলগুলিset -e উত্তরাধিকার সূত্রে প্রাপ্ত নয় , যা সত্য।
mklement0

202

গৃহীত উত্তর যুক্ত করতে:

মনে রাখবেন যে set -eকখনও কখনও পর্যাপ্ত নয়, বিশেষত যদি আপনার পাইপ থাকে।

উদাহরণস্বরূপ, ধরুন আপনার কাছে এই স্ক্রিপ্ট রয়েছে

#!/bin/bash
set -e 
./configure  > configure.log
make

... যা প্রত্যাশার মতো কাজ করে: configureমৃত্যুদন্ড কার্যকর করতে একটি ত্রুটি ।

আগামীকাল আপনি আপাতদৃষ্টিতে তুচ্ছ পরিবর্তন করুন:

#!/bin/bash
set -e 
./configure  | tee configure.log
make

... এবং এখন এটি কাজ করে না। এটি এখানে ব্যাখ্যা করা হয়েছে , এবং একটি কার্যপ্রণালী (কেবলমাত্র ব্যাশ) সরবরাহ করা হয়েছে:

#! / বিন / ব্যাশ
সেট -ই 
পাইপফেল সেট করুন

./ কনফিগার | টি কনফিগার.লগ
করতে

1
pipefailসাথে যেতে হবে গুরুত্ব ব্যাখ্যা করার জন্য আপনাকে ধন্যবাদ set -o!
ম্যালকম 25

83

আপনার উদাহরণে যদি বিবৃতিগুলি অপ্রয়োজনীয় হয়। কেবল এটির মতো করুন:

dosomething1 || exit 1

আপনি যদি ভিল লৌরিকারীর পরামর্শ গ্রহণ করেন এবং ব্যবহার করেন set -eতবে কিছু আদেশের জন্য আপনার এটি ব্যবহারের প্রয়োজন হতে পারে:

dosomething || true

|| trueকরতে হবে কমান্ড পাইপলাইন একটি আছে trueফেরত মান এমনকি যদি কমান্ড ব্যর্থ যাতে -eবিকল্প স্ক্রিপ্ট হত্যা করা হবে না।


1
আমি এই পছন্দ। বিশেষত কারণ শীর্ষ উত্তরটি বাশকেন্দ্রিক (এটি zsh স্ক্রিপ্টিংয়ের ক্ষেত্রে / কী পরিমাণে প্রযোজ্য তা আমার কাছে মোটেও পরিষ্কার নয়)। এবং আমি এটি সন্ধান করতে পারে, কিন্তু আপনার কেবল পরিষ্কার, কারণ যুক্তি।
g33kz0r

set -eবাশকেন্দ্রিক নয় - এটি মূল বোর্ন শেল এমনকি সমর্থিত।
মার্কোস ভিভস ডেল সোল

27

আপনার যদি ক্লিনআপ থাকে তবে প্রস্থান করতে হবে, আপনি সিউডো সিগন্যাল ইআরআর দিয়ে 'ট্র্যাপ' ব্যবহার করতে পারেন। এটি আইএনটি বা অন্য কোনও সংকেত আটকে দেওয়ার মতোই কাজ করে; কোনও কমান্ড যদি ননজারো মান সহ প্রস্থান করে তবে বাশ ইআরআর ছুড়ে ফেলে:

# Create the trap with   
#    trap COMMAND SIGNAME [SIGNAME2 SIGNAME3...]
trap "rm -f /tmp/$MYTMPFILE; exit 1" ERR INT TERM
command1
command2
command3
# Partially turn off the trap.
trap - ERR
# Now a control-C will still cause cleanup, but
# a nonzero exit code won't:
ps aux | grep blahblahblah

বা, বিশেষত যদি আপনি "সেট-ই" ব্যবহার করেন, আপনি প্রস্থান করতে পারেন; আপনার ফাঁদটি তখন কার্যকর করা হবে যখন কোনও সাধারণ প্রান্ত, বাধা, -e বিকল্পের কারণে প্রস্থান হওয়া ইত্যাদি সহ স্ক্রিপ্টটি কোনও কারণে প্রস্থান করে when


12

$?পরিবর্তনশীল খুব কমই প্রয়োজন হয়। সিউডো-আইডিয়ামটি command; if [ $? -eq 0 ]; then X; fiসর্বদা হিসাবে লেখা উচিত if command; then X; fi

ক্ষেত্রে $?যখন প্রয়োজন হয় তখন এটি একাধিক মানের বিরুদ্ধে পরীক্ষা করা দরকার:

command
case $? in
  (0) X;;
  (1) Y;;
  (2) Z;;
esac

বা যখন $?পুনরায় ব্যবহারের প্রয়োজন হয় বা অন্যথায় ম্যানিপুলেট করা প্রয়োজন:

if command; then
  echo "command successful" >&2
else
  ret=$?
  echo "command failed with exit code $ret" >&2
  exit $ret
fi

3
"সর্বদা" কেন লেখা উচিত? মানে, "কেন" এমন হওয়া উচিত ? যখন কোনও কমান্ড দীর্ঘ হয় (এক ডজন বিকল্পের সাথে জিসিসিকে অনুরোধ করুন), তারপরে রিটার্নের স্থিতি পরীক্ষা করার আগে কমান্ডটি চালানো আরও বেশি পঠনযোগ্য।
ysap

যদি কোনও কমান্ডটি দীর্ঘ হয় তবে আপনি এটির নাম রেখে এটি ভেঙে ফেলতে পারেন (শেল ফাংশনটি সংজ্ঞায়িত করুন)।
মার্ক এডগার

12

এটি শীর্ষে -eবা set -eউপরে চালান ।

এছাড়াও দেখুন set -u


34
অন্যদের সম্ভাব্যরূপে সংরক্ষণ করার জন্য help set: -uত্রুটি হিসাবে আনসেট ভেরিয়েবলের উল্লেখ করে।
mklement0

1
তাই এটা হয় এর set -uবা set -eউভয়, তাই না? @ লম্পাইনোজ
এরিকন

1
@ এরিক আমি কয়েক বছর আগে অবসর নিয়েছি। যদিও আমি আমার কাজকে ভালবাসি আমার বয়স্ক মস্তিষ্ক সবকিছু ভুলে গেছে। অফহ্যান্ড আমি অনুমান করব যে আপনি উভয়কে একসাথে ব্যবহার করতে পারবেন; আমার পক্ষে খারাপ শব্দ; আমার "এবং / অথবা" বলা উচিত ছিল।
lumpynose

3

মত একটি অভিব্যক্তি

dosomething1 && dosomething2 && dosomething3

কমান্ডগুলির মধ্যে একটি যখন শূন্য-মান সহ ফিরে আসে তখন প্রক্রিয়াজাতকরণ বন্ধ হবে। উদাহরণস্বরূপ, নিম্নলিখিত কমান্ডটি কখনই "সম্পন্ন" মুদ্রণ করবে না:

cat nosuchfile && echo "done"
echo $?
1


-2

মার্ক এডগার্স ইনপুটটিতে অতিরিক্ত প্রশ্ন থাকার কারণে কেবল রেফারেন্সের জন্য অন্য একটি ছুঁড়ে ফেলা হচ্ছে এবং এখানে একটি অতিরিক্ত উদাহরণ দেওয়া হয়েছে এবং সামগ্রিকভাবে বিষয়টিতে স্পর্শ করা হয়েছে:

[[ `cmd` ]] && echo success_else_silence

যা cmd || exit errcodeকেউ দেখিয়েছে ঠিক তেমনই।

যেমন। আমি নিশ্চিত করতে চাই যে একটি পার্টিশন মাউন্ট করা থাকলে আনমাউন্ট করা আছে:

[[ `mount | grep /dev/sda1` ]] && umount /dev/sda1 

5
না, [[ সেমিডি`]] same একই জিনিস নয়। কমান্ডের আউটপুট অবস্থা নির্বিশেষে কমান্ডের আউটপুট খালি এবং সত্য হলে এটি মিথ্যা।
গিলস 'অশুভ হওয়া বন্ধ করুন'
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.