যেকোনো পর্যায় থেকে একটি zsh পাইপলাইনে ব্যর্থতার রিপোর্ট পাওয়ার জন্য, এটি চালানোর আগে PIPE_FAIL বিকল্পটি সক্রিয় করুন। Mac-এর Terminal-এ setopt PIPE_FAIL লিখুন; একটি স্ক্রিপ্টে, পাইপলাইনের আগে সেই লাইনটি রাখুন। পাইপলাইনটি তখন তার সর্বডানের ব্যর্থ কমান্ডের এক্সিট স্ট্যাটাস প্রদান করে, অথবা প্রতিটি কমান্ড সফল হলে শূন্য দেয়। পাইপলাইনের ঠিক পরেই $? ক্যাপচার করুন যদি পরবর্তী কমান্ডগুলো দ্বারা সেই ফলাফল প্রতিস্থাপন হওয়া প্রতিরোধ করতে চান। zsh অপশন ম্যানুয়াল-এ এই আচরণটি নথিভুক্ত করা আছে।

কেন একটি ব্যর্থ পাইপলাইনকে সফল মনে হতে পারে

ডিফল্টভাবে, zsh একটি পাইপলাইনকে তার শেষ কমান্ডের এক্সিট স্ট্যাটাস দেয়। তাই যদি আগের কোনো কমান্ড ব্যর্থ হয় কিন্তু শেষ কমান্ডটি সফল হয়, তবে সামগ্রিক পাইপলাইনটিকে সফল মনে হতে পারে। উদাহরণস্বরূপ, grep কোনো মিল পাওয়া লাইন না পেলেও নিচের চূড়ান্ত cat কমান্ডটি সফল হতে পারে:

printf '%s\n' 'ready' | grep 'missing' | cat
print -r -- $?

zsh ম্যানুয়াল পাইপলাইনকে | দ্বারা যুক্ত কমান্ড হিসেবে সংজ্ঞায়িত করে এবং বলে যে এর মান সাধারণত শেষ কমান্ডের মান হয়। একটি শূন্য স্ট্যাটাস মানে সফলতা; একটি অশূন্য (nonzero) স্ট্যাটাস মানে কমান্ড বা পাইপলাইন ব্যর্থতার রিপোর্ট করেছে। zsh পাইপলাইন সংক্রান্ত ডকুমেন্টেশন-এ এই ডিফল্ট নিয়মটি বর্ণনা করা হয়েছে।

পাইপলাইনের জন্য PIPE_FAIL সক্রিয় করুন

একটি Terminal সেশনে, কমান্ড চালানোর আগে বিকল্পটি সেট করুন:

setopt PIPE_FAIL
printf '%s\n' 'ready' | grep 'missing' | cat
print -r -- $?

এখন চূড়ান্ত স্ট্যাটাসটি অশূন্য, কারণ cat সফল হওয়া সত্ত্বেও grep ব্যর্থ হয়েছে। PIPE_FAIL পাইপলাইনের সর্বডানের অশূন্য স্ট্যাটাসটি ব্যবহার করে। এটি zsh দ্বারা নির্বাচিত প্রকৃত স্ট্যাটাস কোড প্রদান করার পাশাপাশি ব্যর্থতাকে অর্থপূর্ণ রাখে। একই সেশনে এই আচরণটি আবার বন্ধ করতে, unsetopt PIPE_FAIL চালান।

একটি স্ক্রিপ্টের ক্ষেত্রে, বিকল্পটি ইন্টারপ্রেটার লাইনের পরে এবং যেকোনো প্রভাবিত পাইপলাইনের আগে, ওপরের দিকে রাখুন:

#!/bin/zsh
setopt PIPE_FAIL

printf '%s\n' 'ready' | grep 'missing' | cat
pipeline_status=$?

if (( pipeline_status != 0 )); then
  print -u2 -- "Pipeline failed with status $pipeline_status"
  exit "$pipeline_status"
fi

স্পষ্টভাবে স্ট্যাটাস অ্যাসাইন করা জরুরি: $? মানে শেষ কমান্ডের স্ট্যাটাস, তাই পরবর্তী কোনো print, ভ্যারিয়েবল সংক্রান্ত কমান্ড বা কন্ডিশনাল এটি যা রিপোর্ট করে তা পরিবর্তন করতে পারে। তাৎক্ষণিকভাবে মানটি সংরক্ষণ করলে স্ক্রিপ্ট অন্য কাজের পরেও এটি রিপোর্ট করতে পারে বা এটি নিয়ে প্রস্থান (exit) করতে পারে। এই উদাহরণটি স্ক্রিপ্ট চালু করা প্রোগ্রামটিতে একটি ব্যর্থতার স্ট্যাটাস ফেরত পাঠায়; এটি আগের কোনো পর্যায় ব্যর্থ হওয়ার সাথে সাথে পৃথক পাইপলাইন কমান্ডগুলো চলা বন্ধ করে না।

