run PostgreSQL by hands
Раз в год (или около того) мне нужно запустить PostgreSQL с целью поразрабатывать что-нибудь. За то время что я его не использую знания выветриваются, так что на будущее я делаю эту заметку, в основном для себя.
Запускать PostgreSQL можно разными способами, вот два самых распространенных:
- использовать docker
- поставить пакет
Оба способа немного магические. Контейнеры стараются быть удобными и покрывать как можно больше функциональности, что выливается в адские entrypoint’ы на bash с обратным удобству эффектом. Пакеты в распространенных дистрибутивах тоже содержат не мало магии, ведь они обычно (как минимум) инициализируют директорию с данными СУБД и запускают её сервис.
В nixos тоже есть пакет для PostgreSQL, но он не управляет ни запуском, ни процессом инициализации. Так что полезно помнить как работать руками.
Если вы уже собрались ругать nixos за это то вам стоит знать что эти “сайдэффекты” вынесены в отдельную сущность, которая называется “services”.
В моём случае в корне каждого проекта есть файл shell.nix
с примерно таким содержимым:
with import <nixpkgs> {}; stdenv.mkDerivation { name = "shell"; buildInputs = [ go postgresql ]; }
Когда мне нужно разрабатывать этот проект я делаю cd
в директорию с кодом и запускаю nix-shell
, после чего указанные buildInputs
становятся доступны внутри запустившегося bash
.
Т.к. я мало чего помнил о том с какими флагами нужно запускать PostgreSQL чтобы добиться желаемого и каков должен быть порядок действий то я подумал что было бы неплохо составить представление о том насколько дружелюбен PostgreSQL к пользователю в 2019 году. Начнём с самого начала, у нас есть установленные бинарники PostgreSQL и надо его запустить.
Пробуем просто:
$ postgres postgres does not know where to find the server configuration file. You must specify the --config-file or -D invocation option or set the PGDATA environment variable.
Не получилось, хотя можно было создать директорию для данных внутри текущей автоматически. Хорошо, сделаем это сами:
Скажу сразу: это ошибочный путь, смотрите далее.
$ mkdir data $ postgres -D data postgres: could not access the server configuration file ".../data/postgresql.conf": No such file or directory
Подозрительно, PostgreSQL хочет чтобы ему положили конфиг. Проверяем --help
, не находим какого-либо флага про генерацию дефолтного конфига и ищем его гуглом, находя sample на github, его и подкладываем:
$ curl -Ls https://raw.githubusercontent.com/postgres/postgres/master/src/backend/utils/misc/postgresql.conf.sample > data/postgresql.conf $ postgres -D data LOG: skipping missing configuration file ".../data/postgresql.auto.conf" FATAL: data directory ".../data" has group or world access DETAIL: Permissions should be u=rwx (0700).
Конфигурацию у нас приняли, но теперь сервису не нравятся права на директорию с данными. У меня были установлены drwxr-xr-x
, т.е. 755
.
Здесь хочется сказать пару слов про сервисы, которые считают админа/пользователя идиотом. Я понимаю чем это вызвано, раньше сервисы настраивали руками и было просто упустить что-нибудь и получить нежелательный сайдэффект в виде чтения данных людьми, которым их читать не нужно.
Сегодня ситуация иная. Правами чаще всего управляют через пакетный менеджер, руками редко нужно что-то делать и эти проверки только мешают. На мой взгляд сегодня их все можно классифицировать как не фатальные и просто показывать warning.
А те кто эти ворнинги будет игнорировать (и таки прострелит себе ноги) сам виноват.
В данном случае сообщение о не правильных правах меня насторожило и я вспомнил что раньше директорию для хранения данных PostgreSQL нужно было как-то инициализировать. Сходил в гугл и вернулся с:
$ pg_ctl initdb --pgdata=data The files belonging to this database system will be owned by user "user". This user must also own the server process. The database cluster will be initialized with locale "en_US.UTF-8". The default database encoding has accordingly been set to "UTF8". The default text search configuration will be set to "english". Data page checksums are disabled. creating directory data ... ok creating subdirectories ... ok selecting default max_connections ... 100 selecting default shared_buffers ... 128MB selecting dynamic shared memory implementation ... posix creating configuration files ... ok running bootstrap script ... ok performing post-bootstrap initialization ... ok syncing data to disk ... ok WARNING: enabling "trust" authentication for local connections You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb. Success. You can now start the database server using: pg_ctl -D data -l logfile start
Нам предлагают запустить СУБД через pg_ctl
, но в этом случае процесс уйдёт в бэкграунд, а это совсем не то чего я хочу для разработки.
Много открытых терминалов не является для меня проблемой, но это может быть удобно если этот же терминал хочется использовать ещё для чего-нибудь.
Так что:
$ postgres -D data LOG: database system was shut down at 2019-02-25 17:30:27 UTC LOG: MultiXact member wraparound protections are now enabled LOG: autovacuum launcher started LOG: database system is ready to accept connections
Сервер у нас есть и он слушает на 127.0.0.1:5432/tcp
. Но это ещё не всё, если попробовать запустить клиент:
$ psql psql: could not connect to server: No such file or directory Is the server running locally and accepting connections on Unix domain socket "/tmp/.s.PGSQL.5432"?
Он почему-то хочет соединяться с базой только по unix socket, что конечно хорошо, ещё бы логика по которой клиент ломится по unix socket была консистентна с логикой сервера…
Так что нужно ещё явно указать хост:
$ psql -h 127.0.0.1 psql: FATAL: database "user" does not exist
Что тут у нас? Базы данных для вашего пользователя нет?
В дистрибутивах её обычно создаёт специальный postinstall скрипт. Так что придётся проделать ещё вот что:
$ createdb -h 127.0.0.1 delirium
Теперь можно соединяться:
$ psql -h 127.0.0.1 -d delirium psql (9.6.11) Type "help" for help. delirium=# help You are using psql, the command-line interface to PostgreSQL. Type: \copyright for distribution terms \h for help with SQL commands \? for help with psql commands \g or terminate with semicolon to execute query \q to quit delirium=# \q
вывод
PostgreSQL не блещет удобством для пользователя, но указанные мною шероховатости могут быть сглажены со временем. Хотя стоит отдать должное, он далеко не худший в этом плане(вы пробовали запустить nginx от непривилегированного пользователя?).