Цикл while выполняется только один раз при использовании rsync

#bash #ssh #rsync

#bash #ssh #rsync

Вопрос:

Я создал скрипт bash для переноса сайтов и баз данных с одного сервера на другой: алгоритм:

  1. Проанализируйте .pgpass файл, чтобы создать отдельные дампы для всех указанных Postgres db.
  2. Загрузите указанные дампы на другой сервер через rsync .
  3. Загрузите кучу папок, связанных с каждой базой данных, на другой сервер, также через rsync.

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

Это мой скрипт, который будет запущен на исходном сервере:

 #!/bin/bash

# Read each line of the input file, parse args separated by semicolon (:)
while IFS=: read host port db user pswd ; do
    # Create the dump. No need to enter the password as we're using .pgpass
    pg_dump -U $user -h $host -f "$db.sql" $db
    # Create a dir in the destination server to copy the files into
    ssh user@destination.server mkdir -p webapps/$db/static/media
    # Copy the dump to the destination server
    rsync -azhr $db.sql user@destination:/home/user
    # Copy the website files and folders to the destination server
    rsync -azhr --exclude "*.thumbnails*" webapps/$db/static/media/ user@destination.server:/home/user/webapps/$db/static/media
# At this point I expect the script to continue to the next line, but if exits at the first line
done < $1
 

Это .pgpass, файл для анализа:

 localhost:*:db_name1:db_user1:db_pass1
localhost:*:db_name3:db_user2:db_pass2
localhost:*:db_name3:db_user3:db_pass3
# Many more...
 

И вот как я это называю:

 ./my_script.sh .pgpass
 

На данный момент все работает. Создается первый дамп, который передается на сервер назначения вместе со связанными файлами и папками. Проблема в том, что скрипт завершается там и не будет анализировать другие строки .pgpass . Я закомментировал все строки, связанные с rsync (поэтому скрипт создает только дампы), и он работает правильно, выполняя один раз для каждой строки в скрипте. Как я могу заставить скрипт не завершать работу после выполнения rsync?

Кстати, я использую ssh-аутентификацию на основе ключа для подключения серверов, поэтому сценарий полностью не требует подсказок.

Ответ №1:

Давайте спросим shellcheck:

 $ shellcheck yourscript

In yourscript line 4:
while IFS=: read host port db user pswd ; do
^-- SC2095: ssh may swallow stdin, preventing this loop from working properly.

In yourscript line 8:
    ssh user@destination.server mkdir -p webapps/$db/static/media
    ^-- SC2095: Add < /dev/null to prevent ssh from swallowing stdin.
 

И вот так.

Комментарии:

1. Отлично! Я просто передал параметр -n в ssh, который выполняет то же самое, и сейчас он работает. Спасибо, что поделились shellcheck.