Postgresql - 配置为 Upstart 作业问题

Postgresql - 配置为 Upstart 作业问题

我需要将 Postgresql 配置为使用 Upstart 系统启动,因为我使用 Upstarts 事件来启动另一个依赖于 pgsql 运行的应用程序。这是我使用的教程/脚本:

http://bradleyayers.blogspot.com/2011/10/upstart-job-for-postgresql-91-on-ubuntu.html

当我重新启动服务器 ( shutdown -r now) 时,postgresql 没有运行(通过“top”命令看不到作业)。然后我尝试手动运行以下命令:

root@server:~# exec su -c "/usr/lib/postgresql/9.1/bin/postgres -D /var/lib/postgresql/9.1/main -c config_file=/etc/postgresql/9.1/main/postgresql.conf" postgres

我的 ssh 会话只是断开连接,没有返回任何内容。如果我重新连接并再次检查正在运行的作业,pgsql 仍然没有运行。所以我尝试运行没有“exec”的命令,以下是响应:

root@server:~# su -c "/usr/lib/postgresql/9.1/bin/postgres -D /var/lib/postgresql/9.1/main -c config_file=/etc/postgresql/9.1/main/postgresql.conf" postgres

2012-12-03 19:31:36 MSK FATAL:  could not create lock file "/var/run/postgresql/.s.PGSQL.5432.lock": No such file or directory

我认为问题与 postgresql 本身有关,而不是 upstart 系统。我认为它提到的文件应该存在,因此可以访问,但由于某种原因它不存在。是否有其他人偶然发现这个问题,或者有潜在的解决方案?

答案1

我也有同样的愿望,希望以这种方式配置 pg。对我来说,我想要多个集群,每个集群都有自己独立的调度程序 (pgagent)。当我关闭单个集群时,pgagent 将自动停止,但当我启动集群时,我希望 pgagent 也为该集群自动启动。如果我在启动集群时忘记启动调度程序,那我就有麻烦了。

我搜索了一番,但始终找不到在 Upstart 下运行 PostgreSQL 的好方法。大多数解决方案都明确启动了 postmaster,而不是使用 pg_wrapper 命令。按照 Upstart 的工作方式,这似乎很危险,在极少数情况下可能会导致数据丢失。

因此,我继续前进,尝试创建自己的 Upstart 脚本来完成这项工作。我发现很难捕获集群及其 pgagent 实例的正确 PID。但最终,我意识到使用 PostgreSQL,您实际上并不关心 PID。您关心的是版本和集群。一旦我意识到这一点,一切都结合在一起,我创建了以下三个脚本:

第一个我称之为 pg_versions.conf。

description "PostgreSQL Version Controller"
author "Brian Myers"

start on runlevel [2345]
stop on runlevel [016]

env DEFAULT_VERSIONS="9.3"

pre-start script
  if [ -z $VERSIONS ]; then
    VERSIONS=$DEFAULT_VERSIONS
  fi
  for version in $VERSIONS 
  do
    for cluster in $(pg_lsclusters -h | grep $version | cut -d" " -f 2) 
    do
      if [ `tail -1 /etc/postgresql/$version/$cluster/start.conf` = "auto" ]; then
        start pg_cluster version=$version cluster=$cluster
      fi
    done
  done
end script

post-stop script
  if [ -z $VERSIONS ]; then
    VERSIONS=$DEFAULT_VERSIONS
  fi
  for version in $VERSIONS 
  do
    for cluster in $(pg_lsclusters -h | grep $version | cut -d" " -f 2) 
    do
      stop pg_cluster version=$version cluster=$cluster
    done
  done
end script

接下来是 pg_cluster.conf。

description "PostgreSQL Cluster Controller"
author "Brian Myers"

instance $version-$cluster

pre-start script
  if [ `pg_lsclusters -h | grep $version | grep $cluster | cut -d" " -f 4` = "down" ]; then
    pg_ctlcluster $version $cluster start || :
    start pg_agent version=$version cluster=$cluster || :
  fi
end script

post-stop script
  if [ -e "/var/run/postgresql/pgagent-$version-$cluster.pid" ]; then
    stop pg_agent version=$version cluster=$cluster
  fi
  if [ `pg_lsclusters -h | grep $version | grep $cluster | cut -d" " -f 4` = "online" ]; then
    pg_ctlcluster $version $cluster stop
  fi
end script

最后是 pg_agent.conf。

description "PgAgent Controller"
author "Brian Myers"

instance ${version}-${cluster}

setuid postgres

pre-start script
  PORT=`pg_lsclusters -h | grep $version | grep $cluster | cut -d" " -f 3`
  if [ -z `psql -c "select schema_name FROM information_schema.schemata WHERE schema_name = 'pgagent';" -d postgres -p $PORT | grep pgagent` ]; then
    stop ; exit 0
  fi
  PGAGENTDIR=`which pgagent`
  PGAGENTOPTIONS="host=/var/run/postgresql dbname=postgres user=postgres port=$PORT"
  start-stop-daemon --start --oknodo --name "pga$version$cluster" --exec $PGAGENTDIR -- $PGAGENTOPTIONS
  pgrep -f "$PGAGENTDIR.+$PORT" > /var/run/postgresql/pgagent-$version-$cluster.pid
end script

post-stop script
  start-stop-daemon --stop --oknodo --pidfile /var/run/postgresql/pgagent-$version-$cluster.pid
  if [ -w /var/run/postgresql/pgagent-$version-$cluster.pid ]; then
    rm -f /var/run/postgresql/pgagent-$version-$cluster.pid
  fi
end script

如果您想要的不仅仅是 9.3 版本,只需将版本添加到env DEFAULT_VERSIONS="9.3"以空格分隔的行中。

有了这些,我可以:

启动所有尚未运行的集群: sudo initctl start pg_versions

启动尚未运行的特定版本的所有集群: sudo initctl start pg_versions version=9.3

启动特定集群,自动启动该集群的 pgagent,但前提是该集群启用了 pgagent: sudo initctl start pg_cluster version=9.3 cluster=main

如果集群启用了 pgagent,则启动集群的 pgagent: sudo initctl start pg_agent version=9.3 cluster=main

将 start 改为 stop 可获得相反的行为。当然,所有程序都会在启动时启动,并在 stop 时通过 关机pg_ctlcluster,因此不会丢失数据。我确实必须通过 bum 禁用 init.d 脚本。

我确信这些问题可以得到解决,或者以更好的方式解决。例如,pg_agent 脚本——我一直搞不明白为什么使用 script 或 exec 无法捕获正确的 PID。最后我放弃了,自己管理了 pid 文件,但这仍然是个谜。这可能是因为我的 shell 脚本编写技能太差了。

还请注意,如果您手动关闭集群,pg_ctlcluster这些 Upstart 作业仍将显示为正在运行,即使相关版本/集群未运行。这没什么大不了的,因为您只需使用 或 重新启动它们即可pg_ctlclusterinitctl但出于这个原因,如果您部署这些作业,我建议使用initctl来控制您的集群。

无论如何,这些对我来说都很有效。

答案2

错误意味着 Postgres 无法在/var/run/postgresql目录中创建其锁定文件。预脚本应该创建它,并且它将所有权设置为 postgres。对我来说,这个脚本看起来根本就没有运行。因此,请检查start postgres(作为超级用户)、存在和权限的输出ls -l /var/run/postgresql

仅供参考:exec在 Upstart 作业中很有用,因此script运行 shell 脚本的部分不会留下额外的 PID。在 shell 会话中,当执行的程序退出时,它会使您的 shell 退出。

相关内容