Как извлечь 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 для достижения аналогичного эффекта.

Другие вопросы по тегам