$> set -o pipefail
$> fortune | head -1 > /dev/null && echo "Повезло!" || echo "Вы проиграли"
Повезло!
$> fortune | head -1 > /dev/null && echo "Повезло!" || echo "Вы проиграли"
Вы проиграли
энд fortune
нөхцөлт хөтөлбөргүйгээр exit(rand())
.
Чи тайлбарлаж чадах уу? энд юу болоод байна?
Уянгын-түүхийн ухралт
Би энэ Хэйзенбугтай дөрөвний нэг зууны өмнө анх танилцсан. Дараа нь FaxNET-ийн гарцын хувьд хэд хэдэн хэрэгслүүдээр дамжуулан үүсгэх шаардлагатай болсон
Өмнө нь sendmail болон 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')"'
Хүнээр орчуулсан
Энэ нь энд нийтлэг байдаг --version
Энэ нь түүнийг хэн болохыг асууж, хэрэв энэ сонголтыг дэмжихгүй бол stub оруулна "GCC эсвэл CLANG нийцтэй хөрвүүлэгчийг ашиглана уу".
Дуртай
#define MDBX_BUILD_COMPILER "lcc:1.23.20:Sep--4-2019:e2k-v3-linux Please use GCC or CLANG compatible compiler"
Үнэнийг хэлэхэд, би хуучин "танилаа" шууд таньсангүй. Түүгээр ч зогсохгүй уг төслийг Эльбрус дээр олон удаа туршиж үзсэн бөгөөд Alt зэрэг олон янзын хуваарилалтад хамрагдсан. Төрөл бүрийн хөрвүүлэгч, GNU Make болон bash хувилбаруудтай. Тиймээс би энд өөрийнхөө алдааг харахыг хүсээгүй.
Асуудлыг дахин гаргах эсвэл юу болж байгааг ойлгохыг оролдох үед илүү хачирхалтай зүйлс тохиолдож эхлэв.
Тушаалын мөрийн үсэг:
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?"
Зөв:
-
(fortune && echo "Успешно" || echo "Ошибка") | head -1
Энд хоолойг эрт хаахыг үүрлэсэн дамжуулах хоолойд ("хашилтанд") засвар үйлчилгээ хийх үед командын орчуулагч хариуцна. Үүний дагуу хэрэв
fortune
статусын хаалттай суваг руу бичих алдааг мэдээлэх болно, дараа нь гаралт|| echo "Ошибка"
Энэ суваг аль хэдийн хаагдсан тул хаашаа ч хүрэхгүй. -
fortune | cat - | head -1 && echo "Успешно" || echo "Ошибка"
Хэрэгсэл нь энд байна
cat
алдааг үл тоомсорлодог тул сааруулагчийн үүрэг гүйцэтгэдэгEPIPE
татан буулгах үед. Энэ нь одоо дүгнэлт хийхэд хангалттайfortune
жижиг (хэд хэдэн мөр) ба сувгийн буферт (512 байтаас ≈64К хүртэл, ихэнх үйлдлийн системд ≥4K) багтдаг. Үгүй бол асуудал буцаж болзошгүй.
Хэрхэн зөв боловсруулах вэ EPIPE
болон бусад бичлэгийн алдаа?
Ганц зөв шийдэл байхгүй, гэхдээ энгийн зөвлөмжүүд байдаг:
EPIPE
шаардлагатай боловсруулах ёстой (мөн гарах төлөвт тусгагдсан) бүрэн бүтэн байдлыг шаарддаг өгөгдлийг гаргах үед. Жишээлбэл, архивлагч эсвэл нөөцлөх хэрэгслийг ажиллуулах явцад.EPIPE
үл тоомсорлох нь дээр мэдээлэл болон туслах мессежийг харуулах үед. Жишээлбэл, сонголтуудын талаархи мэдээллийг харуулах үед--help
буюу--version
.- Хэрэв боловсруулж буй кодыг өмнө нь дамжуулах хоолойд ашиглаж болно
| head
Дараа ньEPIPE
Үүнийг үл тоомсорлох нь дээр, эс тэгвээс гарах төлөвийг боловсруулж, тусгах нь дээр.
Энэ завшааныг ашиглаад багуудад баярласнаа илэрхийлмээр байна
Цаашдаа үргэлжлүүлээрэй Камарадууд, дээшээ
Спасибо
KDPV-аас
Эх сурвалж: www.habr.com