PostgreSQL 9.4.4 中文手册
上一页 | 上一级 | 章 17. 服务器设置和操作 | 下一页

# 17.3. 启动数据库服务器

在任何人可以访问数据库前，你必须启动数据库服务器。数据库服务器程序名叫`postgres`， 它必须知道在哪里能找到它要用的数据。 这是利用`-D`选项实现的。因此，启动服务器最简单的方法是像下面这样：

    $ postgres -D /usr/local/pgsql/data

这样将把服务器放在前台运行。这个步骤同样必须以PostgreSQL用户帐户登录来做。 没有`-D`选项，服务器将使用环境变量`PGDATA`命名的目录； 如果这个环境变量也没有，将导致失败。

通常，最好在后台启动`postgres`，使用下面的 Unix shell 语法：

    $ postgres -D /usr/local/pgsql/data >logfile 2>&1 &

把服务器的stdout和stderr放到某个地方是非常重要的， 就像在上面建议的这样。这样做既可以帮助审计又可以帮助诊断问题。 参阅第 23.3 节获取有关日志文件处理的更完整讨论。

`postgres`还接受一些其它的一些命令行选项。 更多的信息请参考postgres手册页和下面的第 18 章。

这些 shell 语法很容易让人觉得无聊。因此我们提供了封装程序 pg_ctl以简化一些任务。比如：

    pg_ctl start -l logfile

将在后台启动服务器并且把输出放到指定的日志文件中。`-D` 选项和你直接运行`postgres`时的意思是一样的。`pg_ctl` 还可以用于关闭服务器。

通常，你会希望在计算机启动的时候启动数据库服务器。 自动启动脚本是与操作系统相关的。PostgreSQL自己带了几个， 放在`contrib/start-scripts`目录里。需要 root 权限安装它们。

不同的系统在引导时有不同的启动守护进程的方法，所以我们建议你先熟悉它。 许多系统有名字称为`/etc/rc.local`或`/etc/rc.d/rc.local` 这样的文件，其它的还有`rc.d`目录。不管你怎么做，都要记住服务器必须以 PostgreSQL用户帐户，而不是 root 或者任何其它用户身份运行。因此，你可能总是要用`su postgres -c '...'`这样的命令。比如：

    su postgres -c 'pg_ctl start -D /usr/local/pgsql/data -l serverlog'

下面是一些比较详细的与操作系统相关的建议。请注意把每个例子里的具体数值替换成合适的安装路径和用户名。

- 对于FreeBSD，看看PostgreSQL 源代码版本里的`contrib/start-scripts/freebsd`文件。

- 在OpenBSD上，把下面几行加到`/etc/rc.local`文件里：

      if [ -x /usr/local/pgsql/bin/pg_ctl -a -x /usr/local/pgsql/bin/postgres ]; then
          su -l postgres -c '/usr/local/pgsql/bin/pg_ctl start -s -l /var/postgresql/log -D /usr/local/pgsql/data'
          echo -n ' postgresql'
      fi

- 在Linux系统里，要么往`/etc/rc.d/rc.local`或 `/etc/rc.local`文件里加上下面几行：

      /usr/local/pgsql/bin/pg_ctl start -l logfile -D /usr/local/pgsql/data

  要么看看PostgreSQL源代码树里的 `contrib/start-scripts/linux`文件。

- 在NetBSD上，你可以根据爱好选择FreeBSD 或Linux的启动脚本之一。

- 在Solaris上，创建一个叫`/etc/init.d/postgresql`的文件， 包含下面行：

      su - postgres -c "/usr/local/pgsql/bin/pg_ctl start -l logfile -D /usr/local/pgsql/data"

  然后在`/etc/rc3.d`里创建一个指向它的符号链接，名字叫`S99postgresql`。

运行的时候，它的PID是保存在数据目录下的`postmaster.pid` 文件里的。这样做是为了避免多个服务器在同一个数据目录内运行，此文件同样可以用于关闭服务器。

## 17.3.1. 服务器启动失败

有几个非常常见的原因会导致服务器启动失败。通过检查服务器日志或者使用手工启动的方法 (不做 stdout 和 stderr 的重定向)，就可以看到错误消息。下面我们更详细地解释了其中一些错误消息。

    LOG:  could not bind IPv4 socket: Address already in use
    HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry.
    FATAL:  could not create TCP/IP listen socket

就像它提示的那样：你试图在已经有一个服务器运行着的端口上再运行了一个服务器。不过， 如果内核的错误消息不是`Address already in use` 或者是其它的变种， 那就有可能是别的毛病。比如，试图在一个保留的端口上运行服务器会收到下面这样的信息：

    $ postgres -p 666
    LOG:  could not bind IPv4 socket: Permission denied
    HINT:  Is another postmaster already running on port 666? If not, wait a few seconds and retry.
    FATAL:  could not create TCP/IP listen socket

像这样的信息：

    FATAL:  could not create shared memory segment: Invalid argument
    DETAIL:  Failed system call was shmget(key=5440001, size=4011376640, 03600).

可能意味着内核对共享内存区的限制小于PostgreSQL试图分配的缓冲区大小 (本例中是 4011376640 字节)。或者可能意味着你根本就没有配置 System-V 风格的共享内存支持。 作为一个临时的解决办法，你可以试着以小于正常数量的缓冲区数(shared_buffers) 启动服务器。你最终还是会希望重新配置内核，以增加共享内存的尺寸。 如果你试图在同一台机器上启动多个服务器，而且它们所需的总空间超过了内核的限制，也会报这个错。

像下面这样的错误：

    FATAL:  could not create semaphores: No space left on device
    DETAIL:  Failed system call was semget(5440126, 17, 03600).

并不意味着着你已经用光磁盘空间了。它的意思是内核的 System V信号灯的限制小于PostgreSQL想创建的数量。 和上面一样，你可以通过减少允许的连接数(max_connections)来绕开， 但最终你还是会希望修改内核的限制。

如果你收到一个"illegal system call"错误，那么很有可能是内核根本不支持共享内存或者信号灯。 如果是这样的话，你唯一的选择就是重新配置内核并且把这些特性打开。

关于配置系统System V IPC资源的细节见第 17.4.1 节。

## 17.3.2. 客户端连接问题

尽管可能在客户端出现的错误条件范围宽广，而且还和应用相关，但的确有几种错误与服务器的启动方式直接相关。 除了下面提到的几种错误以外的问题都应该在相应的客户端应用的文档中。

    psql: could not connect to server: Connection refused
            Is the server running on host "server.joe.com" and accepting
            TCP/IP connections on port 5432?

这是纯粹的"我找不到可以交谈的服务器"错误。当试图进行 TCP/IP 通讯时它看起来像上面的样子。 常见的错误是忘记把服务器配置成允许 TCP/IP 连接。

另外，当试图通过一个 Unix 套接字与本机服务器通讯时，你会看到这个：

    psql: could not connect to server: No such file or directory
            Is the server running locally and accepting
            connections on Unix domain socket "/tmp/.s.PGSQL.5432"?

最后一行可以有效地验证客户端进行连接尝试时是否连对了位置。如果实际上没有服务器在那里运行， 典型的内核错误是像上面显示的那样或者是`Connection refused`或 `No such file or directory`。尤其要注意的是这种环境下 `Connection refused`的信息显示并不 意味着服务器收到连接然后拒绝了连接。那样的话会产生一个不同的信息(像 第 19.4 节里面显示的那样)。其它像 `Connection timed out`这样的信息表示更基本的问题，比如缺少网络连接等。

上一页 | 起始页 | 下一页
创建数据库集群 | 上一级 | 管理内核资源