Практикум
Клиент - серверное взаимодействие
-
Проверьте, запущен ли серве
[student@p620 ~]$ sudo systemctl status postgresql ● postgresql.service - Runners PostgreSQL service
Loaded: loaded (/etc/systemd/system/postgresql.service; enabled; vendor preset: disabled)
Active: active (running) since Fri 2024-11-08 11:27:25 MSK; 12min ago
Main PID: 806 (postgres)
Tasks: 11 (limit: 4652)
Memory: 63.2M
CPU: 1.468s
CGroup: /system.slice/postgresql.service
├─ 806 /usr/pangolin-6.2.0/bin/postgres -D /pgdata/06/data
├─ 901 "postgres: logger " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""
├─ 905 "postgres: checkpointer " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""
├─ 906 "postgres: background writer " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""
├─ 918 "postgres: walwriter " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""
├─ 920 "postgres: autovacuum launcher " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""
├─ 921 "postgres: autounite launcher " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""
├─ 922 "postgres: integrity check launcher " "" "" "" "" "" "" "" "" "" "" "" "" "" ""
└─ 923 "postgres: logical replication launcher " "" "" "" "" "" "" "" "" "" "" "" "" -
Если вместо приведенного выше вывода видите следующее:
[student@p620 ~]$ sudo systemctl status postgresql ○ postgresql.service - Runners PostgreSQL service
Loaded: loaded (/etc/systemd/system/postgresql.service; enabled; vendor preset: disabled)
Active: inactive (dead) since Fri 2024-11-08 11:42:07 MSK; 2s ago
Process: 806 ExecStart=/bin/bash -i -c /usr/pangolin-6.2.0/bin/postgres -D /pgdata/06/data
(code=exited, status=0/SUCCESS)
Main PID: 806 (code=exited, status=0/SUCCESS)
CPU: 1.749sто необходимо запустить сервер:
[student@p620 ~]$ sudo systemctl start postgresql
-
Получите список процессов экземпляра:
[student@p620 ~]$ ps f -C postgres
PID TTY
9675 ?
9699 ?
9700 ?
9701 ?
STAT TIME COMMAND
Ss 0:00 /usr/pangolin-6.2.0/bin/postgres -D /pgdata/06/data
Ss 0:00 \_ postgres: logger
Ss 0:00 \_ postgres: checkpointer
Ss 0:00 \_ postgres: background writer
9703 ?
9704 ?
9705 ?
9706 ?
9707 ?
9708 ?
9709 ?
Ss 0:00 \_ postgres: idle sessions terminator
Ss 0:00 \_ postgres: walwriter
Ss 0:00 \_ postgres: license checker
Ss 0:00 \_ postgres: autovacuum launcher
Ss 0:00 \_ postgres: autounite launcher
Ss 0:00 \_ postgres: integrity check launcher
Ss 0:00 \_ postgres: logical replication launcher -
Откройте в графическом эмуляторе терминала вкладку, или запустите еще один терминал. В новом терминале выполните команды:
[student@p620 ~]$ sudo -iu postgres [postgres@p620 ~]$ psql
psql (15.5)
Type "help" for help.
postgres=#
Первая команда (sudo) запускает оболочку Bash от имени пользователя postgres
. Вторая команда запускает клиент psql
, в результате чего у вас имеется клиент - серверное соединение.
5. Узнайте PID
серверного процесса, обслуживающего вашу сессию в psql
, выполнив команду в psql
:
postgres=# select pg_backend_pid(); pg_backend_pid
----------------
9787
(1 row)
Обратите внимание на точку с запятой в конце команды. Точка с запятой - символ того, что ввод команды SQL закончен.
Если в конце команды не введена точка с запятой, а далее нажат Enter, на экране будет видно следующее:
postgres=# select pg_backend_pid() postgres-#
Обратите внимание на символ -#
в конце приглашения командной строки. Оно сообщает о том, что ввод команды не завершен и надо либо отказатьс я от ввода команды, нажав Ctrl+C
, либо ввести точку с запятой и Enter
:
postgres=# select pg_backend_pid() postgres-# ;
pg_backend_pid
----------------
(1 row)
Этот механизм позволяет вводить длинные команды SQL, разбивая их на отдельные строки. Только в самом конце длинной команды надо ввести ;
.
6. Проверьте, что в списке процессов экземпляра появился обслуживающий процесс с выведенным функцией pg_backend_pid()
PID:
postgres=# select pg_backend_pid() postgres-# ;
pg_backend_pid
----------------
9787
(1 row)
postgres=# \! ps f -C postgres
PID TTY
9675 ?
9699 ?
9700 ?
9701 ?
9703 ?
9704 ?
9705 ?
9706 ?
9707 ?
9708 ?
9709 ?
9787 ?
STAT TIME COMMAND
Ss 0:00 /usr/pangolin-6.2.0/bin/postgres -D /pgdata/06/data
Ss 0:00 \_ postgres: logger
Ss 0:00 \_ postgres: checkpointer
Ss 0:00 \_ postgres: background writer
Ss 0:00 \_ postgres: idle sessions terminator
Ss 0:00 \_ postgres: walwriter
Ss 0:00 \_ postgres: license checker
Ss 0:00 \_ postgres: autovacuum launcher
Ss 0:00 \_ postgres: autounite launcher
Ss 0:00 \_ postgres: integrity check launcher
Ss 0:00 \_ postgres: logical replication launcher
Ss 0:00 \_ postgres: postgres postgres [local] idle
Запущенный серверный процесс обеспечивает клиент-серверное взаимодействие с psql.
Этапы взаимодействия клиента и сервера
-
Перезапустите соединение, выполнив команду psql
\с
и проверьте, изменился ли PID серверного процесса:postgres=# \c
You are now connected to database "postgres" as user "postgres". postgres=# select pg_backend_pid();
pg_backend_pid
----------------
9988
(1 row)Старый серверный процесс завершен, вместо него запущен новый. Все, что сохранялось в локальной памяти серверного процесса сброшено. Память клиента psql - осталась, так как клиент не рестартовал.
-
Зарегистрируйте в PostgreSQL новую роль с паролем. Проверьте, пройдет ли успешно процесс аутентификации при входе в сеанс нового пользователя:
postgres=# create user dbuser1 password 'dbuser1'; CREATE ROLE
postgres=# \du dbuser1 List of roles
Role name | Attributes | Member of
-----------+------------+-----------
dbuser1 | | {}У пользователя dbuser1 пароль, соответствующий его имени. Зайдите в сеанс:
postgres=# \c - dbuser1
connection to server on socket "/tmp/.s.PGSQL.5432" failed: FATAL: Peer authentication failed for user "dbuser1"
Previous connection keptНе удалось. Команда
\c
- подключиться (connect
), первое тире после нее - подключиться к той же БД, к которой выполнено подключение сейчас,dbuser1
- от имени этой роли. -
Если вход в сеанс не удался, стоит проверить, почему. По сообщению в примере видно строку Peer authentication failed for user "dbuser1". Это сообщение о том, что не прошла аутентификация по методу peer, которая разрешает зайти в сеанс только тем зарегистрированным в ОС пользователям, чье имя пользователя в ОС совпадает с именем пользователя в PostgreSQL. Проверим содержимое конфигурационного файла, отвечающего за аутентификацию:
postgres=# select * from pg_hba_file_rules();
line_number | type | database | user_name | address | netmask | auth_method | options |
-------------+-------+---------------+-----------+-----------+-----------------------------------------+---------------+---------+
(7 rows)
89 | local | {all}
90 | host | {student}
93 | host | {all}
95 | host | {all}
98 | local | {replication} 99 | host | {replication}
100 | host | {replication}
| {all} |
| {student} | | {all} | | {all} | | {all} | | {all} | | {all} |
|
IP | 127.0.0.1 | ::1 |
| 127.0.0.1 | ::1 |
255.255.255.255
255.255.255.255 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
255.255.255.255 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
| peer | |
| scram-sha-256 | | | scram-sha-256 | | | scram-sha-256 | | | peer | | | scram-sha-256 | | | scram-sha-256 | |Если в выделенной строке вместо слова
peer
стоитtrust
, то сеанс должен был запуститься. В данном случае из-за peer требуется чтобы локальный вход в сеанс осуществлял зарегистрированный пользователь ОС, имя которого совпадает с ролью в PostgreSQL. В данном случае dbuser1 в ОС не зарегистрирован. -
Попробуем аутентификацию
host
. В отличие отlocal
, которая настраивает локальные подключения через Unix сокеты, аутентификация host относится только к сетевым подключениям через сетевые интерфейсы:postgres=# select * from pg_hba_file_rules();
line_number | type | database | user_name | address | netmask | auth_method | options |
-------------+-------+---------------+-----------+-----------+-----------------------------------------+---------------+---------+
89 | local | {all}
90 | host | {student}
93 | host | {all}
95 | host | {all}
98 | local | {replication} 99 | host | {replication}
100 | host | {replication}
| {all} | | {student} | | {all} | | {all} | | {all} | | {all} | | {all} |
| IP | 127.0.0.1 | ::1 | | 127.0.0.1 | ::1 |
255.255.255.255
255.255.255.255
ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
255.255.255.255 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
| peer | | | scram-sha-256 | | | scram-sha-256 | | | scram-sha-256 | | | peer | | | scram-sha-256 | | | scram-sha-256 | |
(7 rows)При показанных настройках подключение к любой БД от имени любой роли PostgreSQL через
localhost
будет требовать подтверждения аутентичности пользователя с помощью пароля:postgres=# \c - dbuser1 localhost
Password for user dbuser1:
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
You are now connected to database "postgres" as user "dbuser1" on host "localhost" (address "::1") at port "5432".Подключение установлено. Выйдите из сеанса:
postgres=> \q [postgres@p620 ~]$
Параметры соединения
-
Войдите в сеанс:
[postgres@p620 ~]$ psql psql (15.5)
Type "help" for help.
postgres=# -
Проверьте, как было установлено соединение:
postgres=# \conninfo
You are connected to database "postgres" as user "postgres" via socket in "/tmp" at port "5432". -
Переподключитесь через
localhost
:postgres=# \c - - localhost
Password for user postgres:
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
You are now connected to database "postgres" as user "postgres" on host "localhost" (address "::1") at port "5432".
postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "localhost" (address "::1") at port "5432".
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)Первый раз подключение было локальное через Unix сокет, и оно не было шифрованным. Второй раз - через сетевой интерфейс
localhost
, команда\connninfo
сообщает, что это соединение шифрованное (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384
).
Сокеты
-
Проверьте наличие Unix сокета в каталоге
/tmp
:postgres=# \! ls -al /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Команда в клиенте psql
\!
позволяет выполнить команду ОС без вых ода из программы psql. Выполнена командаls -l
, предоставляющая подробную информацию о файлах. Из ее вывода заметно, что есть файл/tmp/.s.PGSQL
.5432
- сокет. Для файлов-сокетов командаls -l
перед правами доступа rwxrwxrwx пишет тип файла -s
(socket
). -
Проверьте, какой процесс сейчас работает с этим файлом:
postgres=# \! lsof /tmp/.s.PGSQL.5432
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
postgres 9675 postgres 8u unix 0x00000000ccb46eea 0t0 44241 /tmp/.s.PGSQL.5432 type=STREAM -
Узнайте, что это за процесс:
postgres=# \! ps -fp 9675
UID PID PPID C STIME TTY TIME CMD
postgres 9675 1 0 11:44 ? 00:00:02 /usr/pangolin-6.2.0/bin/postgres -D /pgdata/06/data
Настройки сервера для сокетов
-
Проверьте, как настроен экземпляр: какие сетевые интерфейсы прослушиваются, номер порта TCP и расположение сокета в файловой системе:
postgres=# \dconfig listen*|port|unix*dir* List of configuration parameters
Parameter | Value
-------------------------+-------
listen_addresses | *
port | 5432
unix_socket_directories | /tmp
(3 rows) -
Проверьте, действительно ли прослушиваются данные порты:
postgres=# \! ss -ln | grep 5432
u_str LISTEN 0 290 /tmp/.s.PGSQL.5432 44241 * 0
tcp LISTEN 0 290 0.0.0.0:5432 0.0.0.0:*
tcp LISTEN 0 290 [::]:5432 [::]:*
Информация о сервере
-
Исследуйте содержимое файла
postmaster.pid
:postgres=# \! cat $PGDATA/postmaster.pid 9675
/pgdata/06/data
1731055479
5432 /tmp *
786435 51
readyПеременная
PGDATA
указывает имя каталога данных кластера. Доллар перед именем переменной извлекает значение из нее. -
Извлеките из файла
postmaster.pid
утилитой head первую строку и подставьте ее в утилитуps
для получения отчета о статусе головного процесса экземпляра:postgres=# \! ps -fp $(head -1 $PGDATA/postmaster.pid)
UID PID PPID C STIME TTY TIME CMD
postgres 9675 1 0 11:44 ? 00:00:02 /usr/pangolin-6.2.0/bin/postgres -D /pgdata/06/dataКонструкция
$()
- командная подстановка, вместо нее подставляется результат выполненной команды.Выйдите из сеанса:
postgres=# \q
Получение информации о сеансе
-
Зайдите в сеанс из-под сессии postgres в ОС и получите информацию о пользователе в сеансе PostgreSQL, текущую БД, сетевой порт TCP и адрес источника соединения:
[postgres@p620 ~]$ psql psql (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 template1 - localhost
Password for user postgres:
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
You are now connected to database "template1" as user "postgres" on host "localhost" (address "::1") at port "5432".
template1=# select user, current_catalog, inet_server_port(), inet_server_addr();
user | current_catalog | inet_server_port | inet_server_addr
----------+-----------------+------------------+------------------
postgres | template1 | 5432 | ::1
(1 row)Обратите вн имание, что подключение произведено через
localhost
по протоколуIPv6
- адрес::1/128
. -
Подключитесь от имени пользователя
dbuser1
и проверьте те же параметры:template1=# \c template1 dbuser1 localhost
Password for user dbuser1:
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off) You are now connected to database "template1" as user "dbuser1".
template1=> select user, current_catalog, inet_server_port(), inet_server_addr();
user | current_catalog | inet_server_port | inet_server_addr
---------+-----------------+------------------+------------------
dbuser1 | template1 | 5432 | ::1
(1 row)
template1=> \q
Библиотека libpq
-
Получите путь к исполняемому файлу psql:
[postgres@p620 ~]$ which psql /bin/psql
-
Проверьте, загружается ли библиотека
libpq
при старте этой программы:[postgres@p620 ~]$ ldd `which psql` | grep libpq
libpq.so.5 => /usr/pangolin/lib/libpq.so.5 (0x00007f2051065000)