暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

postgresql之命令pg_ctl启动研究源代码

SmallDB 2025-03-13
100

 

总结

pg_ctl这个工具我们经常使用的工具,工具启动的过程中去会读取PGDATA这个环境变量,如果 没有不能成功启动,或者我们加上D 参数手动传入,然后重新设置PGDATA这个环境变量,
第一步读取PGDATA

            switch (c)
            {
                case 'D':
                    {
                        char       *pgdata_D;

                        pgdata_D = pg_strdup(optarg);
                        canonicalize_path(pgdata_D);
                        setenv("PGDATA", pgdata_D, 1);

                        /*
                         * We could pass PGDATA just in an environment
                         * variable but we do -D too for clearer postmaster
                         * 'ps' display
                         */

                        pgdata_opt = psprintf("-D \"%s\" ", pgdata_D);
                        free(pgdata_D);
                        break;

第二步设置PGDATA

/* Note we put any -D switch into the env var above */
    pg_config = getenv("PGDATA");
    if (pg_config)
    {
        pg_config = pg_strdup(pg_config);
        canonicalize_path(pg_config);
        pg_data = pg_strdup(pg_config);
    }

第三步执行启动

    /* No -D or -D already added during server start */
    if (ctl_command == RESTART_COMMAND || pgdata_opt == NULL)
        pgdata_opt = "";

    if (exec_path == NULL)
        exec_path = find_other_exec_or_die(argv0, "postgres", PG_BACKEND_VERSIONSTR);

第四步真正的打工人-干活的函数

    pm_pid = start_postmaster();

    if (do_wait)
    {
        /*
         * If the user interrupts the startup (e.g. with CTRL-C), we'd like to
         * abort the server launch.  Install a signal handler that will
         * forward SIGINT to the postmaster process, while we wait.
         *
         * (We don't bother to reset the signal handler after the launch, as
         * we're about to exit, anyway.)
         */

        postmasterPID = pm_pid;
        pqsignal(SIGINT, trap_sigint_during_startup);

        print_msg(_("waiting for server to start..."));

        switch (wait_for_postmaster_start(pm_pid, false))
        {
            case POSTMASTER_READY:
                print_msg(_(" done\n"));
                print_msg(_("server started\n"));
                break;
            case POSTMASTER_STILL_STARTING:
                print_msg(_(" stopped waiting\n"));
                write_stderr(_("%s: server did not start in time\n"),
                             progname);
                exit(1);
                break;
            case POSTMASTER_FAILED:
                print_msg(_(" stopped waiting\n"));
                write_stderr(_("%s: could not start server\n"
                               "Examine the log output.\n"),
                             progname);
                exit(1);
                break;
        }
    }
    else
        print_msg(_("server starting\n"));


相关的工具链

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

/usr/local/pgsqldebug/bin/pg_ctl -D usr/local/pgsqldebug/data -l logfile stop
 

进入pg_ctl
所在的目录, 执行如下命令:

gdb usr/local/pgsqldebug/bin/pg_ctl
(gdb) layout src
(gdb) set args -D /usr/local/pgsqldebug/data start
(gdb) b main
(gdb) run

调试截图


调试信息


    switch (ctl_command)
    {
        case INIT_COMMAND:
            do_init();
            break;
        case STATUS_COMMAND:
            do_status();
            break;
        case START_COMMAND:
            do_start();
            break;
        case STOP_COMMAND:
            do_stop();
            break;
        case RESTART_COMMAND:
            do_restart();
            break;
        case RELOAD_COMMAND:
            do_reload();
            break;
        case PROMOTE_COMMAND:
            do_promote();
            break;
        case LOGROTATE_COMMAND:
            do_logrotate();
            break;
        case KILL_COMMAND:
            do_kill(killproc);
            break;
#ifdef WIN32
        case REGISTER_COMMAND:
            pgwin32_doRegister();
            break;
        case UNREGISTER_COMMAND:
            pgwin32_doUnregister();
            break;
        case RUN_AS_SERVICE_COMMAND:
            pgwin32_doRunAsService();
            break;
#endif
        default:
            break;
    }

    exit(0);
}


static void do_start(void);
static void
do_start(void)
{
    pgpid_t        old_pid = 0;
    pgpid_t        pm_pid;

    if (ctl_command != RESTART_COMMAND)
    {
        old_pid = get_pgpid(false);
        if (old_pid != 0)
            write_stderr(_("%s: another server might be running; "
                           "trying to start server anyway\n"),
                         progname);
    }

    read_post_opts();

    /* No -D or -D already added during server start */
    if (ctl_command == RESTART_COMMAND || pgdata_opt == NULL)
        pgdata_opt = "";

    if (exec_path == NULL)
        exec_path = find_other_exec_or_die(argv0, "postgres", PG_BACKEND_VERSIONSTR);

#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
    if (allow_core_files)
        unlimit_core_size();
#endif

static char *
find_other_exec_or_die(const char *argv0, const char *target, const char *versionstr)
{
    int            ret;
    char       *found_path;

    found_path = pg_malloc(MAXPGPATH);

    if ((ret = find_other_exec(argv0, target, versionstr, found_path)) < 0)
    {
        char        full_path[MAXPGPATH];

        if (find_my_exec(argv0, full_path) < 0)
            strlcpy(full_path, progname, sizeof(full_path));

        if (ret == -1)
            write_stderr(_("The program \"%s\" is needed by %s but was not found in the\n"
                           "same directory as \"%s\".\n"
                           "Check your installation.\n"),
                         target, progname, full_path);
        else
            write_stderr(_("The program \"%s\" was found by \"%s\"\n"
                           "but was not the same version as %s.\n"
                           "Check your installation.\n"),
                         target, full_path, progname);
        exit(1);
    }

    return found_path;
}

 


文章转载自SmallDB,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论