$> set -o pipefail
$> fortune | head -1 > /dev/null && echo "ΠΠΎΠ²Π΅Π·Π»ΠΎ!" || echo "ΠΡ ΠΏΡΠΎΠΈΠ³ΡΠ°Π»ΠΈ"
ΠΠΎΠ²Π΅Π·Π»ΠΎ!
$> fortune | head -1 > /dev/null && echo "ΠΠΎΠ²Π΅Π·Π»ΠΎ!" || echo "ΠΡ ΠΏΡΠΎΠΈΠ³ΡΠ°Π»ΠΈ"
ΠΡ ΠΏΡΠΎΠΈΠ³ΡΠ°Π»ΠΈ
iku fortune
program kondisional tanpa exit(rand())
.
Apa sampeyan bisa nerangake? ana apa ing kene?
Digression liris-historis
Aku pisanan dadi kenalan karo Heisenbug iki seprapat abad kepungkur. Banjur kanggo gateway ing FaxNET perlu kanggo nggawe sawetara keperluan liwat
Pengalamanku sadurunge nangani kewan omo ing sendmail lan uucp/upc ditambahake kanggo ketekunan "penanganan kesalahan sing lengkap." Ora ana gunane nyilem menyang rincian crita kasebut, nanging aku berjuang karo Heisenbug iki sajrone rong minggu suwene 10-14 jam. Mula dieling-eling, wingi kenalan tuwa iki mampir dolan maneh.
TL; DR Jawaban
Utilitas head
bisa nutup saluran saka fortune
langsung sanalika dheweke maca baris pisanan. Yen fortune
output luwih saka siji baris, banjur telpon cocog write()
bakal ngasilake kesalahan utawa laporan yen bita luwih sithik tinimbang sing dijaluk. Ing siji, ditulis kanthi ati-ati kesalahan penanganan fortune
nduweni hak kanggo nggambarake kahanan iki ing status metu sawijining. Banjur amarga instalasi set -o pipefail
bakal bisa || echo "ΠΡ ΠΏΡΠΎΠΈΠ³ΡΠ°Π»ΠΈ"
.
Nanging, head
bisa uga ora teka ing wektu cedhak sadurunge fortune
bakal rampung output data. Banjur bakal bisa && echo "ΠΠΎΠ²Π΅Π·Π»ΠΎ!"
.
Ing salah sawijining dina iki GNUMakefile
echo '#define MDBX_BUILD_COMPILER "$(shell set -o pipefail; $(CC) --version | head -1 || echo 'Please use GCC or CLANG compatible compiler')"'
Diterjemahake menyang manungsa
Iku umum kene kanggo --version
iku takon sapa iku, lan yen pilihan ora didhukung, banjur stub dipasang "Gunakake kompiler sing kompatibel karo GCC utawa CLANG".
Kaya
#define MDBX_BUILD_COMPILER "lcc:1.23.20:Sep--4-2019:e2k-v3-linux Please use GCC or CLANG compatible compiler"
Terus terang, aku ora langsung ngerteni "kenalan" lawasku. Kajaba iku, proyek kasebut wis diuji kaping pirang-pirang ing Elbrus lan ing macem-macem distribusi, kalebu Alt. Kanthi macem-macem kompiler, versi GNU Make lan bash. Mulane, aku ora pengin ndeleng kesalahanku ing kene.
Nalika nyoba ngasilake masalah lan / utawa ngerti apa sing kedadeyan, kedadeyan sing luwih aneh.
Ejaan baris perintah:
echo "#define MDBX_BUILD_COMPILER '$(set -o pipefail; LC_ALL=C cc --version | head -1 || echo "Please use GCC or CLANG compatible compiler")'"
Saben-saben bakal ngasilake teks ekstra, banjur ora ... Asring salah siji opsi bakal tetep kanggo dangu, nanging yen sampeyan poked maneh, sampeyan tansah entuk loro!
Mesthi, strace
Miturut cara, kaya sembarang ajining dhiri strace
luwih seneng ora reproduksi.
Dadi apa sing kedadeyan?
- Utilitas
head
nduweni hak (utawa luwih, malah dipeksa) kanggo nutup saluran sing diwaca sanalika maca nomer garis sing dijaluk. - Penulis program sing ngasilake data (ing kasus iki
cc
) bisa print sawetara garis lan gratis nindakake iki liwat sawetara telponwrite()
. - yen maca bakal duwe wektu kanggo nutup saluran ing sisih sadurunge mburi rekaman ing sisih penulis, banjur penulis bakal nampa kesalahan.
- Program panulis duwe hak loro nglirwakake kesalahan nulis saluran lan nggambarake ing kode completion Panjenengan.
- Amarga instalasi
set -o pipefail
kode completion pipeline bakal non-zero (erroneous) yen asil non-zero saka paling siji unsur, lan banjur bakal bisa|| echo "Please use GCC or CLANG compatible compiler"
.
Bisa uga ana variasi gumantung carane program panulis bisa nganggo sinyal. Contone, program kasebut bisa mandheg kanthi ora normal (kanthi nggawe status terminasi non-nol/error otomatis), utawa write()
bakal ngasilake asil nulis bita luwih sithik tinimbang sing dijaluk lan disetel errno = EPIPE
.
Sapa sing disalahake?
Ing kasus sing diterangake sethitik kabeh. Kesalahan nangani ing cc
(lcc:1.23.20:Sepβ4-2019:e2k-v3-linux) ora keluwih. Ing pirang-pirang kasus, luwih apik kanggo salah ing sisih ati-ati, sanajan iki mbukak cacat dadakan ing boilerplate sing dirancang kanggo prilaku tradisional.
Apa aku kudu?
Salah:
fortune | head -1 && echo "ΠΠΎΠ²Π΅Π·Π»ΠΎ, Π½ΠΎ Π²Ρ ΡΠΈΡΠΊΡΠ΅ΡΠ΅!" || echo "WTF?"
Bener:
-
(fortune && echo "Π£ΡΠΏΠ΅ΡΠ½ΠΎ" || echo "ΠΡΠΈΠ±ΠΊΠ°") | head -1
Ing kene, penutupan awal pipa bakal ditangani dening juru printah nalika nglayani pipa bersarang ("ing" kurung). Patut, yen
fortune
bakal laporan kesalahan ing nulis kanggo saluran ditutup ing status, banjur output|| echo "ΠΡΠΈΠ±ΠΊΠ°"
ora bakal tekan ngendi wae, amarga saluran kasebut wis ditutup. -
fortune | cat - | head -1 && echo "Π£ΡΠΏΠ΅ΡΠ½ΠΎ" || echo "ΠΡΠΈΠ±ΠΊΠ°"
Punika sarana
cat
tumindak minangka damper amarga nglirwakake kesalahanEPIPE
nalika mundur. Iki cukup kanggo kesimpulan saikifortune
cilik (sawetara garis) lan mathuk ing buffer saluran (saka 512 bait kanggo β64K, ing paling OS β₯4K). Yen ora masalah bisa bali.
Cara ngolah kanthi bener EPIPE
lan kesalahan rekaman liyane?
Ora ana solusi sing bener, nanging ana rekomendasi sing gampang:
EPIPE
dibutuhake kudu diproses (lan dibayangke ing status metu) nalika outputting data sing mbutuhake integritas. Contone, sajrone operasi arsip utawa utilitas serep.EPIPE
luwih becik digatekake nalika nampilake informasi lan pesen tambahan. Contone, nalika nampilake informasi babagan opsi--help
utawa--version
.- Yen kode sing dikembangake bisa digunakake ing pipa sadurunge
| head
, banjurEPIPE
Iku luwih apik kanggo nglirwakake, yen ora, iku luwih apik kanggo proses lan nggambarake ing status metu.
Aku pengin njupuk kesempatan iki kanggo ngucapake matur nuwun marang tim
Terusno Camarades, munggah
Π‘ΠΏΠ°ΡΠΈΠ±ΠΎ
KDPV saka
Source: www.habr.com