Как заставить set -o pipefail выполнять первую команду в pipe

Один из способов сделать это - использовать команду rfcomm bind ... .

используйте сканирование bluetoothctl и выполните сопряжение целевого устройства, затем свяжите последовательное устройство с:

sudo rfcomm bind 0 C9:5B:CE:A4:97:C7

, чтобы оно создавало устройство как

ls /dev/rfcomm0

, затем вы можете использовать любой инструмент (например, dd ) для записи / читать данные из этого канала.

Когда закончите, вы можете использовать для освобождения:

rfcomm release 0

и bluetoothctl , чтобы отключить / разорвать пару с устройством.

1
16.02.2016, 22:12
2 ответа

set -o pipefail errexit действительно предотвращает выполнение последующих команд, но это вам не помогает, потому что вы не пытаетесь предотвратить выполнение следующей команды. В трубопроводе производитель | Команды потребителя , производителя и потребителя выполняются параллельно . Вы не можете предотвратить запуск потребителя в случае отказа производителя , потому что, если не считать случайного совпадения времени, он уже запустился.

Если возможны только две возможности: « потребитель преуспевает и производит непустой вывод» и « потребитель терпит неудачу и не производит никакого вывода», вы можете использовать ifne ] из moreutils Джои Хесса .

producer | ifne consumer

Я не думаю, что это сработает в вашем случае - совпадения строк могут не оказаться (ложноотрицательные, и вы получите устаревшие данные), соединение с базой данных может быть потеряно посередине (ложное срабатывание и получить усеченные данные).

Если вам нужно узнать, преуспел ли производитель, вам нужно дождаться его завершения, прежде чем запускать потребителя. А поскольку потребителя еще нет, нужно что-то сохранить вывод.

Если вывод не содержит нулевых байтов и не слишком велик, вы можете сохранить его в переменной оболочки.

output=$(producer); producer_status=$?
if [ $producer_status -ne 0 ]; then
  echo >&2 "Producer failed with status $producer_status"
  exit $producer_status
fi
printf '%s\n' "$output" | consumer

В ksh93, bash или zsh эта последняя строка может быть упрощена до consumer <<< "$ output" .

Обратите внимание, что подстановка команд удаляет завершающие символы новой строки. Если уместны завершающие пустые строки, обходной путь состоит в том, чтобы изменить первую строку на

output=$(producer; echo a); producer_status=$?; output=${output%?}

. Если вывод потенциально слишком велик или может содержать нулевые байты, сохраните его во временном файле.

2
27.01.2020, 23:36

Как сказал DopeGhoti, pipefail ... просто означает, что ошибка в любой точке конвейерной цепочки будет сохранена для кода выхода [конвейера].

Чтобы сценарий завершился в случае ошибки, используйте set -e .

Чтобы предотвратить создание файла, создайте временный и переименуйте его в случае успеха, а именно:

set -e 
psql $PG_HOST -At -F$'\t' -c \
    "SELECT * FROM mytable"  >  /tmp/mytable.txt~
                          # ^^^ cf. Useless Use of Cat
mv /tmp/mytable.txt~ /tmp/mytable.txt

Я всегда использую make для такого рода вещей, потому что он останавливается при ошибке и позволяет мне создавать перезапускаемые конвейеры.

0
27.01.2020, 23:36

Теги

Похожие вопросы