Клиент-серверное взаимодействие
Предусловие: пройдены практические задания предыдущего модуля: «Ручная установка Pangolin» и «Запуск systemd для Pangolin».
В задании «Запуск systemd для Pangolin» мы уже настроили сервис postgresql, который управляет работой СУБД Pangolin.
-
Проверьте, запущен ли сервис:
[student@ServerName ~]$ sudo systemctl status postgresql● postgresql.service - Runners PostgreSQL serviceLoaded: loaded (/etc/systemd/system/postgresql.service; disabled; vendor preset: disabled)Active: active (running) since Wed 2025-05-07 09:50:27 MSK; 8s agoProcess: 11933 ExecStartPre=/bin/mkdir -p /var/run/postgresql (code=exited, status=0/SUCCESS)Process: 11934 ExecStartPre=/bin/chown -R postgres:postgres /var/run/postgresql (code=exited, status=0/SUCCESS)Main PID: 11935 (postgres)Tasks: 10 (limit: 2362)Memory: 28.6MCGroup: /system.slice/postgresql.service├─11935 /usr/pangolin-{major.minor}/bin/postgres -D /pgdata/06/data├─11939 postgres: checkpointer├─11940 postgres: background writer├─11942 postgres: idle sessions terminator├─11943 postgres: walwriter├─11944 postgres: autovacuum launcher├─11945 postgres: autounite launcher├─11946 postgres: integrity check launcher├─11947 postgres: license checker└─11948 postgres: logical replication launcher -
Если сервис неактивен (вывод содержит
Active: inactive (dead)), его необходимо запустить:[student@ServerName ~]$ sudo systemctl start postgresql -
Получите список процессов экземпляра:
[student@ServerName ~]$ ps f -C postgresPID TTY STAT TIME COMMAND11935 ? Ss 0:00 /usr/pangolin-{major.minor}/bin/postgres -D /pgdata/06/data11939 ? Ss 0:00 \_ postgres: checkpointer11940 ? Ss 0:00 \_ postgres: background writer11942 ? Ss 0:00 \_ postgres: idle sessions terminator11943 ? Ss 0:00 \_ postgres: walwriter11944 ? Ss 0:00 \_ postgres: autovacuum launcher11945 ? Ss 0:00 \_ postgres: autounite launcher11946 ? Ss 0:00 \_ postgres: integrity check launcher11947 ? Ss 0:00 \_ postgres: license checker11948 ? Ss 0:00 \_ postgres: logical replication launcherРазбор команды:
ps– утилита для просмотра информации о процессе;f– отображает процессы в виде дерева (родитель-потомки);-C postgres– выбирает процессы с именемpostgres.
Подробнее об опциях
psможно узнать вman ps.Головной процесс (PID 11935) запускает все остальные. Каждый из дочерних процессов выполняет свою функцию – запись журналов, обслуживание кешей, проверку целостности и другие.
-
Для подключения к серверу используется клиент psql. Откройте новый терминал (или вкладку) и выполните:
[student@ServerName ~]$ sudo su - postgres[postgres@ServerName ~]$ psqlpsql (15.5)Type "help" for help.postgres=#Первая команда (
sudo) запускает оболочку Bash от имени пользователяpostgres. Вторая команда запускает клиент psql, в результате чего у вас имеется клиент-серверное соединение. -
Каждое клиентское соединение обслуживается отдельным серверным процессом. Узнайте его PID с помощью функции
pg_backend_pid():postgres=# SELECT pg_backend_pid();pg_backend_pid----------------12105(1 row)Обратите внимание на точку с запятой в конце команды. Она означает, что ввод команды SQL закончен.
А если ее не поставить?
Если точку с запятой не поставить, psql будет ожидать продолжения ввода, что отражается в приглашении
-#:postgres=# SELECT pg_backend_pid()postgres-#Чтобы завершить команду, нужно ввести
;и нажатьEnter, либо отменить ввод комбинациейCtrl+C.Этот механизм позволяет вводить длинные команды SQL, разбивая их на отдельные строки. Только в самом конце длинной команды надо ввести
;. -
Проверьте, что в списке процессов экземпляра появился обслуживающий процесс с полученным PID (в примере это процесс 12105):
postgres=# \! ps f -C postgresPID TTY STAT TIME COMMAND11935 ? Ss 0:00 /usr/pangolin-{major.minor}/bin/postgres -D /pgdata/06/data11939 ? Ss 0:00 \_ postgres: checkpointer11940 ? Ss 0:00 \_ postgres: background writer11942 ? Ss 0:00 \_ postgres: idle sessions terminator11943 ? Ss 0:00 \_ postgres: walwriter11944 ? Ss 0:00 \_ postgres: autovacuum launcher11945 ? Ss 0:00 \_ postgres: autounite launcher11946 ? Ss 0:00 \_ postgres: integrity check launcher11947 ? Ss 0:00 \_ postgres: license checker11948 ? Ss 0:00 \_ postgres: logical replication launcher12105 ? Ss 0:00 \_ postgres: postgres postgres [local] idleМетакоманда
\!позволяет выполнить команду ОС без выхода из клиента psql. Запущенный серверный процесс обеспечивает клиент-серверное взаимодействие с psql.
Этапы взаимодействия клиента и сервера
-
Перезапустите соединение, выполнив команду psql
\си проверьте, изменился ли PID серверного процесса:postgres=# \cYou are now connected to database "postgres" as user "postgres".postgres=# SELECT pg_backend_pid();pg_backend_pid----------------12161(1 row)postgres=# \! ps f -C postgresPID TTY STAT TIME COMMAND11935 ? Ss 0:00 /usr/pangolin-{major.minor}/bin/postgres -D /pgdata/06/data11939 ? Ss 0:00 \_ postgres: checkpointer11940 ? Ss 0:00 \_ postgres: background writer11942 ? Ss 0:00 \_ postgres: idle sessions terminator11943 ? Ss 0:00 \_ postgres: walwriter11944 ? Ss 0:00 \_ postgres: autovacuum launcher11945 ? Ss 0:00 \_ postgres: autounite launcher11946 ? Ss 0:00 \_ postgres: integrity check launcher11947 ? Ss 0:00 \_ postgres: license checker11948 ? Ss 0:00 \_ postgres: logical replication launcher12161 ? Ss 0:00 \_ postgres: postgres postgres [local] idleСтарый серверный процесс (12105) завершен, вместо него запущен новый (12161). Все, что сохранялось в локальной памяти серверного процесса, сброшено. Память клиента psql осталась, так как клиент не рестартовал.
-
Зарегистрируйте в Pangolin новую роль с паролем. Проверьте, пройдет ли успешно процесс аутентификации при входе в сеанс нового пользователя:
postgres=# CREATE USER dbuser1 PASSWORD 'dbuser1';CREATE ROLEpostgres=# \du dbuser1List of rolesRole name | Attributes | Member of-----------+------------+-----------dbuser1 | | {}Метакоманда
\duвыводит список ролей базы данных. Подробнее об этом рассказывается в курсе DBA1 в главе «Авторизация и аутентификация».Подключитесь в сеанс от имени
dbuser1через Unix-сокет:postgres=# \c - dbuser1You are now connected to database "postgres" as user "dbuser1". -
Подключитесь в сеанс от имени
dbuser1через сеть:postgres=# \c - dbuser1 localhostYou are now connected to database "postgres" as user "dbuser1" on host "localhost" (address "::1") at port "5432". -
Подключение установлено. Выйдите из сеанса:
postgres=> \q
Параметры соединения
-
Войдите в сеанс:
[postgres@ServerName ~]$ psqlpsql (15.5)Type "help" for help.postgres=# -
Проверьте, как было установлено соединение:
postgres=# \conninfoYou are connected to database "postgres" as user "postgres" via socket in "/tmp" at port "5432". -
Переподключитесь через
localhost:postgres=# \c - - localhostYou are now connected to database "postgres" as user "postgres" on host "localhost" (address "127.0.0.1") at port "5432".postgres=# \conninfoYou are connected to database "postgres" as user "postgres" on host "localhost" (address "127.0.0.1") at port "5432".SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)Если соединение будет засекреченным, как при сетевом подключении, то команда
\connninfoсообщит об этом –SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off).
Сокеты
-
Вернитесь к подключению через Unix-сокет:
postgres=# \c - - /tmpYou are now connected to database "postgres" as user "postgres" via socket in "/tmp" at port "5432". -
Проверьте наличие файла Unix-сокета в каталоге
/tmp:postgres=# \! ls -la /tmp/.*5432*srwxrwxrwx 1 postgres postgres 0 Nov 8 11:44 /tmp/.s.PGSQL.5432-rw------- 1 postgres postgres 42 Nov 8 11:44 /tmp/.s.PGSQL.5432.lockВыполнена команда
ls -l, предоставляющая подробную информацию о файлах, опция-aпоказывает скрытые файлы и каталоги (начинающиеся с точки).Из ее вывода заметно, что есть файл
/tmp/.s.PGSQL.5432— сокет. Для файлов-сокетов командаls -lперед правами доступаrwxrwxrwxпишет тип файла —s(socket). Файл/tmp/.s.PGSQL.5432.lock– это блокировка, предотвращающая одновременный запуск нескольких экземпляров. -
Проверьте, какие процессы сейчас используют этот сокет:
postgres=# \! lsof /tmp/.s.PGSQL.5432COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEpostgres 11935 postgres 6u unix 0x0000000000000000 0t0 155748 /tmp/.s.PGSQL.5432 type=STREAMpostgres 12943 postgres 7u unix 0x0000000000000000 0t0 159730 /tmp/.s.PGSQL.5432 type=STREAM -
Узнайте, что это за процессы:
postgres=# \! ps -fp 11935UID PID PPID C STIME TTY TIME CMDpostgres 11935 1 0 09:50 ? 00:00:00 /usr/pangolin-{major.minor}/bin/postgres -D /pgdata/06/datapostgres=# \! ps -fp 12943UID PID PPID C STIME TTY TIME CMDpostgres 12943 11935 0 10:44 ? 00:00:00 postgres: postgres postgres [local] idleПервый процесс (11935) – головной процесс экземпляра, второй (12943) – серверный процесс, обслуживающий текущую сессию.
Настройки сервера для сокетов
-
Проверьте, как настроен экземпляр: какие сетевые интерфейсы прослушиваются, номер порта TCP и расположение сокета в файловой системе:
postgres=# \dconfig listen*|port|unix*dir*List of configuration parametersParameter | Value-------------------------+-------listen_addresses | *port | 5432unix_socket_directories | /tmp(3 rows)Где:
\dconfig– метакоманда для просмотра параметров конфигурации сервера и их значений;- шаблон
listen*|port|unix*dir*выбирает параметры, содержащие указанные строки.
-
Проверьте, действительно ли прослушиваются данные порты:
postgres=# \! ss -ln | grep 5432u_str LISTEN 0 294 /tmp/.s.PGSQL.5432 155748 * 0tcp LISTEN 0 294 0.0.0.0:5432 0.0.0.0:*
Информация о сервере
-
Исследуйте содержимое файла
postmaster.pid:postgres=# \! cat $PGDATA/postmaster.pid11935/pgdata/06/data17466006275432/tmp*652803 7readyОбратите внимание на PID (11935). Вы его уже встречали ранее. Сделайте выводы.
-
Получите отчет о статусе головного процесса экземпляра:
postgres=# \! ps -fp $(head -1 $PGDATA/postmaster.pid)UID PID PPID C STIME TTY TIME CMDpostgres 11935 1 0 09:50 ? 00:00:00 /usr/pangolin-{major.minor}/bin/postgres -D /pgdata/06/dataКонструкция
$()— командная подстановка, вместо нее подставляется результат выполненной команды, в данном случаеhead -1(первая строка файла). -
Выйдите из сеанса:
postgres=# \q
Получение информации о сеансе
-
Зайдите в сеанс из-под сессии
postgresв ОС и получите информацию о пользователе в сеансе СУБД Pangolin – текущую БД, сетевой порт TCP и адрес источника соединения:[postgres@ServerName ~]$ psqlpsql (15.5)Type "help" for help.postgres=# SELECT user, current_catalog, inet_server_port(), inet_server_addr();user | current_catalog | inet_server_port | inet_server_addr----------+-----------------+------------------+------------------postgres | postgres | |(1 row)Так как подключение в данной сессии произведено через сокет, функции
inet_server_port()иinet_server_addr()возвращаютNULL. -
Подключитесь через
localhostи проверьте те же параметры:postgres=# \c - - localhostYou are now connected to database "postgres" as user "postgres" on host "localhost" (address "127.0.0.1") at port "5432".postgres=# SELECT user, current_catalog, inet_server_port(), inet_server_addr();user | current_catalog | inet_server_port | inet_server_addr----------+-----------------+------------------+------------------postgres | postgres | 5432 | 127.0.0.1(1 row) -
Подключитесь от имени пользователя
dbuser1и проверьте те же параметры:postgres=# \c postgres dbuser1 localhostYou are now connected to database "postgres" as user "dbuser1".postgres=> SELECT user, current_catalog, inet_server_port(), inet_server_addr();user | current_catalog | inet_server_port | inet_server_addr---------+-----------------+------------------+------------------dbuser1 | postgres | 5432 | 127.0.0.1(1 row) -
Выйдите из сеанса:
postgres=> \q
Библиотека libpq
Клиент psql использует библиотеку libpq для взаимодействия с сервером. Убедимся в этом:
-
Получите путь к исполняемому файлу psql:
[postgres@ServerName ~]$ which psql/usr/bin/psql -
Проверьте, загружается ли библиотека
libpqпри старте этой программы:[postgres@ServerName ~]$ ldd `which psql` | grep libpqlibpq.so.5 => /usr/pangolin/lib/libpq.so.5 (0x00007fcff7ade000) -
В завершение работы выйдите из сеанса
postgres:[postgres@ServerName ~]$ exitlogout
На этом работу с клиентским подключением в Pangolin можно считать завершенной.
Самопроверка
Вопрос 1
В сеансе psql выполнена команда:
postgres=# \! ps f -C postgres
PID TTY STAT TIME COMMAND
986 ? Ss 0:03 /usr/pangolin-\{pangolin-version\}/bin/postgres -D /pgdata/06/data
1085 ? Ss 0:00 \_ postgres: logger
1099 ? Ss 0:00 \_ postgres: checkpointer
1100 ? Ss 0:00 \_ postgres: background writer
1101 ? Ss 0:00 \_ postgres: idle sessions terminator
1247 ? Ss 0:00 \_ postgres: walwriter
1248 ? Ss 0:00 \_ postgres: license checker
1249 ? Ss 0:00 \_ postgres: autovacuum launcher
1250 ? Ss 0:00 \_ postgres: autounite launcher
1251 ? Ss 0:00 \_ postgres: integrity check launcher
1252 ? Ss 0:00 \_ postgres: logical replication launcher
30003 ? Ss 0:00 \_ postgres: postgres postgres [local] idle
Какое число выдаст запрос SELECT pg_backend_pid();, выполненный в том же сеансе psql?
Вопрос 2
В сеансе psql выполнены следующие команды:
postgres=# SHOW enabled_extra_auth_methods;
enabled_extra_auth_methods
----------------------------
scram-sha-256, peer
(1 row)
postgres=# CREATE ROLE test_user PASSWORD 'password';
CREATE ROLE
postgres=# SELECT * FROM pg_hba_file_rules();
line_number | type | database | user_name | address | netmask | auth_method | options | error
-------------+-------+---------------+------------+-----------+-----------------------------------------+---------------+---------+-------
95 | local | {all} | {all} | | | peer | |
97 | host | {all} | {all} | 127.0.0.1 | 255.255.255.255 | scram-sha-256 | |
99 | host | {all} | {all} | ::1 | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | scram-sha-256 | |
102 | local | {replication} | {all} | | | peer | |
103 | host | {replication} | {all} | 127.0.0.1 | 255.255.255.255 | scram-sha-256 | |
104 | host | {replication} | {all} | ::1 | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | scram-sha-256 | |
postgres=# \c - test_user
connection to server on socket "/tmp/.s.PGSQL.5432" failed: FATAL: Peer authentication failed for user "test_user"
Previous connection kept
Каким образом можно обеспечить подключение роли test_user к текущей базе данных в данном сеансе psql? Рассмотрите следующие варианты:
-
Вариант 1. Путем последовательного выполнения следующих действий:
- в файле
pg_hba.confудалить 95-ю строку - в psql выполнить запрос
SELECT pg_reload_conf(); - в psql выполнить команду
\c - test_userи ввести пароль пользователя
- в файле
-
Вариант 2. Путем последовательного выполнения следующих действий:
- в файле
pg_hba.confв 95-й строке изменить значение поляauth_methodнаscram-sha-256 - в psql выполнить запрос
SELECT pg_reload_conf(); - в psql выполнить команду
\c - test_userи ввести пароль пользователя
- в файле
-
Вариант 3. Выполнить в psql команду
\c - test_user localhostи ввести пароль пользователя
Выберите верные варианты.
Вопрос 3
В shell выполнена команда:
ps f -C postgres
PID TTY STAT TIME COMMAND
986 ? Ss 0:03 /usr/pangolin-\{pangolin-version\}/bin/postgres -D /pgdata/06/data
1085 ? Ss 0:00 \_ postgres: logger
1099 ? Ss 0:00 \_ postgres: checkpointer
1100 ? Ss 0:00 \_ postgres: background writer
1101 ? Ss 0:00 \_ postgres: idle sessions terminator
1247 ? Ss 0:00 \_ postgres: walwriter
1248 ? Ss 0:00 \_ postgres: license checker
1249 ? Ss 0:00 \_ postgres: autovacuum launcher
1250 ? Ss 0:00 \_ postgres: autounite launcher
1251 ? Ss 0:00 \_ postgres: integrity check launcher
1252 ? Ss 0:00 \_ postgres: logical replication launcher
30003 ? Ss 0:00 \_ postgres: postgres postgres [local] idle
Какое число выдаст команда shell sudo head -1 $PGDATA/postmaster.pid?
Вопрос 4
В сеансе psql выполнен следующий запрос:
postgres=# SELECT inet_server_addr();
inet_server_addr
-------------
::1
С использованием какого сетевого протокола выполнено подключение в данном сеансе?