$> set -o pipefail
$> fortune | head -1 > /dev/null && echo "Повезло!" || echo "Вы проиграли"
Повезло!
$> fortune | head -1 > /dev/null && echo "Повезло!" || echo "Вы проиграли"
Вы проиграли
یہاں fortune
مشروط پروگرام کے بغیر exit(rand())
.
کیا آپ وضاحت کر سکتے ہیں؟ یہاں کیا غلط ہے?
گیت-تاریخی ڈگریشن
میں ایک چوتھائی صدی قبل اس ہائیزن بگ سے پہلی بار واقف ہوا۔ پھر FaxNET میں گیٹ وے کے لیے اس کے ذریعے کئی یوٹیلیٹیز بنانا ضروری تھا۔
سینڈ میل اور uucp/uupc میں کیڑے سے نمٹنے کے میرے پچھلے تجربے نے "مکمل غلطی سے نمٹنے" میں میری مستعدی میں اضافہ کیا۔ اس کہانی کی تفصیلات میں غوطہ لگانے کا کوئی فائدہ نہیں ہے، لیکن میں نے اس ہائیزن بگ کے ساتھ دو ہفتوں تک 10-14 گھنٹے تک جدوجہد کی۔ اس لیے یاد آیا اور کل یہ پرانا شناسا دوبارہ ملنے کے لیے رک گیا۔
TL؛ DR جواب
افادیت۔ head
کر سکتے ہیں سے چینل بند کریں fortune
ابھی جیسے ہی وہ پہلی لائن پڑھتا ہے۔ اگر fortune
ایک سے زیادہ لائنوں کو آؤٹ پٹ کرتا ہے، پھر متعلقہ کال write()
ایک غلطی واپس کرے گا یا رپورٹ کرے گا کہ درخواست سے کم بائٹس آؤٹ پٹ ہیں۔ بدلے میں، محتاط غلطی سے نمٹنے کے ساتھ لکھا گیا fortune
اس صورت حال کو اپنی خارجی حیثیت میں ظاہر کرنے کا حق رکھتا ہے۔ پھر تنصیب کی وجہ سے set -o pipefail
کام کرے گا || echo "Вы проиграли"
.
تاہم، head
وقت پر نہیں کر سکتے ہیں اس سے پہلے بند کرو fortune
آؤٹ پٹ ڈیٹا کو ختم کر دے گا۔ پھر یہ کام کرے گا۔ && echo "Повезло!"
.
میرے آج میں سے ایک میں GNUMakefile
echo '#define MDBX_BUILD_COMPILER "$(shell set -o pipefail; $(CC) --version | head -1 || echo 'Please use GCC or CLANG compatible compiler')"'
انسان میں ترجمہ کیا گیا۔
کے لیے یہاں عام ہے۔ --version
یہ پوچھتا ہے کہ وہ کون ہے، اور اگر آپشن تعاون یافتہ نہیں ہے، تو ایک سٹب ڈال دیا جاتا ہے۔ "براہ کرم GCC یا CLANG ہم آہنگ کمپائلر استعمال کریں".
پسند
#define MDBX_BUILD_COMPILER "lcc:1.23.20:Sep--4-2019:e2k-v3-linux Please use GCC or CLANG compatible compiler"
سچ کہوں تو، میں نے اپنے پرانے "آشنا" کو فوری طور پر نہیں پہچانا۔ مزید برآں، پراجیکٹ کا پہلے ہی ایلبرس پر اور بہت سی مختلف تقسیموں کے تحت تجربہ کیا جا چکا ہے، بشمول Alt۔ مختلف کمپائلرز کے ساتھ، GNU Make اور bash کے ورژن۔ اس لیے، میں یہاں اپنی غلطی نہیں دیکھنا چاہتا تھا۔
جب مسئلہ کو دوبارہ پیش کرنے اور/یا یہ سمجھنے کی کوشش کی گئی کہ کیا ہو رہا ہے، تو مزید عجیب و غریب چیزیں ہونے لگیں۔
کمانڈ لائن ہجے:
echo "#define MDBX_BUILD_COMPILER '$(set -o pipefail; LC_ALL=C cc --version | head -1 || echo "Please use GCC or CLANG compatible compiler")'"
وقتاً فوقتاً یہ اضافی ٹیکسٹ تیار کرے گا، پھر نہیں... اکثر آپشنز میں سے ایک آپشن کافی دیر تک چپکا رہتا ہے، لیکن اگر آپ زیادہ دیر تک ٹہلتے ہیں، تو آپ کو ہمیشہ دونوں مل جاتے ہیں!
ظاہر کی، strace
ویسے کسی بھی عزت نفس کی طرح strace
دوبارہ پیدا نہ کرنے کو ترجیح دیتے ہیں۔
تو کیا ہو رہا ہے؟
- افادیت۔
head
اس کے پاس یہ حق ہے (یا اس کے بجائے، مجبور بھی ہے) کہ پڑھے جانے والے چینل کو جیسے ہی وہ مطلوبہ لائنوں کی تعداد پڑھتا ہے اسے بند کر دے۔ - ڈیٹا تیار کرنے والا پروگرام مصنف (اس معاملے میں
cc
) کر سکتے ہیں متعدد لائنیں پرنٹ کریں اور مفت یہ متعدد کالوں کے ذریعے کریں۔write()
. - اگر قاری کے پاس مصنف کی طرف سے ریکارڈنگ ختم ہونے سے پہلے اپنی طرف کا چینل بند کرنے کا وقت ہوگا، پھر مصنف کو ایک غلطی موصول ہوگی۔
- رائٹر پروگرام حق ہے دونوں چینل لکھنے کی غلطی کو نظر انداز کرتے ہیں اور اسے اپنے تکمیلی کوڈ میں ظاہر کرتے ہیں۔
- تنصیب کی وجہ سے
set -o pipefail
پائپ لائن کی تکمیل کا کوڈ غیر صفر (غلط) ہوگا اگر نتیجہ کم از کم ایک عنصر سے غیر صفر ہے، اور پھر یہ کام کرے گا۔|| echo "Please use GCC or CLANG compatible compiler"
.
اس بات پر منحصر ہے کہ رائٹر پروگرام سگنلز کے ساتھ کیسے کام کرتا ہے۔ مثال کے طور پر، پروگرام غیر معمولی طور پر ختم ہو سکتا ہے (غیر صفر/غلطی ختم ہونے کی حیثیت کی خودکار تخلیق کے ساتھ)، یا write()
درخواست اور سیٹ سے کم بائٹس لکھنے کا نتیجہ واپس کر دے گا۔ errno = EPIPE
.
الزام کون ہے؟
بیان کردہ کیس میں ہر چیز کا تھوڑا سا. میں ہینڈل کرنے میں خرابی۔ cc
(lcc:1.23.20:Sep—4-2019:e2k-v3-linux) نہیں ہے۔ بے کار بہت سے معاملات میں احتیاط کی طرف سے غلطی کرنا بہتر ہے، حالانکہ یہ روایتی رویے کے لیے ڈیزائن کیے گئے بوائلر پلیٹ میں اچانک خامیوں کو ظاہر کرتا ہے۔
کیا؟
غلط:
fortune | head -1 && echo "Повезло, но вы рискуете!" || echo "WTF?"
درست طریقے سے:
-
(fortune && echo "Успешно" || echo "Ошибка") | head -1
یہاں، پائپ کی جلد بندش کو کمانڈ انٹرپریٹر کے ذریعے سنبھالا جائے گا جب نیسٹڈ پائپ لائن (قوسین کے "اندر") کی خدمت کرتے وقت۔ اس کے مطابق، اگر
fortune
اسٹیٹس میں بند چینل کو لکھنے میں غلطی کی اطلاع دے گا، پھر آؤٹ پٹ|| echo "Ошибка"
یہ کہیں نہیں ملے گا، کیونکہ چینل پہلے ہی بند ہے۔ -
fortune | cat - | head -1 && echo "Успешно" || echo "Ошибка"
یہاں افادیت ہے
cat
ایک damper کے طور پر کام کرتا ہے کیونکہ یہ غلطی کو نظر انداز کرتا ہے۔EPIPE
واپسی پر. ابھی نتیجہ نکالنے کے لیے یہی کافی ہے۔fortune
چھوٹی (کئی لائنیں) اور چینل بفر میں فٹ ہوجاتی ہیں (512 بائٹس سے ≈64K تک، زیادہ تر OS ≥4K میں)۔ ورنہ مسئلہ واپس آ سکتا ہے۔
صحیح طریقے سے عمل کرنے کا طریقہ EPIPE
اور دیگر ریکارڈنگ کی غلطیاں؟
کوئی واحد صحیح حل نہیں ہے، لیکن سادہ سفارشات ہیں:
EPIPE
ضرورت ہے عملدرآمد کرنا ضروری ہے (اور باہر نکلنے کی حالت میں ظاہر ہوتا ہے) جب ڈیٹا آؤٹ پٹ کرتے ہیں جس میں سالمیت کی ضرورت ہوتی ہے۔ مثال کے طور پر، آرکائیورز یا بیک اپ یوٹیلیٹیز کے آپریشن کے دوران۔EPIPE
نظر انداز کرنا بہتر ہے معلومات اور معاون پیغامات کی نمائش کرتے وقت۔ مثال کے طور پر، اختیارات پر معلومات ظاہر کرتے وقت--help
یا--version
.- اگر کوڈ تیار کیا جا رہا ہے تو اس سے پہلے پائپ لائن میں استعمال کیا جا سکتا ہے۔
| head
پھرEPIPE
نظر انداز کرنا بہتر ہے، بصورت دیگر باہر نکلنے کی حالت میں پروسیسنگ اور عکاسی کرنا بہتر ہے۔
میں اس موقع سے ٹیموں کا شکریہ ادا کرنا چاہوں گا۔
کیپ اٹ اپ کیمریڈز، اوپر
شکریہ
KDPV سے
ماخذ: www.habr.com