Комментарии 36
Спасибо, очень интересная статься… но как всегда нужна мера, чтобы не полочалось такого:
# odmget -q «attribute=num and uniquetype=pty/pty/pty» PdAt | sed «s/0-64/0-512/» | odmchange -q «attribute=num and uniquetype=pty/pty/pty» -o PdAt
потом разбираться сложно :)
# odmget -q «attribute=num and uniquetype=pty/pty/pty» PdAt | sed «s/0-64/0-512/» | odmchange -q «attribute=num and uniquetype=pty/pty/pty» -o PdAt
потом разбираться сложно :)
0
Не хотелось бы никого обижать, но что нового привнесла эта статья? Что хотел донести автор? Свой восторг от открытия pipe?
Как бы то ни было, название точно не соответствует содержимому.
Как бы то ни было, название точно не соответствует содержимому.
-3
pipefail — это костыль мешающей работе!
Если утиль ничего не вернула это тоже результат, а не ошибка!
Если утиль ничего не вернула это тоже результат, а не ошибка!
-1
Я бы вообще pipefail по дефолту ставил. Он роняет пайп не когда утиль ничего не вернула, а когда утиль сама вернула ненулевой код возврата, всё правильно делает.
+3
Утиль не может ничего вернуть, выход из main() всегда равен нулю, если не указанно иного и нет ошибки.
К тому, что летает по трубе, это ваще никак не относится.
Если пишешь скрипты, у тебя весь канал должен отрабатывать пустые результаты.
К тому, что летает по трубе, это ваще никак не относится.
Если пишешь скрипты, у тебя весь канал должен отрабатывать пустые результаты.
-1
Окей, смотри.
Каждый бинарник в пайпе возвращает три вещи:
1. exit code
2. stderr
3. stdout
stderr традиционно игнорируется (на самом деле в итоге выдается пользователю)
stdout идёт на вход следующей утилите
exit code — если не ставить опций, то игнорируется для всех команд кроме последней
Ненулевой exit code, и пустой stdout — это разные вещи. Пустой stdout безусловно должен обрабатываться корректно и не является ошибкой, но это так и происходит, независимо от наличия опции pipefail.
Рассмотрим такой пайп:
Если файл foo пустой, то всё будет работать как и в общем случае, ничего не ломается.
Но при отсутствии файла foo команда cat вернёт не только пустой output, но и не нулевой код возврата. И если мы хотим этот случай отличить от пустого файла а- мы должны ставить опцию pipefail, иначе падение команды cat будет проигнорировано.
Каждый бинарник в пайпе возвращает три вещи:
1. exit code
2. stderr
3. stdout
stderr традиционно игнорируется (на самом деле в итоге выдается пользователю)
stdout идёт на вход следующей утилите
exit code — если не ставить опций, то игнорируется для всех команд кроме последней
Ненулевой exit code, и пустой stdout — это разные вещи. Пустой stdout безусловно должен обрабатываться корректно и не является ошибкой, но это так и происходит, независимо от наличия опции pipefail.
Рассмотрим такой пайп:
cat foo | sed 's/abra/cadabra/g'
Если файл foo пустой, то всё будет работать как и в общем случае, ничего не ломается.
Но при отсутствии файла foo команда cat вернёт не только пустой output, но и не нулевой код возврата. И если мы хотим этот случай отличить от пустого файла а- мы должны ставить опцию pipefail, иначе падение команды cat будет проигнорировано.
+1
Так вам и говорят про ситуацию, когда выход из main() не равен нулю.
Не про пустой результат, а про код возврата.
Попробуйте с
Не про пустой результат, а про код возврата.
Попробуйте с
set -o pipefail
сделать (true | cat) && echo True || echo False
, а потом замените true
на false
. В случае с true
будет выведено «True», в случае с false
— «False», но без set -o pipefail
в обоих случаях будет «True». При этом ни true
, ни false
ничего не пишут в stdout+1
Вот там в примере, grep который возвращает 1 в случае нулевого результата,… ну и хрен бы с ним,
сделай так чтоб следующий за ним тоже вернул ноль.
Для полного феншуя, нужно разделять проверку на код возврата и сравнения строк,
не мешать функции strcmp() и математические: <, >, =, !=
сделай так чтоб следующий за ним тоже вернул ноль.
Для полного феншуя, нужно разделять проверку на код возврата и сравнения строк,
не мешать функции strcmp() и математические: <, >, =, !=
-1
grep который возвращает 1 в случае нулевого результата
Да, неудобно. Решается вызовом
Немного некрасиво, но лучше чем без pipefail. Пайпы без pipefail, это как bash-скрипт без «set -e». Это как программа, где каждый оператор заключён в try с пустым блоком catch.
Да, неудобно. Решается вызовом
first-command | (grep "foo" || true) | next-command
Немного некрасиво, но лучше чем без pipefail. Пайпы без pipefail, это как bash-скрипт без «set -e». Это как программа, где каждый оператор заключён в try с пустым блоком catch.
+1
Какие try, catch… юзай PHP/Perl/Ruby при чем тут баш?!
-8
// В zsh есть аналог try-finally с возможностью проигнорировать ошибки (но без полноценного catch).
Вообще‐то в сообщении, на который вы отвечаете, try-catch приводился в качестве аналогии. Ваш ответ соответствует сообщению, на который вы отвечаете, не более, чем абзац выше соответствует вашему сообщению.
Если бы в качестве аналогии было приведено «это как переходить дорогу, никогда не глядя на светофор», вы бы тоже сказали «Какие светофоры… прогуляйся на улице при чем тут баш?!»?
Вообще‐то в сообщении, на который вы отвечаете, try-catch приводился в качестве аналогии. Ваш ответ соответствует сообщению, на который вы отвечаете, не более, чем абзац выше соответствует вашему сообщению.
Если бы в качестве аналогии было приведено «это как переходить дорогу, никогда не глядя на светофор», вы бы тоже сказали «Какие светофоры… прогуляйся на улице при чем тут баш?!»?
+5
Ах да, автор — забыл: document here
grep root < /etc/passwd | mail -s "Thank you" archive@nsa.gov
-2
тогда уж
grep root < /etc/shadow | mail -s "Thank you" archive@nsa.gov
0
Это не document here, это перенаправление входного дескриптора из файла. Document here — это
cat << EOF
blah-blah-blah
EOF
+1
Мне ещё нравится process substitution (башизм, но в, например, zsh он тоже есть). Если есть какая-то программа, принимающая в качестве аргумента файл, можно вместо этого файла подсунуть pipe.
Для примера rsync, которому можно передать файл со списком файлов:
Для примера rsync, которому можно передать файл со списком файлов:
get_file_list() { # все названия выдуманы, совпадения случайны find . -name "*.py" find www echo run } rsync \ -t \ -vv \ --files-from=<(get_file_list) \ . \ $DESTINATION \
+3
Так и не увидел tricks.
Ни слова про контролирование скорости передачи в пайпе, ни про именованные пайпы.
Ни слова про контролирование скорости передачи в пайпе, ни про именованные пайпы.
+9
Ещё один способ получить коды завершения элементов контейнеров
man bash
man bash
PIPESTATUS
An array variable (see Arrays below) containing a list of exit status values from the processes in the most-recently-executed foreground pipeline (which may contain only a single
command).
+3
Таким образом, bash обрабатывает символ конвейера путем системного вызова pipe() для каждого встретившегося символа ‘|’ и выполняет каждую команду в отдельном процессе с использованием соответствующих файловых дескрипторов в качестве входного и выходного потоков.то есть не
все команды в конвейере работают параллельноа только две, причем вторая ждет вывода от первой. Собственно не совсем асинхронно. Процессы то может запущены и параллельно, но работу они делают последовательно, после получения порции данных на вход. Кажется так?
0
Нет. Первая выдала порцию данных, вторая уже может начинать работать. Первая тем временем продолжает генерировать новые данные. Потом через какое-то время данные дойдут и до третьей команды и т.д.
При наличии достаточно больших буферов, и отсутствия узких мест — никакие из процессов не будут ждать, все будут активно работать.
По факту же да, бывает что одна из команд обрабатывает данные медленнее чем другие, поэтому большую часть времени остальные ждут её (причем как те кто перед ней, так и те что после неё). Но всё равно работает быстрее чем если бы мы обрабатывали последовательно.
При наличии достаточно больших буферов, и отсутствия узких мест — никакие из процессов не будут ждать, все будут активно работать.
По факту же да, бывает что одна из команд обрабатывает данные медленнее чем другие, поэтому большую часть времени остальные ждут её (причем как те кто перед ней, так и те что после неё). Но всё равно работает быстрее чем если бы мы обрабатывали последовательно.
0
Кстати, в цитате из ядра нираскрыта самая интересная тема — как собственно передаются данные. Кого волнует инициализация структур, в самом деле.
0
Само ядро никуда данные не передает. см. execute_command_internal (cmd->value.Connection->first, asynchronous, prev, fildes[1], fd_bitmap);
тут `prev` — это файловый дескриптор, stdin для вызываемой программы и является stdout'ом для предыдущей команды.
тут `prev` — это файловый дескриптор, stdin для вызываемой программы и является stdout'ом для предыдущей команды.
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Linux pipes tips & tricks