У меня есть следующий код Python, который работает локально для создания дампа. Я хотел бы докеризовать его без подсказки пароля для подключения к базе данных, когда я использую команду pg_dump, а также я не знаю, что я дам в файле докеры вместо postgres_bin = r"C:\Program Files\PostgreSQL\13\ мусорное ведро
import os
import paramiko
import subprocess
postgres_bin = r"C:\Program Files\PostgreSQL\13\bin"
dump_file = "database_dump.sql"
with open(dump_file, "w") as f:
result = subprocess.call([os.path.join(postgres_bin, "pg_dump"), "-Fp", "-d", "XXX", "-U", "XXX", "-h", "XXX", "-p", "XXX"], stdout=f)
transport.close()
Этот код работает локально. Я хотел бы, чтобы тот же код работал без необходимости указывать пароль в приглашении, которое у меня есть локально.
Как мне это сделать ?
Я обновил свой код ниже. Этот код работает с подсказкой. Но когда я раскомментирую строку с помощью «-w» и env = {'PGPASSWORD': 'secret'}, у меня возникает ошибка, что имя хоста не может быть переведено: неизвестная ошибка сервера.
import os
import paramiko
import subprocess
print("Import has been done !")
postgres_bin = r"C:\Program Files\PostgreSQL\13\bin"
dump_file = "database_dump.sql"
with open(dump_file, "w") as f:
result = subprocess.call([
os.path.join(postgres_bin, "pg_dump"),
"-Fp",
"-d",
"anonymedev",
"-U",
"pgsqladmin",
"-h",
"hostname",
"-p",
"32045",
# '-w'
],
# env = {'PGPASSWORD': 'secret'},
stdout=f
)
Я попробовал это, но не работал. Я думаю, что вы правы, и я не использовал его хорошо. У вас есть пример, пожалуйста?
Вы можете использовать переменные среды PGPASSWORD
или PGPASSFILE
, как описано в документации.
Например, чтобы вывести базу данных «пример» от имени пользователя «postgres» с паролем «secret», я могу написать:
PGHOST=127.0.0.1 \
PGUSER=postgres \
PGPASSWORD=secret \
PGDATABASE=example \
pg_dump
Я могу сохранить пароль в файле вместо использования переменной окружения PGPASSWORD
; в этом случае нам нужно отформатировать файл, как описано в «Файл паролей»:
echo 127.0.0.1:5432:example:postgres:secret
А затем сослаться на этот файл с помощью переменной окружения PGPASSFILE
:
PGPASSFILE=pgpass \
pg_dump -h 127.0.0.1 -U postgres example
Если вы запускаете pg_dump
из Python, то для установки переменной среды вам нужно установить ключи в os.environ
или использовать параметр env
для subprocess.call
.
Использование параметра env
устанавливает среду для этого единственного вызова subprocess.call
, и вы должны явно включить существующие переменные среды, если хотите, чтобы они были видны в дочернем процессе:
with open(dump_file, "w") as f:
result = subprocess.call(
[
os.path.join(postgres_bin, "pg_dump"),
"-Fp",
"-d",
"XXX",
"-U",
"XXX",
"-h",
"XXX",
"-p",
"XXX",
],
env=os.environ | {'PGPASSWORD': 'secret'},
stdout=f,
)
(Обратите внимание, что синтаксис dict union здесь требует Python 3.9 или более поздней версии).
В качестве альтернативы вы можете обновить os.environ
, что сделает переменную доступной для всех последующих подпроцессов:
os.environ['PGPASSWORD'] = 'secret'
with open(dump_file, "w") as f:
result = subprocess.call(
[
os.path.join(postgres_bin, "pg_dump"),
"-Fp",
"-d",
"XXX",
"-U",
"XXX",
"-h",
"XXX",
"-p",
"XXX",
],
stdout=f,
)
Перед "с открытым..." в моем коде я добавил PGPASSWORD=secret, но соединение не работает.
Смотрите обновление к моему ответу.
Спасибо, я добавил это: env = {'PGPASSWORD': 'secret'}, но теперь у меня ошибка, что имя хоста не может быть переведено: неизвестная ошибка сервера. Это работает, когда я не добавляю env = {'PGPASSWORD': 'secret'}. Так что не знаю, откуда проблема.
Хост является удаленным хостом PGAAS
Это может быть ошибка в вашем коде, но чтобы диагностировать ее, мне нужно увидеть фактический код с вашими последними изменениями. Может быть, вы могли бы обновить свой вопрос и добавить его?
Я обновил свой вопрос кодом, который использовал с вашим ответом
Извините, это была моя ошибка! Установка env
на subprocess.call
переопределяет среду процесса, поэтому вы должны явно включать существующие переменные среды. Я обновил ответ здесь двумя альтернативами.
Спасибо ! Я пробовал две возможности. Сначала выдается ошибка: TypeError: неподдерживаемые типы операндов для |: '_Environ' и 'dict'. Второй вариант работает! Есть ли у вас какие-либо советы о том, как я могу защитить его больше о пароле? Моя конечная цель — поместить этот код в приложение flask и докеризовать его. Может быть, жестко закодированный пароль не подходит
Конечно, жестко закодированный пароль — плохая идея. Распространенным решением является чтение пароля из среды — таким образом, его можно прочитать из .env
, предоставленного приложению, или в docker
, или docker-compose
, или через docker run -e PGPASSWORD = "..."
, и т. д.
Вы можете использовать переменные среды
PGPASSWORD
илиPGPASSFILE
, как описано в документации.