$> set -o pipefail
$> fortune | head -1 > /dev/null && echo "Повезло!" || echo "Вы проиграли"
Повезло!
$> fortune | head -1 > /dev/null && echo "Повезло!" || echo "Вы проиграли"
Вы проиграли
இது fortune
நிபந்தனை நிரல் இல்லாமல் exit(rand())
.
உன்னால் விளக்க முடியுமா? இங்கே என்ன தவறு?
பாடல்-வரலாற்று விலகல்
நான் முதன்முதலில் இந்த ஹைசன்பக் உடன் கால் நூற்றாண்டுக்கு முன்பு அறிமுகமானேன். பின்னர் FaxNET இல் நுழைவாயிலுக்கு பல பயன்பாடுகளை உருவாக்குவது அவசியம்
செண்ட்மெயில் மற்றும் 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
அவர் யார் என்று அது கேட்கிறது, மேலும் விருப்பம் ஆதரிக்கப்படவில்லை என்றால், ஒரு குட்டை செருகப்படும் "தயவுசெய்து GCC அல்லது CLANG இணக்கமான கம்பைலரைப் பயன்படுத்தவும்".
போன்ற
#define MDBX_BUILD_COMPILER "lcc:1.23.20:Sep--4-2019:e2k-v3-linux Please use GCC or CLANG compatible compiler"
வெளிப்படையாக, எனது பழைய "அறிமுகத்தை" நான் உடனடியாக அடையாளம் காணவில்லை. மேலும், திட்டம் ஏற்கனவே எல்ப்ரஸில் பல முறை சோதிக்கப்பட்டது மற்றும் Alt உட்பட பல்வேறு விநியோகங்களின் கீழ். பல்வேறு கம்பைலர்களுடன், குனு மேக் மற்றும் பாஷின் பதிப்புகள். எனவே, எனது தவறை நான் இங்கு பார்க்க விரும்பவில்லை.
சிக்கலை மீண்டும் உருவாக்க முயற்சிக்கும் போது மற்றும்/அல்லது என்ன நடக்கிறது என்பதைப் புரிந்து கொள்ளும்போது, மேலும் விசித்திரமான விஷயங்கள் நடக்கத் தொடங்கின.
கட்டளை வரி எழுத்துப்பிழை:
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 பைட்டுகளில் இருந்து ≈64K வரை, பெரும்பாலான OS ≥4K இல்). இல்லையெனில் பிரச்சனை மீண்டும் வரலாம்.
சரியாக செயலாக்குவது எப்படி EPIPE
மற்றும் பிற பதிவு பிழைகள்?
சரியான தீர்வு எதுவும் இல்லை, ஆனால் எளிய பரிந்துரைகள் உள்ளன:
EPIPE
தேவையான செயலாக்கப்பட வேண்டும் (மற்றும் வெளியேறும் நிலையில் பிரதிபலிக்கிறது) ஒருமைப்பாடு தேவைப்படும் தரவை வெளியிடும் போது. எடுத்துக்காட்டாக, காப்பகங்கள் அல்லது காப்புப் பிரதி பயன்பாடுகளின் செயல்பாட்டின் போது.EPIPE
புறக்கணிப்பது நல்லது தகவல் மற்றும் துணை செய்திகளைக் காண்பிக்கும் போது. உதாரணமாக, விருப்பங்கள் பற்றிய தகவலைக் காண்பிக்கும் போது--help
அல்லது--version
.- உருவாக்கப்படும் குறியீட்டை முன்பு ஒரு பைப்லைனில் பயன்படுத்தலாம்
| head
, பின்னர்EPIPE
புறக்கணிப்பது நல்லது, இல்லையெனில் செயலாக்க மற்றும் வெளியேறும் நிலையில் பிரதிபலிக்க நல்லது.
அணிகளுக்கு எனது நன்றியைத் தெரிவிக்க இந்த வாய்ப்பைப் பயன்படுத்த விரும்புகிறேன்
தோழிகளே, தொடருங்கள்
Спасибо
இருந்து KDPV
ஆதாரம்: www.habr.com