如何从shell脚本中的postgresql中提取pg_backend_pid并将其传递给另一个进程?

时间:2011-10-30 00:47:02

标签: perl postgresql shell

我需要在命令行(或脚本)上运行bin/psql并打印其pg_backend_pid,以便pg_backend_pid可以传递给另一个进程(由root运行)命令行参数。对我来说问题是其他进程需要在获得pid后运行。 psql(具有相同的pid会话)然后在另一个进程启动后运行查询。

诀窍是Psql需要等到另一个进程获得pg_backend_pid并且它必须保持相同的会话。

可以通过shell脚本或perl来完成吗?

1 个答案:

答案 0 :(得分:10)

你想在bash中使用协同进程,或者在perl中使用某种双向管道。在Python中,您可以使用os.popen2命令; perl also has facilities for interacting with subprocesses over pipes。但是,如果可能的话,使用DBD::Pgpsycopg2等本地语言数据库驱动程序会更好

如果您必须在shell中执行此操作,请参阅“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命令,并且不会打印输出,因此它更容易在shell上进行交互。

或者,您可能根本不需要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来实现类似的效果。