Я написал скрипт bash, который выполняет частичную синхронизацию из удаленной промежуточной базы данных в базу данных разработки на локальном компьютере (мой Macbook). Сценарий сначала выгружает определенные таблицы из промежуточной базы данных (обычно через туннель SSH) в локальные файлы .sql, а затем выполняет эти файлы .sql по отношению к локальной базе данных. Вот сценарий (некоторые таблицы переименованы для защиты виновных):
rm -rf export/
mkdir export
set -e # abort if any command in the script fails
abort() {
echo $1
exit 1
}
dump_table() {
echo "Dumping to $1.sql..."
pg_dump $DATABASE_URL -t $1 --data-only > export/$1.sql
}
[ -z "$DATABASE_URL" ] && abort "usage: DATABASE_URL=postgres://un:pw@localhost:55555/dbname sh bin/importdb.sh"
echo "_structure.sql..."
pg_dump $DATABASE_URL -s > export/_structure.sql
dump_table events
dump_table users
dump_table attendees
dump_table orders
dump_table admissions
dump_table teams
# etc...
echo ""
echo "Done with dump from staging!"
echo "Starting local import..."
# Prepend all dumpfiles with the ON_ERROR_STOP flag so the script will abort on error
for f in export/*.sql; do ex -sc '1i|\set ON_ERROR_STOP on' -cx $f; done
dropdb cello_development
createdb cello_development
psql -d cello_development -f export/_structure.sql
# Because we're only importing certain tables, we first need to remove
# a bunch of FKs so that references to un-imported tables are ignored.
psql -d cello_development -c "ALTER TABLE users DROP CONSTRAINT fk_rails_047fa7c340"
psql -d cello_development -c "ALTER TABLE users DROP CONSTRAINT fk_rails_752aed9fe5"
psql -d cello_development -c "ALTER TABLE events DROP CONSTRAINT fk_rails_e1c8c23245"
psql -d cello_development -c "ALTER TABLE events DROP CONSTRAINT fk_rails_1a56b1500c"
psql -d cello_development -c "ALTER TABLE events DROP CONSTRAINT fk_rails_ae012fe18a"
psql -d cello_development -c "ALTER TABLE events DROP CONSTRAINT fk_rails_95c0269b21"
# etc...
echo "events..."
psql -d cello_development -f export/events.sql
echo "users..."
psql -d cello_development -f export/users.sql
echo "attendees..."
psql -d cello_development -f export/attendees.sql
echo "orders..."
psql -d cello_development -f export/orders.sql
echo "admissions..."
psql -d cello_development -f export/admissions.sql
echo "teams..."
psql -d cello_development -f export/teams.sql
# etc...
echo ""
echo "Done with local db import!"
Я запускаю этот сценарий, сначала открыв туннель ssh, чтобы я мог получить доступ к удаленной (исходной) базе данных, затем запустив сценарий сDATABASE_URL
env var set. Как вы можете видеть, нет ничего необычного в том, как я вызываю скрипт:
# In one window, open an SSH tunnel so I can access the source db
ssh -NTL 55555:cello-staging.rds.amazonaws.com:5432 ubuntu@staging.cello.com
# In second window, run the script with DATABASE_URL set
DATABASE_URL=postgres://un:pw@localhost:55555/cello_staging sh bin/importdb.sh
Некоторые из этих таблиц большие (4 м + строки), поэтому выполнение сценария в целом может занять пару часов. (Да, я уверен, что есть лучшие способы заполнить базу данных dev.)
Моя проблема заключается в следующем : часто (~ 60% времени) скрипт завершается ошибкой с ошибками, которые предполагают, чточасть заявления "пропущена". Один пример:
# The failure message:
-bash: mp_table: command not found
# The statement at that line in the script:
dump_table admissions
Другой пример:
# The failure message:
bin/importdb.sh: line 65: port/admissions.sql: No such file or directory
# The statement at that line in the script:
psql -d cello_development -f export/admissions.sql
Ошибки соответствуют тому, что я увидел бы, если бы я запустил оператор в этой строке, без первые два символа (всегда ровно два ведущих символа). Например, если я независимо выполню оператор dump_table admissions
(при условии, что определена функция dump_table
), я ожидаю, что он завершится успешно;но если я независимо запускаю оператор mp_table admissions
, я вижу то же сообщение об ошибке, что и выше.
Сбои, как правило, происходят сразу после пары особенно больших табличных операций. Но это касается не всех сравнительно больших таблиц.
Мое лучшее предположение состоит в том, что, так или иначе, выполняемые дорогостоящие операции с БД postgres вызывают путаницу в скрипте bash и иногда «пропускают» символы в последующем выражении.
Мои вопросы:
- Как бы вы решили эту проблему? когда оператор в вашем bash-скрипте (иногда) перед выполнением (иногда) изменяется / сокращается?
- При выполнении bash-скрипта возможно ли, чтобы побочные эффекты более ранних операторов каким-то образом влияли на формулировку последующих операторов вscript?
- Возможно ли, что команды
psql
& pg_dump
, которые я выполняю, взаимодействуют с содержимым вызывающего их скрипта?
Context: I 'м на MacOS 10.14, используя iTerm2. Локальный сервер БД - Postgres v9.6.
Редактировать 1: Ни при каких условиях сам скрипт не изменяется. Он зарегистрирован в Git, никаких изменений не видно, он находится на моем локальном компьютере, ни один пользователь не должен иметь доступа для внесения изменений в файл, кроме меня.
Редактировать 2: Переписано, чтобы включитьзапускается полный скрипт, а также полная команда, которую я использую для его запуска.