প্রতিটি পর্যায়ের ফলাফল প্রয়োজন হলে pipestatus ব্যবহার করুন

PIPE_FAIL পাইপলাইনের সারসংক্ষেপ দেয়। কোন কমান্ডটি কোন কোড দিয়েছে তাও যদি আপনার শনাক্ত করার প্রয়োজন হয়, তবে zsh বিশেষ অ্যারে pipestatus প্রদান করে, যাতে শেষ পাইপলাইনের প্রতিটি কমান্ডের স্ট্যাটাস থাকে। এটি সাথে সাথেই পড়ে নিন, কারণ অন্য কোনো পাইপলাইন এই মানগুলোকে প্রতিস্থাপন করে দেয়। zsh প্যারামিটার রেফারেন্স-এ এই অ্যারেটির বিবরণ রয়েছে।

printf '%s\n' 'ready' | grep 'missing' | cat
print -r -- "Stage statuses: ${pipestatus[*]}"

এই তিনটি কমান্ডের উদাহরণের জন্য, আউটপুটটি printf-এর জন্য শূন্য, grep-এর জন্য একটি অশূন্য মান এবং cat-এর জন্য শূন্য দেখায়। সুনির্দিষ্ট অশূন্য কোডটি কমান্ডের ওপর নির্ভর করে। আপনার যদি সামগ্রিক ফলাফল এবং প্রতি-পর্যায়ের ফলাফল উভয়েরই প্রয়োজন হয়, তবে PIPE_FAIL ব্যবহার করুন এবং সাথে সাথেই সামগ্রিক $? সংরক্ষণ করুন; পর্যায়গুলো ডায়াগনোজ করার সময় আলাদা পাইপলাইন চালানোর ঠিক পরেই pipestatus পরীক্ষা করুন, অথবা প্রথমে অ্যারেটি রেকর্ড করতে এবং সেই সংরক্ষিত ডেটা থেকে কাঙ্ক্ষিত সামগ্রিক ফলাফল গণনা করতে স্ক্রিপ্টটি ডিজাইন করুন। পাইপলাইন এবং যে স্ট্যাটাসটি আপনি পড়তে চান তার মাঝে অন্য কোনো কমান্ড বা পাইপলাইন ঢোকানো এড়িয়ে চলুন।

সঠিক শেলের মধ্যে সেটিংটি রাখুন

একটি ইন্টারঅ্যাক্টিভ zsh সেশনে পরবর্তী কমান্ডগুলোতে এই অপশন প্রয়োগ করতে, সেই সেশনে setopt PIPE_FAIL চালান। প্রতিটি নতুন zsh সেশনের জন্য এটি সক্রিয় করতে, লাইনটি ~/.zshrc-এ যোগ করুন, তারপর একটি নতুন Terminal উইন্ডো খুলুন অথবা source ~/.zshrc দিয়ে ফাইলটি সোর্স করুন। Apple-এর Terminal গাইড zsh-কে ডিফল্ট শেল হিসেবে চিহ্নিত করে, পাশাপাশি উল্লেখ করে যে সেটিংস বা অ্যাডমিনিস্ট্রেটররা অন্য কোনো শেল বেছে নিতে পারেন। zsh-নির্দিষ্ট সিনট্যাক্সের ওপর নির্ভর করার আগে সক্রিয় শেলটি নিশ্চিত করুন। Apple-এর Terminal গাইড ব্যাখ্যা করে কীভাবে Terminal শেল নির্বাচন করে।

#!/bin/zsh দিয়ে শুরু হওয়া একটি স্ক্রিপ্ট Terminal-এর জন্য কনফিগার করা ইন্টারঅ্যাক্টিভ শেল নির্বিশেষে সরাসরি zsh-এর অনুরোধ করে। স্ক্রিপ্টটি যদি অন্য কোনো শেল দ্বারা চালানো হয়, তবে setopt এবং pipestatus সেই শেলের নিজস্ব পাইপলাইন নিয়ন্ত্রণের পোর্টেবল বিকল্প নয়। ইন্টারপ্রেটার এবং সিনট্যাক্স সামঞ্জস্যপূর্ণ রাখুন, তারপর পরবর্তী কাজ করার আগে পাইপলাইনের ফলাফল সংরক্ষণ করুন।

সূত্রসমূহ