পাইপফাইলে একইভাবে ব্যাকটিক ব্যর্থতায় প্রস্থান করার জন্য আমি কীভাবে বাশ পেতে পারি?


55

সুতরাং আমি আমার ব্যাশ স্ক্রিপ্টগুলিকে শক্ত করতে চাই যেখানেই আমি (এবং পাইথন / রুবির মতো কোনও ভাষাতে অর্পণ করতে সক্ষম না হয়ে) ত্রুটিগুলি যাতে না ঘটে তা নিশ্চিত করতে।

সেই শিরাতে আমার কড়া আছে sh

set -e
set -u
set -o pipefail

এবং অন্যান্য স্ক্রিপ্টে এটি উত্স। যাইহোক, পাইপফেইলটি যখন গ্রহণ করবে:

false | echo it kept going | true

এটি উঠবে না:

echo The output is '`false; echo something else`' 

আউটপুট হবে

আউটপুট ''

মিথ্যাটি শূন্য-বিহীন স্থিতি এবং কোনও স্টাডাউট দেয়। পাইপে এটি ব্যর্থ হত তবে এখানে ত্রুটি ধরা পড়ে না। এটি যখন পরবর্তী সময়ের জন্য কোনও ভেরিয়েবলে সঞ্চিত একটি গণনা এবং মানটি ফাঁকা সেট করা থাকে, এটি পরে সমস্যাগুলির কারণ হতে পারে।

সুতরাং - বাইরে বেরোনোর ​​যথেষ্ট কারণ হিসাবে ব্যাকটিকের অভ্যন্তরে শূন্য নন রিটার্নকোডটি চিকিত্সা করার জন্য কি বাশ পাওয়ার কোনও উপায় আছে?

উত্তর:


51

একক ইউনিক্স স্পেসিফিকেশনে এর অর্থটিset -e বর্ণনা করতে সঠিক ভাষাটি ব্যবহৃত হয়:

যখন এই বিকল্পটি চালু থাকে, শেল ত্রুটিগুলির ফলাফলের তালিকাভুক্ত কোনও কারণে যদি একটি সাধারণ কমান্ড ব্যর্থ হয় বা একটি প্রস্থান স্থিতির মান> 0 প্রদান করে এবং [শর্তসাপেক্ষ বা অবহেলিত কমান্ড] না হয়, তবে শেলটি তত্ক্ষণাত প্রস্থান করা হবে।

এই ধরনের একটি কমান্ড সাব-শেলের মধ্যে আসলে কী হয় তা নিয়ে একটি অস্পষ্টতা রয়েছে । ব্যবহারিক দৃষ্টিকোণ থেকে, সমস্ত সাবস্কেল যা করতে পারে তা প্রস্থান এবং পিতামাতার শেলের কাছে একটি ননজারো স্থিতি ফিরিয়ে আনতে হবে। প্যারেন্ট শেলটি পরিবর্তিতভাবে প্রস্থান করবে কিনা তার উপর নির্ভর করে এই ননজারো স্থিতিটি পিতামাত্ত শেলটিতে ব্যর্থ হওয়া কোনও সাধারণ কমান্ডে অনুবাদ করে কিনা on

এরকম একটি সমস্যাযুক্ত কেস হ'ল আপনার মুখোমুখি হওয়া: একটি কমান্ড সাবস্টিটিউশন থেকে ননজারো রিটার্নের স্থিতি । যেহেতু এই স্থিতিটিকে উপেক্ষা করা হচ্ছে, এটি প্যারেন্ট শেলটিকে প্রস্থান করতে পারে না। হিসাবে আপনি ইতিমধ্যে আবিষ্কার করেছি একাউন্টে প্রস্থান অবস্থা গ্রহণ করা একটি উপায় একটি সহজ কমান্ড প্রতিকল্পন ব্যবহার করা নিয়োগ তারপর: নিয়োগ প্রস্থান অবস্থা নিয়োগ (গুলি) গত কমান্ড প্রতিকল্পন প্রদর্শন করে প্রস্থান অবস্থা

