$> set -o pipefail
$> fortune | head -1 > /dev/null && echo "ΠΠΎΠ²Π΅Π·Π»ΠΎ!" || echo "ΠΡ ΠΏΡΠΎΠΈΠ³ΡΠ°Π»ΠΈ"
ΠΠΎΠ²Π΅Π·Π»ΠΎ!
$> fortune | head -1 > /dev/null && echo "ΠΠΎΠ²Π΅Π·Π»ΠΎ!" || echo "ΠΡ ΠΏΡΠΎΠΈΠ³ΡΠ°Π»ΠΈ"
ΠΡ ΠΏΡΠΎΠΈΠ³ΡΠ°Π»ΠΈ
Hapa fortune
mpango wa masharti bila exit(rand())
.
Unaweza elezea? kuna nini hapa?
Mchepuko wa sauti-kihistoria
Nilianza kufahamiana na Heisenbug hii robo ya karne iliyopita. Kisha kwa lango katika FaxNET ilikuwa ni lazima kuunda huduma kadhaa kupitia
Uzoefu wangu wa awali wa kushughulika na hitilafu katika sendmail na uucp/uupc uliongeza kwa bidii yangu katika "kushughulikia makosa kikamilifu." Hakuna maana katika kupiga mbizi katika maelezo ya hadithi hiyo, lakini nilijitahidi na Heisenbug hii kwa wiki mbili kwa saa 10-14. Kwa hivyo, ilikumbukwa, na jana jamaa huyu wa zamani aliacha kutembelea tena.
Jibu la TL; DR
Huduma head
Unaweza funga kituo kutoka fortune
mara moja mara tu anaposoma mstari wa kwanza. Kama fortune
hutoa zaidi ya mstari mmoja, kisha simu inayolingana write()
itarudisha hitilafu au itaripoti kuwa kaiti chache hutolewa kuliko ilivyoombwa. Kwa upande wake, imeandikwa na utunzaji wa makosa kwa uangalifu fortune
ina haki ya kuakisi hali hii katika hali yake ya kutoka. Kisha kutokana na ufungaji set -o pipefail
itafanya kazi || echo "ΠΡ ΠΏΡΠΎΠΈΠ³ΡΠ°Π»ΠΈ"
.
Hata hivyo, head
inaweza isifike kwa wakati karibu kabla fortune
itamaliza kutoa data. Kisha itafanya kazi && echo "ΠΠΎΠ²Π΅Π·Π»ΠΎ!"
.
Katika moja ya leo yangu GNUMakefile
echo '#define MDBX_BUILD_COMPILER "$(shell set -o pipefail; $(CC) --version | head -1 || echo 'Please use GCC or CLANG compatible compiler')"'
Imetafsiriwa kwa mwanadamu
Ni kawaida hapa kwa --version
inauliza yeye ni nani, na ikiwa chaguo halihimiliwi, basi stub imeingizwa "Tafadhali tumia kikusanyaji kinacholingana cha GCC au CLANG".
kama
#define MDBX_BUILD_COMPILER "lcc:1.23.20:Sep--4-2019:e2k-v3-linux Please use GCC or CLANG compatible compiler"
Kwa kweli, sikumtambua mara moja βrafikiβ wangu wa zamani. Zaidi ya hayo, mradi tayari umejaribiwa mara nyingi kwenye Elbrus na chini ya usambazaji mwingi tofauti, pamoja na Alt. Na wakusanyaji mbalimbali, matoleo ya GNU Tengeneza na bash. Kwa hivyo, sikutaka kuona kosa langu hapa.
Wakati wa kujaribu kuzalisha tatizo na/au kuelewa kilichokuwa kikiendelea, mambo ya ajabu zaidi yalianza kutokea.
Tahajia ya mstari wa amri:
echo "#define MDBX_BUILD_COMPILER '$(set -o pipefail; LC_ALL=C cc --version | head -1 || echo "Please use GCC or CLANG compatible compiler")'"
Kila mara ingetokeza maandishi ya ziada, basi sivyo... Mara nyingi moja ya chaguo ingeshikamana kwa muda mrefu, lakini ikiwa ungepiga kwa muda mrefu, utapata zote mbili!
Bila shaka, strace
Kwa njia, kama mtu yeyote anayejiheshimu strace
haipendi kuzaliana.
Kwa hiyo nini kinaendelea?
- Huduma
head
ina haki (au tuseme, hata inalazimishwa) kufunga chaneli inayosomwa mara tu inaposoma nambari iliyoombwa ya mistari. - Mwandishi wa programu ya kutengeneza data (katika kesi hii
cc
) Unaweza chapisha mistari mingi na bure fanya hivyo kupitia simu nyingiwrite()
. - Kama msomaji atakuwa na muda wa kufunga chaneli upande wake kabla ya mwisho wa kurekodi upande wa mwandishi, kisha mwandishi atapata makosa.
- Mpango wa mwandishi ana haki zote mbili hupuuza hitilafu ya uandishi wa kituo na kuiakisi katika msimbo wako wa kukamilisha.
- Kutokana na ufungaji
set -o pipefail
msimbo wa kukamilisha bomba hautakuwa sifuri (makosa) ikiwa matokeo sio sifuri kutoka kwa angalau kipengele kimoja, na kisha itafanya kazi.|| echo "Please use GCC or CLANG compatible compiler"
.
Kunaweza kuwa na tofauti kulingana na jinsi programu ya mwandishi inavyofanya kazi na ishara. Kwa mfano, programu inaweza kusitishwa kwa njia isiyo ya kawaida (kwa kuzalisha kiotomatiki hali isiyo ya sufuri/hitilafu ya kukomesha), au write()
itarudisha matokeo ya kuandika baiti chache kuliko ilivyoombwa na kuweka errno = EPIPE
.
Nani ana hatia?
Katika kesi iliyoelezwa kidogo ya kila kitu. Hitilafu katika kushughulikia cc
(lcc:1.23.20:Sepβ4-2019:e2k-v3-linux) sio isiyohitajika. Katika hali nyingi ni bora kukosea kwa tahadhari, ingawa hii inafichua dosari za ghafla kwenye sahani iliyoundwa kwa tabia ya kitamaduni.
Nini cha kufanya?
Si sahihi:
fortune | head -1 && echo "ΠΠΎΠ²Π΅Π·Π»ΠΎ, Π½ΠΎ Π²Ρ ΡΠΈΡΠΊΡΠ΅ΡΠ΅!" || echo "WTF?"
Haki:
-
(fortune && echo "Π£ΡΠΏΠ΅ΡΠ½ΠΎ" || echo "ΠΡΠΈΠ±ΠΊΠ°") | head -1
Hapa, kufungwa kwa bomba mapema kutashughulikiwa na mkalimani wa amri wakati wa kuhudumia bomba lililowekwa kiota ("ndani" ya mabano). Ipasavyo, ikiwa
fortune
itaripoti hitilafu katika maandishi kwa kituo kilichofungwa katika hali, kisha matokeo|| echo "ΠΡΠΈΠ±ΠΊΠ°"
haitafika popote, kwani kituo tayari kimefungwa. -
fortune | cat - | head -1 && echo "Π£ΡΠΏΠ΅ΡΠ½ΠΎ" || echo "ΠΡΠΈΠ±ΠΊΠ°"
Hapa kuna matumizi
cat
hufanya kama damper kwa sababu inapuuza kosaEPIPE
baada ya kujiondoa. Hii inatosha kwa hitimisho sasafortune
ndogo (mistari kadhaa) na inafaa katika bafa ya kituo (kutoka baiti 512 hadi β64K, katika OS nyingi β₯4K). Vinginevyo tatizo linaweza kurudi.
Jinsi ya kusindika kwa usahihi EPIPE
na makosa mengine ya kurekodi?
Hakuna suluhisho moja sahihi, lakini kuna mapendekezo rahisi:
EPIPE
inahitajika lazima kuchakatwa (na kuonyeshwa katika hali ya kuondoka) wakati wa kutoa data inayohitaji uadilifu. Kwa mfano, wakati wa uendeshaji wa kumbukumbu au huduma za chelezo.EPIPE
bora kupuuza wakati wa kuonyesha habari na ujumbe msaidizi. Kwa mfano, wakati wa kuonyesha habari juu ya chaguzi--help
au--version
.- Ikiwa nambari inayotengenezwa inaweza kutumika katika bomba hapo awali
| head
, BasiEPIPE
Ni bora kupuuza, vinginevyo ni bora kusindika na kutafakari katika hali ya kuondoka.
Napenda kuchukua fursa hii kutoa shukurani zangu kwa timu
Keep it up Camarades, up
Shukrani
KDPV kutoka
Chanzo: mapenzi.com