$> set -o pipefail
$> fortune | head -1 > /dev/null && echo "ΠΠΎΠ²Π΅Π·Π»ΠΎ!" || echo "ΠΡ ΠΏΡΠΎΠΈΠ³ΡΠ°Π»ΠΈ"
ΠΠΎΠ²Π΅Π·Π»ΠΎ!
$> fortune | head -1 > /dev/null && echo "ΠΠΎΠ²Π΅Π·Π»ΠΎ!" || echo "ΠΡ ΠΏΡΠΎΠΈΠ³ΡΠ°Π»ΠΈ"
ΠΡ ΠΏΡΠΎΠΈΠ³ΡΠ°Π»ΠΈ
Hemen fortune
baldintzapeko programarik gabe exit(rand())
.
Azaldu dezakezu zer dago gaizki hemen?
Digresio liriko-historikoa
Duela mende laurden ezagutu nuen lehen aldiz Heisenbug hau. Ondoren, FaxNET-eko atebiderako hainbat utilitate sortzea beharrezkoa zen bidez
Sendmail-en eta uucp/uupc-en akatsei aurre egiteko nire aurreko esperientziak "erroreen kudeaketa sakonean" gehitu zitzaidan diligentziari. Ez du balio istorio horren xehetasunetan murgiltzeak, baina Heisenbug honekin borrokatu nintzen bi astez 10-14 orduz. Hori dela eta, gogoratu zen, eta atzo ezagun zahar hau berriro bisita egitera pasa zen.
TL;DR Erantzuna
Erabilgarritasuna head
ahal itxi kanala fortune
ΡΡΠ°Π·Ρ lehen lerroa irakurri bezain pronto. Bada fortune
linea bat baino gehiago ateratzen du, gero dagokion deia write()
errore bat itzuliko du edo eskatutakoa baino byte gutxiago ateratzen direla jakinaraziko du. Era berean, erroreak kontu handiz kudeatuz idatzia fortune
egoera hori bere irteera-egoeran islatzeko eskubidea du. Ondoren, instalazioa dela eta set -o pipefail
funtzionatuko du || echo "ΠΡ ΠΏΡΠΎΠΈΠ³ΡΠ°Π»ΠΈ"
.
Hala eta guztiz ere, head
baliteke garaiz ez egitea itxi aurretik fortune
datuak ateratzen amaituko du. Orduan funtzionatuko du && echo "ΠΠΎΠ²Π΅Π·Π»ΠΎ!"
.
Nire gaurko batean GNUMakefile
echo '#define MDBX_BUILD_COMPILER "$(shell set -o pipefail; $(CC) --version | head -1 || echo 'Please use GCC or CLANG compatible compiler')"'
Gizakira itzulita
Hemen ohikoa da --version
nor den galdetzen du, eta aukera onartzen ez bada, zirriborro bat sartzen da "Mesedez, erabili GCC edo CLANG konpilatzaile bateragarria".
bezalako
#define MDBX_BUILD_COMPILER "lcc:1.23.20:Sep--4-2019:e2k-v3-linux Please use GCC or CLANG compatible compiler"
Egia esan, ez nuen berehala ezagutu nire "ezagun" zaharra. Gainera, proiektua dagoeneko hainbat aldiz probatu da Elbrusen eta banaketa ezberdin askoren pean, Alt. Hainbat konpilatzailerekin, GNU Make eta bash-en bertsioekin. Horregatik, ez nuen nire akatsa hemen ikusi nahi.
Arazoa erreproduzitu eta/edo gertatzen ari zena ulertzen saiatzean, gauza arraroagoak gertatzen hasi ziren.
Komando-lerroko ortografia:
echo "#define MDBX_BUILD_COMPILER '$(set -o pipefail; LC_ALL=C cc --version | head -1 || echo "Please use GCC or CLANG compatible compiler")'"
Tarteka testu gehigarria sortzen zuen, gero ez... Askotan aukeretako bat nahiko denbora luzez geratzen zen, baina luzeago sartzen bazenuen, beti lortzen zenituen biak!
Jakina, strace
Bide batez, nork bere burua errespetatzen duen bezala strace
nahiago du ez ugaltzea.
Beraz, zer gertatzen da?
- Erabilgarritasuna
head
eskubidea du (edo hobeto esanda, behartuta dago) irakurtzen ari den kanala ixteko eskatutako lerro kopurua irakurri bezain laster. - Datuak sortzen dituen programa-idazlea (kasu honetan
cc
) ahal inprimatu hainbat lerro eta dohainik egin hau hainbat deiren bidezwrite()
. - Bada irakurleak denbora izango du bere alboan kanala ixteko idazlearen grabazioa amaitu baino lehen, orduan akats bat jasoko du idazleak.
- Idazle programa eskubidea biek ez diote jaramonik egiten kanalaren idazketa-erroreari eta islatu zure osatze-kodean.
- Instalazioa dela eta
set -o pipefail
kanalizazioa osatzeko kodea ez-zeroa izango da (okerra) emaitza gutxienez elementu batetik zero ez bada, eta orduan funtzionatuko du|| echo "Please use GCC or CLANG compatible compiler"
.
Idazle programak seinaleekin lan egiten duenaren arabera aldakuntzak egon daitezke. Adibidez, programa modu anormalean amai daiteke (zeroa ez den/errorearen amaiera-egoera automatikoki sortuz), edo write()
eskatu eta ezarritako baino byte gutxiago idaztearen emaitza itzuliko du errno = EPIPE
.
Nor da erruduna?
Deskribatutako kasuan denetarik apur bat. Errore bat manipulatzean cc
(lcc:1.23.20:Sepβ4-2019:e2k-v3-linux) ez da erredundantea. Kasu askotan, hobe da zuhurtziaz erratea, nahiz eta horrek ohiko jokabiderako diseinatutako boilerplate baten bat-bateko akatsak agerian uzten dituen.
Zer egin?
oker:
fortune | head -1 && echo "ΠΠΎΠ²Π΅Π·Π»ΠΎ, Π½ΠΎ Π²Ρ ΡΠΈΡΠΊΡΠ΅ΡΠ΅!" || echo "WTF?"
zuzentzeko:
-
(fortune && echo "Π£ΡΠΏΠ΅ΡΠ½ΠΎ" || echo "ΠΡΠΈΠ±ΠΊΠ°") | head -1
Hemen, kanalizazio baten itxiera goiztiarra komando-interpretatzaileak kudeatuko du habiatutako kanalizazioari ("parentesien" barruan) zerbitzua ematen dionean. Horren arabera, bada
fortune
Idazketan errore bat jakinaraziko dio egoeran itxitako kanal bati, ondoren irteera|| echo "ΠΡΠΈΠ±ΠΊΠ°"
ez da inora iritsiko, kanala itxita baitago. -
fortune | cat - | head -1 && echo "Π£ΡΠΏΠ΅ΡΠ½ΠΎ" || echo "ΠΡΠΈΠ±ΠΊΠ°"
Hona hemen erabilgarritasuna
cat
motelgailu gisa jarduten du errorea baztertzen duelakoEPIPE
erretiratzean. Hau nahikoa da oraingo ondorioetarakofortune
txikia (hainbat lerro) eta kanaleko bufferean sartzen da (512 bytetik β64Kra, OS gehienetan β₯4K). Bestela, arazoa itzul daiteke.
Nola prozesatu behar bezala EPIPE
eta grabaketa akatsak?
Ez dago irtenbide zuzen bakarra, baina gomendio sinpleak daude:
EPIPE
beharrezkoa prozesatu egin behar da (eta irteera-egoeran islatzen da) osotasuna eskatzen duten datuak ateratzen direnean. Esate baterako, artxiboen edo babeskopien utilitateen funtzionamenduan.EPIPE
hobe alde batera uztea informazioa eta mezu laguntzaileak bistaratzen direnean. Adibidez, aukerei buruzko informazioa bistaratzen denean--help
edo--version
.- Garatzen ari den kodea aurretik kanalizazio batean erabil badaiteke
| head
ondorenEPIPE
Hobe da alde batera uztea, bestela hobe da irteera egoeran prozesatu eta islatzea.
Aukera hau aprobetxatu nahi dut taldeei nire esker ona adierazteko
Segi horrela Camarades, gora
Eskerrik asko
KDPV-tik
Iturria: www.habr.com