মনে রাখবেন যে কেবলমাত্র সর্বশেষ প্রতিস্থাপনের স্থিতি বিবেচনায় নেওয়া হলে কেবলমাত্র একটি একক কমান্ড প্রতিস্থাপন থাকলেই এটি উদ্দেশ্য হিসাবে সম্পাদন করবে। উদাহরণস্বরূপ, নীচের কমান্ডটি সফল (উভয়ই মান অনুযায়ী এবং প্রতিটি বাস্তবায়নে আমি দেখেছি):

a=$(false)$(echo foo)

জন্য ঘড়ি আরেকটি ক্ষেত্রে দেখা যায় স্পষ্ট subshells : (somecommand)। উপরোক্ত ব্যাখ্যা অনুসারে, সাবশেল একটি ননজারো স্থিতি ফিরিয়ে দিতে পারে, তবে যেহেতু এটি প্যারেন্ট শেলের কোনও সাধারণ কমান্ড নয়, প্যারেন্ট শেলটি চালিয়ে যাওয়া উচিত। আসলে, আমার জানা সমস্ত শেলগুলি পিতামাতাকে এই সময়ে ফিরে আসে। যদিও এটি অনেক ক্ষেত্রে যেমন (cd /some/dir && somecommand)প্যারেন্টেসিসগুলি কোনও ক্রিয়াকলাপ যেমন কোনও বর্তমান ডিরেক্টরি পরিবর্তন হিসাবে স্থানীয় রাখতে ব্যবহৃত হয় set -eততক্ষণে এটি সাবস্কেলে বন্ধ করা থাকলে স্পেসিফিকেশনটিকে লঙ্ঘন করে বা সাবসেল কোনও ননজারো স্ট্যাটাসটি এমনভাবে ফেরত দেয় যাতে !সত্যিকারের কমান্ড ব্যবহার করার মতো এটি এটিকে বন্ধ করবে না । উদাহরণস্বরূপ, fooনিম্নলিখিত উদাহরণগুলি প্রদর্শন না করে ছাই, বাশ, পিডিএক্স, ksh93 এবং zsh এর সমস্ত প্রস্থান :

set -e; (set +e; false); echo "This should be displayed"
set -e; (! true); echo "This should be displayed"

তবুও set -eকার্যকর হওয়ার সময় কোনও সাধারণ আদেশ ব্যর্থ হয়নি !

তৃতীয় সমস্যাযুক্ত কেস হ'ল একটি অনিয়ন্ত্রিত পাইপলাইনের উপাদান । অনুশীলনে, সমস্ত শেলগুলি শেষের ব্যতীত পাইপলাইনের উপাদানগুলির ব্যর্থতা উপেক্ষা করে এবং সর্বশেষ পাইপলাইন উপাদান সম্পর্কিত দুটি আচরণের একটি প্রদর্শন করে:

  • এটিটি ksh এবং zsh, যা প্যারেন্ট শেলের পাইপলাইনের শেষ উপাদানটি কার্যকর করে, যথারীতি ব্যবসা করে: পাইপলাইনের শেষ উপাদানটিতে যদি একটি সাধারণ কমান্ড ব্যর্থ হয় তবে শেলটি সেই আদেশটি কার্যকর করে, যা প্যারেন্ট শেল হিসাবে দেখা যায়, প্রস্থান করে।
  • অন্যান্য শাঁসগুলি যদি পাইপলাইনের শেষ উপাদানটি ননজারো স্থিতি ফিরিয়ে দেয় তবে প্রস্থান করে আচরণের আনুমানিক।

আগের মত, set -eপাইপলাইনের শেষ উপাদানটিতে অবহেলা বা অবহেলা ব্যবহারের ফলে এটি শাঁসটি শেষ না করে এমনভাবে একটি ননজারো স্থিতি ফিরিয়ে আনবে; এটিটি ksh এবং zsh ছাড়া অন্য শেলগুলি তখন প্রস্থান করবে।

বাশ-এর pipefailবিকল্পের ফলে কোনও পাইপলাইন অবিলম্বে প্রস্থান করতে পারে set -eযদি এর কোনও উপাদান ননজারো স্থিতি ফিরিয়ে দেয়।

