Как извлечь pg_backend_pid из postgresql в сценарии оболочки и передать его другому процессу?
Мне нужно бежать bin/psql
в командной строке (или сценарии) и распечатать его pg_backend_pid
так, чтобы pg_backend_pid
может быть передан другому процессу (от имени пользователя root) в качестве аргумента командной строки. Проблема для меня в том, что другой процесс должен запускаться после получения pid. psql
(с тем же сеансом pid) затем запускает запрос после запуска другого процесса.
Хитрость в том, что Psql нужно подождать, пока другой процесс не получит pg_backend_pid
и это должно остаться тем же сеансом.
Это можно сделать с помощью сценария оболочки или Perl?
1 ответ
Вы захотите использовать сопроцесс в bash или в perl с каким-то двусторонним каналом. В Python вы можете использовать команду os.popen2; Perl также имеет средства для взаимодействия с подпроцессами по каналам. Тем не менее, гораздо лучше использовать драйверы баз данных на родном языке, такие как DBD::Pg
или же psycopg2
если вообще возможно.
Если вы должны сделать это в оболочке, смотрите "info bash" и ищите "coprocess".
Вот быстрый демонстрационный скрипт bash, чтобы вы начали.
#!/bin/bash
set -e -u
DBNAME=whatever_my_db_is_called
coproc psql --quiet --no-align --no-readline --tuples-only -P footer=off --no-password "$DBNAME"
echo 'SELECT pg_backend_pid();' >&${COPROC[1]}
read -u ${COPROC[0]} backend_pid
echo "Backend PID is: ${backend_pid}"
echo "SELECT random();" >&${COPROC[1]}
read -u ${COPROC[0]} randnum
echo "\q" >&${COPROC[1]}
wait %1
echo "Random number ${randnum} generated by pg backend ${backend_pid}"
Аргументы psql должны гарантировать, что он не приостанавливает ввод, не интерпретирует вкладки или метасхемы как команды readline и не выводит симпатичные выходные данные, поэтому с оболочкой легче взаимодействовать.
С другой стороны, возможно, вам вообще не нужен psql, вам просто нужно поговорить с сервером PostgreSQL с помощью какого-то скрипта. В этом случае НАМНОГО проще будет использовать язык сценариев с интерфейсом базы данных PostgreSQL. В Python, например:
#!/usr/bin/env python
import os
import sys
import psycopg2
def main():
conn = psycopg2.connect("dbname=classads")
curs = conn.cursor()
curs.execute("SELECT pg_backend_pid();");
pid = curs.fetchall()[0][0]
# Do whatever you need to here,
# like using os.system() or os.popen() or os.popen2() to talk to
# system commands, using curs.execute() to talk to the database, etc.
conn.close();
if __name__ == '__main__':
main()
В Perl вы можете использовать DBI и DBD::Pg для достижения аналогичного эффекта.