У меня есть следующий скрипт:
#!/bin/bash -e
set -e
DATA_DIR=/home/admin/backup_avl_historico/data
DB_HOST=myHost
DB_USER=myPass
#extract table list
logger 'Extracting Table List'
psql -h $DB_HOST -U $DB_USER -c "select table_name from information_schema.tables where table_name like 'avl_historico_%';" -t -o $DATA_DIR/tables.list
array=($(wc -l $DATA_DIR/tables.list))
logger ''$array
total_tables=${array[0]}
logger 'Total tables: '$total_tables
#Get max date
max_date=$(psql -h $DB_HOST -U $DB_USER -t -c "select now() - interval '12 months'")
logger 'Max date: '$max_date
array=($max_date)
date=${array[0]}
logger 'Only date: '$date
#Dump each table
while read table_name
do
logger 'looping...'
if [ ! -z "$table_name" ]; then
logger 'Processing table '$table_name
output=${table_name}_pre_${date}.csv
psql -h $DB_HOST -U $DB_USER -t -F , -c "COPY (select * from reports.$table_name where fecha < '$max_date') TO STDOUT WITH CSV" -o ${DATA_DIR}/$output
if [ -f ${DATA_DIR}/$output ];then
if test -s ${DATA_DIR}/$output
then
logger 'Deleting records'
psql -h $DB_HOST -U $DB_USER -c "delete from reports.$table_name where fecha < '$max_date'"
logger 'Gzipping '$output
pigz ${DATA_DIR}/$output
logger 'Moving to S3'
aws s3 mv ${DATA_DIR}/$output.gz s3://my-bucket/avl_historico/
logger 'Vacuuming table'
psql -h $DB_HOST -U $DB_USER -c "vacuum full analyze reports.$table_name"
else
rm ${DATA_DIR}/$output
fi
fi
fi
done < $DATA_DIR/tables.list
Проблема, с которой я столкнулся, заключается в том, что когда PostgreSQL завершает работу оператора со следующей ошибкой:
ERROR: canceling statement due to lock timeout
Весь скрипт прерывается и не продолжается в следующей итерации do
цикла.
Буду признателен за любые идеи о том, как избежать этого условия выхода, так что скрипт может просто пропустить одну итерацию, но продолжить с остальными.
решение1
Если вы хотите, чтобы ваш скрипт выполнил все команды, игнорируя любые сбои, удалите оба -e
флага. С другой стороны, если вы все еще хотите завершить скрипт в случае ошибки, но хотите поймать определенную (PostgreSQL в вашем случае), оставьте только один из флагов -e
, неважно, какой именно, но личные предпочтения на скрипте, а не на shebang, и способ поймать ошибку — добавить ||
(логическое ИЛИ) в конец команды, завершающейся с не 0. Что это ||
делает, так это если код выхода предыдущей команды не 0, выполните следующее:
psql -h $DB_HOST -U $DB_USER -c "delete from reports.$table_name where fecha < '$max_date'" || true
Приведенный выше пример будет молча перехватывать psql
ненулевые коды выхода и продолжать работу, вы можете заменить команду true
на что угодно (записать ошибку, подождать некоторое время и т. д.), просто убедитесь, что она завершается с 0, иначе вы окажетесь в той же ситуации. Команда true
вообще ничего не делает, она просто завершается с кодом 0.