یو بل هیزنبګ د تمساح څخه تیر شو

یو بل هیزنبګ د تمساح څخه تیر شو

$> set -o pipefail

$> fortune | head -1 > /dev/null && echo "Повезло!" || echo "Вы проиграли"
Повезло!

$> fortune | head -1 > /dev/null && echo "Повезло!" || echo "Вы проиграли"
Вы проиграли

دا fortune پرته له مشروط پروګرام exit(rand()).

کولای شی تشریح کړی؟ دلته څه غلط دي?

شعر - تاریخي تحلیل

زه د لومړي ځل لپاره د دې هیزنبګ سره څلورمه پیړۍ دمخه آشنا شوم. بیا په FaxNET کې د دروازې لپاره دا اړینه وه چې له لارې ډیری اسانتیاوې رامینځته کړي پایپونه د FreeBSD لاندې "چیکر ​​لوبول". لکه څنګه چې تمه کیده، ما خپل ځان یو پرمختللی او عادلانه تجربه لرونکی پروګرامر ګڼلی. له همدې امله ، ما اراده وکړه چې هرڅه د امکان تر حده په احتیاط او احتیاط سره ترسره کړم ، د غلطۍ اداره کولو ته ځانګړې پاملرنه ...

په لیږل شوي میل او 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')"'

انسان ته ژباړل شوی

دا دلته عام دی GNU جوړ کړئ и بش د اختیار په کارولو سره د کمپیلر په لاره کې --version دا پوښتنه کوي چې هغه څوک دی، او که چیرې اختیار نه وي مالتړ شوی، نو یو سټب داخلیږي "مهرباني وکړئ د GCC یا CLANG مطابقت لرونکی کمپیلر وکاروئ".

لکه بویلر پلیټ هرچیرې موندل کیدی شي. دا ډیر وخت دمخه پدې ځای کې څرګند شو او هرچیرې یې په بشپړ ډول کار کاوه (لینکس ، سولاریس ، OSX ، FreeBSD ، WSL وغيره). خو پرون په altlinux په پلیټریټ کې Elbrus 2000 (E2K) ما ولیدل:

#define MDBX_BUILD_COMPILER "lcc:1.23.20:Sep--4-2019:e2k-v3-linux Please use GCC or CLANG compatible compiler"

په ریښتیا، ما سمدلاسه زما زوړ "آشنا" نه پیژندلی. سربیره پردې ، پروژه دمخه په ایلبروس کې څو ځله ازمول شوې او د ډیری مختلف توزیع لاندې ، په شمول د Alt. د مختلف کمپیلرونو سره ، د GNU میک او باش نسخې. له همدې امله، زه نه غواړم دلته خپله تېروتنه وګورم.

کله چې د ستونزې د بیا تولید هڅه وکړئ او / یا پوه شئ چې څه تیریږي، ډیر عجیب شیان پیښ شوي.
د کمانډ لاین املا:

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?"

سمه ده:

  1. (fortune && echo "Успешно" || echo "Ошибка") | head -1

    دلته، د پایپ ژر تړل به د کمانډ ژباړونکي لخوا اداره کیږي کله چې د نیست شوي پایپ لاین خدمت کوي (د قوس دننه"). له مخې، که fortune په وضعیت کې تړل شوي چینل ته په لیکلو کې د تېروتنې راپور ورکوي، بیا محصول || echo "Ошибка" دا به هیڅ ځای ته ونه رسیږي، ځکه چې چینل لا دمخه تړل شوی دی.

  2. fortune | cat - | head -1 && echo "Успешно" || echo "Ошибка"

    دلته افادیت دی cat د ډمپر په توګه کار کوي ځکه چې دا تېروتنه له پامه غورځوي EPIPE د وتلو پر مهال. دا د اوس پایلې لپاره کافي ده fortune کوچنۍ (څو کرښې) او د چینل بفر کې فټ کیږي (د 512 بایټ څخه تر ≈64K پورې، په ډیری OS ≥4K کې). که نه نو ستونزه به بیرته راشي.

څنګه سمه پروسس کول EPIPE او د ثبت کولو نورې تېروتنې؟

هیڅ یو مناسب حل شتون نلري، مګر ساده سپارښتنې شتون لري:

  • EPIPE اړین دی باید پروسس شي (او د وتلو حالت کې منعکس کیږي) کله چې ډیټا تولیدوي چې بشپړتیا ته اړتیا لري. د مثال په توګه، د آرشیف یا بیک اپ اسانتیاوو د عملیاتو په جریان کې.
  • EPIPE له پامه غورځول غوره دي کله چې معلومات او مرستندویه پیغامونه ښکاره کوي. د مثال په توګه، کله چې د اختیارونو په اړه معلومات ښکاره کول --help او یا --version.
  • که چیرې کوډ رامینځته شي مخکې له دې په پایپ لاین کې وکارول شي | headبیا وروسته EPIPE دا غوره ده چې سترګې پټې کړئ، که نه نو دا غوره ده چې د وتلو حالت کې پروسس او منعکس کړئ.

زه غواړم له دې فرصت څخه ګټه واخلم چې له ټیمونو څخه خپله مننه څرګند کړم MCST и altlinux د لوی تولیدي کار لپاره. ستاسو عزم د حیرانتیا وړ دی!
دا ساتئ کامریډز، پورته په مني کې غونډې!

سپوږمکۍ بیریز د ټایپونو او غلطیو سمولو لپاره.
له KDPV څخه جورجی اې.

سرچینه: www.habr.com

Add a comment