Скрипт bash иногда «пропускает» первые два символа оператора. Как устранить неполадки? - PullRequest
2 голосов
/ 05 ноября 2019

Я написал скрипт 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: Переписано, чтобы включитьзапускается полный скрипт, а также полная команда, которую я использую для его запуска.

1 Ответ

1 голос
/ 08 ноября 2019

Я не понимаю, что могло бы сделать это, но у меня есть пара предложений по устранению неполадок / их устранению.

  • Мне действительно кажется, что что-то крадет информацию из оболочки,Попробуйте перенаправить ввод для команд до возникновения проблемы:

    pg_dump $DATABASE_URL -s > export/_structure.sql </dev/null
    
    dump_table events </dev/null
    dump_table users </dev/null
    ...etc
    

    Если это не позволяет, вы можете попытаться удалить некоторые из перенаправлений, пока не сузите, какие команды вызываютпроблема. Или вы могли бы просто оставить их всех там ...

    Если это не не остановит это, то я еще более озадачен, чем сейчас.

  • Вы также можете попробовать обернуть весь скрипт (кроме строки shebang) в какой-то блок оболочки с явным выходом в конце - что-то вроде if true; then ... exit; fi или даже просто { ... exit; }. Это заставит оболочку прочитать и проанализировать весь блок перед выполнением любого из него (и завершить работу, прежде чем пытаться выполнить что-либо после него), поэтому, если что-то мешает с файлом или дескриптором файла или чем-то еще, это не имеет значения:

    #!/bin/bash
    if true; then    # Workaround to avoid script reading weirdness
        rm -rf export/
        mkdir export
    
        ...
    
        exit
    fi
    

Кстати, я рекомендую использовать правильную строку shebang в начале скрипта, сделать его исполняемым (chmod +x bin/importdb.sh) и затем запускаться напрямую без команды sh. По сути, автор сценария (через сам сценарий) должен определить, на каком языке / диалекте и т. Д. Сценарий, в котором он написан, а не лицо (/ внешний сценарий / запись cron / что-либо еще), выполняющее его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...