মনে রাখবেন যে আরও জটিলতা হিসাবে, set -eপশম মোডে না থাকলে ( set -o posixবা POSIXLY_CORRECTবাশ শুরু হওয়ার সাথে সাথে পরিবেশে থাকতে পারে ) ব্যাশ সাবশেলগুলিতে বন্ধ হয় ।

এই সবগুলি দেখায় যে পসিএক্স স্পেসিফিকেশন দুর্ভাগ্যক্রমে -eবিকল্পটি নির্দিষ্ট করার ক্ষেত্রে একটি দুর্বল কাজ করে । ভাগ্যক্রমে, বিদ্যমান শেলগুলি তাদের আচরণে বেশিরভাগ ক্ষেত্রেই সামঞ্জস্যপূর্ণ।


এর জন্য ধন্যবাদ. আমার একটি অভিজ্ঞতা ছিল যে ব্যাশের পরবর্তী সংস্করণে ধরা পড়া কিছু ত্রুটি সেট-ই সহ পূর্ববর্তী সংস্করণগুলিতে উপেক্ষা করা হয়েছিল। এখানে আমার উদ্দেশ্য হ'ল স্ক্রিপ্টগুলিকে কঠোর করা যে কোনও হ্যান্ডেল না করা ত্রুটি ফিরে আসা / ব্যর্থতার শর্ত স্ক্রিপ্টটি প্রস্থান করতে পারে। এটি এমন একটি লিগ্যাসি সিস্টেমে যা জঞ্জাল আউটপুট ফাইলগুলি তৈরি করতে এবং "0" 0 টি শুভ প্রস্থান কোডটি ভুল vভির সাথে বিশৃঙ্খলার আধ ঘন্টা পরে তৈরি করার জন্য পরিচিত - যদি না আপনি বাজপাখির মতো আউটপুট দেখেন (এবং সমস্ত ত্রুটি না স্ট্যাডারে রয়েছে, কিছু স্টডআউটে রয়েছে এবং কিছু অংশ / দেব / নাল), আপনি কেবল জানেন না।
ড্যানি স্ট্যাপল

"উদাহরণস্বরূপ, নিম্নলিখিত উদাহরণগুলিতে ফু প্রদর্শন না করে সমস্ত ছাই, বাশ, পিডিএক্স, কেএস 93 এবং জেডএস প্রস্থান": ব্যাসিবক্স অ্যাশটি সেভাবে আচরণ করে না, এটি অনুমান অনুসারে আউটপুট প্রদর্শন করে। (বুসিবক্স ১.১৯.৪. এর সাথে পরীক্ষিত)) বা এটির সাথে প্রস্থানও হয় না set -e; (cd /nonexisting)
সন্দেহভাজন জিম

27

(আমার নিজের উত্তর দেওয়া কারণ আমি একটি সমাধান খুঁজে পেয়েছি) এর একটি সমাধান হ'ল সর্বদা একটি মধ্যবর্তী ভেরিয়েবলকে এটি নির্ধারণ করা। এইভাবে রিটার্ন কোড ( $?) সেট করা আছে।

সুতরাং

ABC=`exit 1`
echo $?

তবে আউটপুট 1(অথবা set -eউপস্থিত থাকলে প্রস্থান করা হবে ), তবে:

echo `exit 1`
echo $?

0ফাঁকা রেখার পরে আউটপুট আসবে। প্রতিধ্বনিটির রিটার্ন কোড (বা অন্যান্য কমান্ড যা ব্যাকটিক আউটপুট নিয়ে চলেছিল) 0 রিটার্ন কোডটি প্রতিস্থাপন করবে।

আমি এখনও এমন সমাধানগুলিতে উন্মুক্ত রয়েছি যাগুলির মধ্যবর্তী পরিবর্তনশীলগুলির প্রয়োজন হয় না, তবে এটি আমার কিছু উপায় পায়।


23

