$> set -o pipefail
$> fortune | head -1 > /dev/null && echo "Повезло!" || echo "Вы проиграли"
Повезло!
$> fortune | head -1 > /dev/null && echo "Повезло!" || echo "Вы проиграли"
Вы проиграли
it is fortune
betingst programma sûnder exit(rand())
.
Kinsto útlizze? wat is hjir mis?
Lyrysk-histoaryske ôfwiking
Mei dizze Heisenbug kaam ik in kwart ieu lyn foar it earst yn de kunde. Dan foar de poarte yn FaxNET wie it nedich om ferskate nutsbedriuwen te meitsjen fia
Myn eardere ûnderfining fan it omgean mei bugs yn sendmail en uucp/uupc foege ta oan myn warberens yn "yngeande flaterôfhanneling." It hat gjin punt om yn 'e details fan dat ferhaal te dûken, mar ik haw twa wiken lang 10-14 oeren muoite mei dizze Heisenbug. Dêrom waard it betocht, en juster stie dizze âlde kunde nochris op besite.
TL; DR Antwurd
Utility head
kin slute it kanaal út fortune
сразу sa gau as er de earste rigel lêst. As fortune
útfiert mear as ien rigel, dan de oerienkommende oprop write()
sil in flater weromjaan of rapportearje dat minder bytes wurde útfierd dan frege. Op syn beurt skreaun mei soarchfâldige flater ôfhanneling fortune
hat it rjocht om dizze situaasje te reflektearjen yn syn útgongsstatus. Dan fanwege ynstallaasje set -o pipefail
sil wurkje || echo "Вы проиграли"
.
Mar, head
kin it net op 'e tiid meitsje ticht foardat fortune
sil it útfieren fan gegevens foltôgje. Dan sil it wurkje && echo "Повезло!"
.
Yn ien fan myn hjoed GNUMakefile
echo '#define MDBX_BUILD_COMPILER "$(shell set -o pipefail; $(CC) --version | head -1 || echo 'Please use GCC or CLANG compatible compiler')"'
Oerset yn minsklik
It is hjir gewoan foar --version
it freget wa't hy is, en as de opsje net stipe wurdt, dan wurdt in stub ynfoege "Gebrûk asjebleaft GCC- of CLANG-kompatibele kompilator".
lykas
#define MDBX_BUILD_COMPILER "lcc:1.23.20:Sep--4-2019:e2k-v3-linux Please use GCC or CLANG compatible compiler"
Earlik sein, ik herkende myn âlde "bekende" net daliks. Boppedat is it projekt al in protte kearen testen op Elbrus en ûnder in protte ferskillende distribúsjes, ynklusyf Alt. Mei ferskate gearstallers, ferzjes fan GNU Make en bash. Dêrom woe ik myn flater hjir net sjen.
By it besykjen om it probleem te reprodusearjen en/of te begripen wat der bart, begûnen mear frjemde dingen te barren.
Kommandorigel stavering:
echo "#define MDBX_BUILD_COMPILER '$(set -o pipefail; LC_ALL=C cc --version | head -1 || echo "Please use GCC or CLANG compatible compiler")'"
Sa no en dan soe it ekstra tekst opleverje, dan net... Faak bliuwde ien fan de opsjes nochal lang, mar ast langer poarste, krigest altyd beide!
Fansels, strace
Troch de wei, lykas alle sels-respektearjen strace
leaver net reprodusearje.
Wat is der geande?
- Utility
head
hat it rjocht (of leaver, wurdt sels twongen) te sluten it kanaal wurdt lêzen sa gau as it lêst it frege oantal rigels. - De data-generearjende programma-skriuwer (yn dit gefal
cc
) kin print meardere rigels en frij doch dit troch meardere oproppenwrite()
. - as de lêzer sil tiid hawwe om it kanaal oan syn kant te sluten foar it ein fan de opname oan 'e kant fan 'e skriuwer, dan krijt de skriuwer in flater.
- Skriuwersprogramma it rjocht hawwe om beide negearje de skriuwflater fan it kanaal en reflektearje it yn jo foltôgingskoade.
- Troch ynstallaasje
set -o pipefail
de koade foar foltôging fan pipeline sil net-nul wêze (ferkeard) as it resultaat net-nul is fan op syn minst ien elemint, en dan sil it wurkje|| echo "Please use GCC or CLANG compatible compiler"
.
D'r kinne fariaasjes wêze ôfhinklik fan hoe't it skriuwerprogramma wurket mei sinjalen. Bygelyks, it programma kin abnormaal beëinigje (mei automatyske generaasje fan in net-nul/flater beëinigingsstatus), of write()
sil it resultaat weromjaan fan it skriuwen fan minder bytes dan oanfrege en ynsteld errno = EPIPE
.
Wa is skuldich?
Yn it beskreaune gefal bytsje fan alles. Flater behanneling yn cc
(lcc:1.23.20:Sep—4-2019:e2k-v3-linux) is net oerstallich. Yn in protte gefallen is it better om te fersin oan 'e kant fan foarsichtigens, hoewol't dit docht bleat ynienen gebreken yn in boilerplate ûntwurpen foar tradisjoneel gedrach.
Wat moat ik dwaan?
Ferkeard:
fortune | head -1 && echo "Повезло, но вы рискуете!" || echo "WTF?"
Korrekt:
-
(fortune && echo "Успешно" || echo "Ошибка") | head -1
Hjir sil it betiid sluten fan in piip wurde behannele troch de kommando-tolk by it betsjinjen fan de nestele pipeline ("binnen" de haakjes). As gefolch, as
fortune
sil rapportearje in flater skriftlik nei in sletten kanaal yn 'e status, dan de útfier|| echo "Ошибка"
it sil net komme oeral, sûnt it kanaal is al sletten. -
fortune | cat - | head -1 && echo "Успешно" || echo "Ошибка"
Hjir is it nut
cat
fungearret as in damper omdat it negearret de flaterEPIPE
by weromlûken. Dit is genôch foar no konklúzjefortune
lyts (ferskate rigels) en past yn it kanaal buffer (fan 512 bytes to ≈64K, yn de measte OS ≥4K). Oars kin it probleem weromkomme.
Hoe korrekt te ferwurkjen EPIPE
en oare opname flaters?
D'r is gjin ienige juste oplossing, mar d'r binne ienfâldige oanbefellings:
EPIPE
ferplicht moat wurde ferwurke (en wjerspegele yn 'e útgongsstatus) by it útfieren fan gegevens dy't yntegriteit nedich binne. Bygelyks, tidens de wurking fan argiven of reservekopy-nutsbedriuwen.EPIPE
better om te negearjen by it werjaan fan ynformaasje en helpberjochten. Bygelyks by it werjaan fan ynformaasje oer opsjes--help
of--version
.- As de koade wurdt ûntwikkele kin brûkt wurde yn in pipeline foar
| head
, danEPIPE
It is better om te negearjen, oars is it better om te ferwurkjen en te reflektearjen yn 'e útgongsstatus.
Ik wol dizze gelegenheid brûke om myn tankberens út te sprekken oan de teams
Keep it up Camarades, up
Спасибо
KDPV út
Boarne: www.habr.com