
$> set -o pipefail
$> fortune | head -1 > /dev/null && echo "Повезло!" || echo "Вы проиграли"
Повезло!
$> fortune | head -1 > /dev/null && echo "Повезло!" || echo "Вы проиграли"
Вы проигралиಇದು fortune ಇಲ್ಲದೆ ಷರತ್ತುಬದ್ಧ ಪ್ರೋಗ್ರಾಂ exit(rand()).
ನೀನು ವಿವರಿಸಬಲ್ಲೆಯ? ಇಲ್ಲಿ ಏನು ತಪ್ಪಾಗಿದೆ?
ಸಾಹಿತ್ಯ-ಐತಿಹಾಸಿಕ ವಿಷಯಾಂತರ
ಕಾಲು ಶತಮಾನದ ಹಿಂದೆ ಈ ಹೈಸೆನ್ಬಗ್ನ ಪರಿಚಯವಾಯಿತು. ನಂತರ ಫ್ಯಾಕ್ಸ್ನೆಟ್ನಲ್ಲಿ ಗೇಟ್ವೇಗಾಗಿ ಹಲವಾರು ಉಪಯುಕ್ತತೆಗಳನ್ನು ರಚಿಸುವುದು ಅಗತ್ಯವಾಗಿತ್ತು FreeBSD ಅಡಿಯಲ್ಲಿ "ಪ್ಲೇಯಿಂಗ್ ಚೆಕರ್ಸ್". ನಿರೀಕ್ಷೆಯಂತೆ, ನಾನು ಮುಂದುವರಿದ ಮತ್ತು ಸಾಕಷ್ಟು ಅನುಭವಿ ಪ್ರೋಗ್ರಾಮರ್ ಎಂದು ಪರಿಗಣಿಸಿದೆ. ಆದ್ದರಿಂದ, ನಾನು ಎಲ್ಲವನ್ನೂ ಎಚ್ಚರಿಕೆಯಿಂದ ಮತ್ತು ಎಚ್ಚರಿಕೆಯಿಂದ ಸಾಧ್ಯವಾದಷ್ಟು ಮಾಡಲು ಉದ್ದೇಶಿಸಿದೆ, ದೋಷ ನಿರ್ವಹಣೆಗೆ ವಿಶೇಷ ಗಮನ ಕೊಡುತ್ತೇನೆ ...
ಸೆಂಡ್ಮೇಲ್ ಮತ್ತು uucp/uupc ನಲ್ಲಿನ ದೋಷಗಳನ್ನು ನಿಭಾಯಿಸುವ ನನ್ನ ಹಿಂದಿನ ಅನುಭವವು "ಸಂಪೂರ್ಣ ದೋಷ ನಿರ್ವಹಣೆ" ಯಲ್ಲಿ ನನ್ನ ಪರಿಶ್ರಮವನ್ನು ಹೆಚ್ಚಿಸಿದೆ. ಆ ಕಥೆಯ ವಿವರಗಳಿಗೆ ಧುಮುಕುವುದರಲ್ಲಿ ಯಾವುದೇ ಅರ್ಥವಿಲ್ಲ, ಆದರೆ ನಾನು ಈ ಹೈಸೆನ್ಬಗ್ನೊಂದಿಗೆ ಎರಡು ವಾರಗಳ ಕಾಲ 10-14 ಗಂಟೆಗಳ ಕಾಲ ಹೋರಾಡಿದೆ. ಆದ್ದರಿಂದ, ಅದನ್ನು ನೆನಪಿಸಿಕೊಳ್ಳಲಾಯಿತು, ಮತ್ತು ನಿನ್ನೆ ಈ ಹಳೆಯ ಪರಿಚಯವು ಮತ್ತೊಮ್ಮೆ ಭೇಟಿ ಮಾಡಲು ನಿಲ್ಲಿಸಿತು.
TL;DR ಉತ್ತರ
ಉಪಯುಕ್ತತೆ head ಮಾಡಬಹುದು ನಿಂದ ಚಾನಲ್ ಅನ್ನು ಮುಚ್ಚಿ fortune сразу ಅವನು ಮೊದಲ ಸಾಲನ್ನು ಓದಿದ ತಕ್ಷಣ. ಒಂದು ವೇಳೆ fortune ಒಂದಕ್ಕಿಂತ ಹೆಚ್ಚು ಸಾಲುಗಳನ್ನು ಔಟ್ಪುಟ್ ಮಾಡುತ್ತದೆ, ನಂತರ ಅನುಗುಣವಾದ ಕರೆ write() ದೋಷವನ್ನು ಹಿಂತಿರುಗಿಸುತ್ತದೆ ಅಥವಾ ವಿನಂತಿಸಿದಕ್ಕಿಂತ ಕಡಿಮೆ ಬೈಟ್ಗಳು ಔಟ್ಪುಟ್ ಆಗಿವೆ ಎಂದು ವರದಿ ಮಾಡುತ್ತದೆ. ಪ್ರತಿಯಾಗಿ, ಎಚ್ಚರಿಕೆಯ ದೋಷ ನಿರ್ವಹಣೆಯೊಂದಿಗೆ ಬರೆಯಲಾಗಿದೆ fortune ಈ ಪರಿಸ್ಥಿತಿಯನ್ನು ಅದರ ನಿರ್ಗಮನ ಸ್ಥಿತಿಯಲ್ಲಿ ಪ್ರತಿಬಿಂಬಿಸುವ ಹಕ್ಕನ್ನು ಹೊಂದಿದೆ. ನಂತರ ಅನುಸ್ಥಾಪನೆಯ ಕಾರಣ set -o pipefail ಕೆಲಸ ಮಾಡುತ್ತದೆ || echo "Вы проиграли".
ಆದಾಗ್ಯೂ, head ಸಮಯಕ್ಕೆ ಸರಿಯಾಗಿ ಮಾಡದಿರಬಹುದು ಮೊದಲು ಮುಚ್ಚಿ fortune ಡೇಟಾವನ್ನು ಔಟ್ಪುಟ್ ಮಾಡುವುದನ್ನು ಪೂರ್ಣಗೊಳಿಸುತ್ತದೆ. ಆಗ ಅದು ಕೆಲಸ ಮಾಡುತ್ತದೆ && echo "Повезло!".
ನನ್ನ ಇಂದು ಒಂದರಲ್ಲಿ ಒಂದು ಇದೆ :
echo '#define MDBX_BUILD_COMPILER "$(shell set -o pipefail; $(CC) --version | head -1 || echo 'Please use GCC or CLANG compatible compiler')"'ಮಾನವ ಎಂದು ಅನುವಾದಿಸಲಾಗಿದೆ
ಇದು ಇಲ್ಲಿ ಸಾಮಾನ್ಯವಾಗಿದೆ и ಆಯ್ಕೆಯನ್ನು ಬಳಸಿಕೊಂಡು ಕಂಪೈಲರ್ ರೀತಿಯಲ್ಲಿ --version ಅವನು ಯಾರೆಂದು ಅದು ಕೇಳುತ್ತದೆ, ಮತ್ತು ಆಯ್ಕೆಯನ್ನು ಬೆಂಬಲಿಸದಿದ್ದರೆ, ನಂತರ ಸ್ಟಬ್ ಅನ್ನು ಸೇರಿಸಲಾಗುತ್ತದೆ "ದಯವಿಟ್ಟು GCC ಅಥವಾ CLANG ಹೊಂದಾಣಿಕೆಯ ಕಂಪೈಲರ್ ಅನ್ನು ಬಳಸಿ".
ಹಾಗೆ ನೀವು ಅದನ್ನು ಎಲ್ಲಿ ಬೇಕಾದರೂ ಕಾಣಬಹುದು. ಇದು ಬಹಳ ಹಿಂದೆಯೇ ಈ ಸ್ಥಳದಲ್ಲಿ ಕಾಣಿಸಿಕೊಂಡಿತು ಮತ್ತು ಎಲ್ಲೆಡೆ ಸಂಪೂರ್ಣವಾಗಿ ಕೆಲಸ ಮಾಡಿತು (Linux, ಸೋಲಾರಿಸ್, OSX, ಫ್ರೀಬಿಎಸ್ಡಿ, ಇತ್ಯಾದಿ). ಆದರೆ ನಿನ್ನೆ ರಲ್ಲಿ ವೇದಿಕೆಯಲ್ಲಿ ನಾನು ಗಮನಿಸಿದೆ:
#define MDBX_BUILD_COMPILER "lcc:1.23.20:Sep--4-2019:e2k-v3-linux Please use GCC or CLANG compatible compiler"ನಾನೂ, ನನ್ನ ಹಳೆಯ "ಪರಿಚಯವನ್ನು" ನಾನು ತಕ್ಷಣ ಗುರುತಿಸಲಿಲ್ಲ. ಇದಲ್ಲದೆ, ಯೋಜನೆಯನ್ನು ಈಗಾಗಲೇ ಎಲ್ಬ್ರಸ್ನಲ್ಲಿ ಮತ್ತು ಆಲ್ಟ್ ಸೇರಿದಂತೆ ವಿವಿಧ ವಿತರಣೆಗಳ ಅಡಿಯಲ್ಲಿ ಹಲವು ಬಾರಿ ಪರೀಕ್ಷಿಸಲಾಗಿದೆ. ವಿವಿಧ ಕಂಪೈಲರ್ಗಳೊಂದಿಗೆ, GNU ಮೇಕ್ ಮತ್ತು ಬ್ಯಾಷ್ನ ಆವೃತ್ತಿಗಳು. ಆದ್ದರಿಂದ, ಇಲ್ಲಿ ನನ್ನ ತಪ್ಪನ್ನು ನೋಡಲು ನಾನು ಬಯಸುವುದಿಲ್ಲ.
ಸಮಸ್ಯೆಯನ್ನು ಪುನರುತ್ಪಾದಿಸಲು ಮತ್ತು/ಅಥವಾ ಏನಾಗುತ್ತಿದೆ ಎಂಬುದನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಪ್ರಯತ್ನಿಸುವಾಗ, ಹೆಚ್ಚು ವಿಚಿತ್ರವಾದ ಸಂಗತಿಗಳು ಸಂಭವಿಸಲಾರಂಭಿಸಿದವು.
ಆಜ್ಞಾ ಸಾಲಿನ ಕಾಗುಣಿತ:
echo "#define MDBX_BUILD_COMPILER '$(set -o pipefail; LC_ALL=C cc --version | head -1 || echo "Please use GCC or CLANG compatible compiler")'"ಆಗೊಮ್ಮೆ ಈಗೊಮ್ಮೆ ಅದು ಹೆಚ್ಚುವರಿ ಪಠ್ಯವನ್ನು ಉತ್ಪಾದಿಸುತ್ತದೆ, ನಂತರ ಅಲ್ಲ... ಸಾಮಾನ್ಯವಾಗಿ ಆಯ್ಕೆಗಳಲ್ಲಿ ಒಂದು ಸಾಕಷ್ಟು ಸಮಯದವರೆಗೆ ಅಂಟಿಕೊಳ್ಳುತ್ತದೆ, ಆದರೆ ನೀವು ಮುಂದೆ ಚುಚ್ಚಿದರೆ, ನೀವು ಯಾವಾಗಲೂ ಎರಡನ್ನೂ ಪಡೆಯುತ್ತೀರಿ!
ಸಹಜವಾಗಿ, ನಮ್ಮ ಎಲ್ಲವೂ! ಮತ್ತು ಸ್ಟ್ರೇಸ್ ಟೈರೇಡ್ ಅನ್ನು ಟೈಪ್ ಮಾಡಿದ ನಂತರ, ಆದರೆ ಎಂಟರ್ ಅನ್ನು ಒತ್ತಲು ಸಮಯವಿಲ್ಲದ ಕಾರಣ, ನಾನು ನನ್ನ ಹಳೆಯ ಸ್ನೇಹಿತ ಮಿ. ಹೈಸೆನ್ಬಗ್ ಮತ್ತು ಡೆವಲಪರ್ಗಳನ್ನು ಗುರುತಿಸಿದೆ ನಾನೇ 25 ವರ್ಷಗಳ ಹಿಂದೆ ಮತ್ತು ನಾನು ದುಃಖಿತನಾಗಿರಲು ಮತ್ತು ಈ ಟಿಪ್ಪಣಿಯನ್ನು ಬರೆಯಲು ನಿರ್ಧರಿಸಿದೆ 😉
ಮೂಲಕ, ಯಾವುದೇ ಸ್ವಾಭಿಮಾನಿಯಂತೆ , ಅಡಿಯಲ್ಲಿ 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