যেমন ওপি তার নিজের উত্তরে ইঙ্গিত করেছে, সাবকম্যান্ডের আউটপুটটি একটি ভেরিয়েবলের সাথে নির্ধারণ করা সমস্যার সমাধান করে; $?অনাহত ছেড়ে দেওয়া হয়।

যাইহোক, একটি প্রান্তের ক্ষেত্রে এখনও আপনাকে মিথ্যা নেগেটিভ ধাঁধা দিতে পারে (অর্থাত্ কমান্ড ব্যর্থ হয় তবে ত্রুটি বুবল হয় না), localপরিবর্তনশীল ঘোষণা:

local myvar=$(subcommand)হবে সবসময় আসতে 0!

bash(1) এটি উল্লেখ করে:

   local [option] [name[=value] ...]
          ... The return status is 0 unless local is used outside a function,
          an invalid name is supplied, or name is a readonly variable.

এখানে একটি সাধারণ পরীক্ষার কেস:

#!/bin/bash

function test1() {
  data1=$(false) # undeclared variable
  echo 'data1=$(false):' "$?"
  local data2=$(false) # declaring and assigning in one go
  echo 'local data2=$(false):' "$?"
  local data3
  data3=$(false) # assigning a declared variable
  echo 'local data3; data3=$(false):' "$?"
}

test1

আউটপুট:

data1=$(false): 1
local data2=$(false): 0
local data3; data3=$(false): 1

আপনাকে ধন্যবাদ, আমার মধ্যে অসঙ্গতি VAR=...এবং local VAR=...সত্যই আমাকে ভাসিয়ে দিয়েছে!
জনি 14

13

অন্যরা যেমন বলেছে, localসর্বদা 0. ফিরে আসবে সমাধানটি হ'ল প্রথমে ভেরিয়েবলটি ঘোষণা করা:

function testcase()
{
    local MYRESULT

    MYRESULT=$(false)
    if (( $? != 0 )); then
        echo "False returned false!"
        return 1
    fi

    return 0
}

আউটপুট:

$ testcase
False returned false!
$ 

4

কমান্ড প্রতিস্থাপনের ব্যর্থতা থেকে বেরিয়ে আসার জন্য আপনি স্পষ্টভাবে -eএকটি সাবসেলের মধ্যে সেট করতে পারেন , এর মতো:

set -e
x=$(set -e; false; true)
echo "this will never be shown"

1

মজার বিষয়!

আমি এর আগে কখনও হোঁচট খেয়েছি না, কারণ আমি set -e(এর পরিবর্তে আমি পছন্দ করি trap ... ERR) এর বন্ধু নই তবে ইতিমধ্যে এটি পরীক্ষা করেছি: trap ... ERRএছাড়াও $(...)(বা পুরাতন ফ্যাশনযুক্ত ব্যাকটিক্স) এর মধ্যে ত্রুটিগুলি ধরবে না ।

আমি মনে করি যে সমস্যাটি (যতবার ঘন ঘন) এখানে একটি সাবশেল বলা হয় এবং -eস্পষ্টভাবে বোঝানো হয় বর্তমান শেল।

এই মুহুর্তে অন্য যে সমাধানগুলি মনে আসে কেবল তা হ'ল পঠন ব্যবহার করা:

 ls -l ghost_under_bed | read name

এই ছোঁড়া ERRএবং -eশেল দিয়ে সমাপ্ত হবে। কেবলমাত্র সমস্যা: এটি কেবলমাত্র এক লাইনের আউটপুট সহ কমান্ডগুলির জন্য কাজ করে (বা আপনি লাইনগুলিতে যোগ হওয়া কোনও কিছু দিয়ে পাইপ করুন)।


1
পঠন কৌশল সম্পর্কে নিশ্চিত নন, এর চেষ্টাটি ভেরিয়েবলের সাথে আবদ্ধ না হওয়ার দিকে পরিচালিত করে। আমি মনে করি এটি এর কারণ হতে পারে পাইপের অন্য দিকটি কার্যকরভাবে একটি সাবশেল, নাম উপলব্ধ হবে না।
ড্যানি স্ট্যাপল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.