📄 pg_ctl.c
字号:
return; case SERVICE_CONTROL_PAUSE: /* Win32 config reloading */ status.dwWaitHint = 5000; kill(postmasterPID, SIGHUP); return; /* FIXME: These could be used to replace other signals etc */ case SERVICE_CONTROL_CONTINUE: case SERVICE_CONTROL_INTERROGATE: default: break; }}static void WINAPIpgwin32_ServiceMain(DWORD argc, LPTSTR * argv){ STARTUPINFO si; PROCESS_INFORMATION pi; DWORD ret; /* Initialize variables */ status.dwWin32ExitCode = S_OK; status.dwCheckPoint = 0; status.dwWaitHint = 60000; status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE; status.dwServiceSpecificExitCode = 0; status.dwCurrentState = SERVICE_START_PENDING; memset(&pi, 0, sizeof(pi)); memset(&si, 0, sizeof(si)); si.cb = sizeof(si); /* Register the control request handler */ if ((hStatus = RegisterServiceCtrlHandler(register_servicename, pgwin32_ServiceHandler)) == (SERVICE_STATUS_HANDLE) 0) return; if ((shutdownEvent = CreateEvent(NULL, true, false, NULL)) == NULL) return; /* Start the postmaster */ pgwin32_SetServiceStatus(SERVICE_START_PENDING); if (!CreateProcess(NULL, pgwin32_CommandLine(false), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { pgwin32_SetServiceStatus(SERVICE_STOPPED); return; } postmasterPID = pi.dwProcessId; postmasterProcess = pi.hProcess; CloseHandle(pi.hThread); pgwin32_SetServiceStatus(SERVICE_RUNNING); /* Wait for quit... */ ret = WaitForMultipleObjects(2, shutdownHandles, FALSE, INFINITE); pgwin32_SetServiceStatus(SERVICE_STOP_PENDING); switch (ret) { case WAIT_OBJECT_0: /* shutdown event */ kill(postmasterPID, SIGINT); /* * Increment the checkpoint and try again Abort after 12 * checkpoints as the postmaster has probably hung */ while (WaitForSingleObject(postmasterProcess, 5000) == WAIT_TIMEOUT && status.dwCheckPoint < 12) status.dwCheckPoint++; break; case (WAIT_OBJECT_0 + 1): /* postmaster went down */ break; default: /* shouldn't get here? */ break; } CloseHandle(shutdownEvent); CloseHandle(postmasterProcess); pgwin32_SetServiceStatus(SERVICE_STOPPED);}static voidpgwin32_doRunAsService(void){ SERVICE_TABLE_ENTRY st[] = {{register_servicename, pgwin32_ServiceMain}, {NULL, NULL}}; if (StartServiceCtrlDispatcher(st) == 0) { write_stderr(_("%s: could not start service \"%s\": error code %d\n"), progname, register_servicename, (int) GetLastError()); exit(1); }}#endifstatic voiddo_advice(void){ write_stderr(_("Try \"%s --help\" for more information.\n"), progname);}static voiddo_help(void){ printf(_("%s is a utility to start, stop, restart, reload configuration files,\n" "report the status of a PostgreSQL server, or signal a PostgreSQL process.\n\n"), progname); printf(_("Usage:\n")); printf(_(" %s start [-w] [-D DATADIR] [-s] [-l FILENAME] [-o \"OPTIONS\"]\n"), progname); printf(_(" %s stop [-W] [-D DATADIR] [-s] [-m SHUTDOWN-MODE]\n"), progname); printf(_(" %s restart [-w] [-D DATADIR] [-s] [-m SHUTDOWN-MODE] [-o \"OPTIONS\"]\n"), progname); printf(_(" %s reload [-D DATADIR] [-s]\n"), progname); printf(_(" %s status [-D DATADIR]\n"), progname); printf(_(" %s kill SIGNALNAME PID\n"), progname);#if defined(WIN32) || defined(__CYGWIN__) printf(_(" %s register [-N SERVICENAME] [-U USERNAME] [-P PASSWORD] [-D DATADIR]\n" " [-w] [-o \"OPTIONS\"]\n"), progname); printf(_(" %s unregister [-N SERVICENAME]\n"), progname);#endif printf(_("\nCommon options:\n")); printf(_(" -D, --pgdata DATADIR location of the database storage area\n")); printf(_(" -s, --silent only print errors, no informational messages\n")); printf(_(" -w wait until operation completes\n")); printf(_(" -W do not wait until operation completes\n")); printf(_(" --help show this help, then exit\n")); printf(_(" --version output version information, then exit\n")); printf(_("(The default is to wait for shutdown, but not for start or restart.)\n\n")); printf(_("If the -D option is omitted, the environment variable PGDATA is used.\n")); printf(_("\nOptions for start or restart:\n")); printf(_(" -l, --log FILENAME write (or append) server log to FILENAME\n")); printf(_(" -o OPTIONS command line options to pass to the postmaster\n" " (PostgreSQL server executable)\n")); printf(_(" -p PATH-TO-POSTMASTER normally not necessary\n")); printf(_("\nOptions for stop or restart:\n")); printf(_(" -m SHUTDOWN-MODE may be \"smart\", \"fast\", or \"immediate\"\n")); printf(_("\nShutdown modes are:\n")); printf(_(" smart quit after all clients have disconnected\n")); printf(_(" fast quit directly, with proper shutdown\n")); printf(_(" immediate quit without complete shutdown; will lead to recovery on restart\n")); printf(_("\nAllowed signal names for kill:\n")); printf(" HUP INT QUIT ABRT TERM USR1 USR2\n");#if defined(WIN32) || defined(__CYGWIN__) printf(_("\nOptions for register and unregister:\n")); printf(_(" -N SERVICENAME service name with which to register PostgreSQL server\n")); printf(_(" -P PASSWORD password of account to register PostgreSQL server\n")); printf(_(" -U USERNAME user name of account to register PostgreSQL server\n"));#endif printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));}static voidset_mode(char *modeopt){ if (strcmp(modeopt, "s") == 0 || strcmp(modeopt, "smart") == 0) { shutdown_mode = SMART_MODE; sig = SIGTERM; } else if (strcmp(modeopt, "f") == 0 || strcmp(modeopt, "fast") == 0) { shutdown_mode = FAST_MODE; sig = SIGINT; } else if (strcmp(modeopt, "i") == 0 || strcmp(modeopt, "immediate") == 0) { shutdown_mode = IMMEDIATE_MODE; sig = SIGQUIT; } else { write_stderr(_("%s: unrecognized shutdown mode \"%s\"\n"), progname, modeopt); do_advice(); exit(1); }}static voidset_sig(char *signame){ if (!strcmp(signame, "HUP")) sig = SIGHUP; else if (!strcmp(signame, "INT")) sig = SIGINT; else if (!strcmp(signame, "QUIT")) sig = SIGQUIT; else if (!strcmp(signame, "ABRT")) sig = SIGABRT; /* * probably should NOT provide SIGKILL * * else if (!strcmp(signame,"KILL")) sig = SIGKILL; */ else if (!strcmp(signame, "TERM")) sig = SIGTERM; else if (!strcmp(signame, "USR1")) sig = SIGUSR1; else if (!strcmp(signame, "USR2")) sig = SIGUSR2; else { write_stderr(_("%s: unrecognized signal name \"%s\"\n"), progname, signame); do_advice(); exit(1); }}intmain(int argc, char **argv){ static struct option long_options[] = { {"help", no_argument, NULL, '?'}, {"version", no_argument, NULL, 'V'}, {"log", required_argument, NULL, 'l'}, {"mode", required_argument, NULL, 'm'}, {"pgdata", required_argument, NULL, 'D'}, {"silent", no_argument, NULL, 's'}, {NULL, 0, NULL, 0} }; int option_index; int c; pgpid_t killproc = 0;#if defined(WIN32) || defined(__CYGWIN__) setvbuf(stderr, NULL, _IONBF, 0);#endif progname = get_progname(argv[0]); set_pglocale_pgservice(argv[0], "pg_ctl"); /* * save argv[0] so do_start() can look for the postmaster if necessary. we * don't look for postmaster here because in many cases we won't need it. */ argv0 = argv[0]; umask(077); /* support --help and --version even if invoked as root */ if (argc > 1) { if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) { do_help(); exit(0); } else if (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "--version") == 0) { printf("%s (PostgreSQL) %s\n", progname, PG_VERSION); exit(0); } } /* * Disallow running as root, to forestall any possible security holes. */#ifndef WIN32#ifndef __BEOS__ /* no root check on BEOS */ if (geteuid() == 0) { write_stderr(_("%s: cannot be run as root\n" "Please log in (using, e.g., \"su\") as the " "(unprivileged) user that will\n" "own the server process.\n"), progname); exit(1); }#endif#endif /* * 'Action' can be before or after args so loop over both. Some * getopt_long() implementations will reorder argv[] to place all flags * first (GNU?), but we don't rely on it. Our /port version doesn't do * that. */ optind = 1; /* process command-line options */ while (optind < argc) { while ((c = getopt_long(argc, argv, "D:l:m:N:o:p:P:sU:wW", long_options, &option_index)) != -1) { switch (c) { case 'D': { char *pgdata_D; char *env_var = pg_malloc(strlen(optarg) + 8); pgdata_D = xstrdup(optarg); canonicalize_path(pgdata_D); snprintf(env_var, strlen(optarg) + 8, "PGDATA=%s", pgdata_D); putenv(env_var); /* * We could pass PGDATA just in an environment * variable but we do -D too for clearer postmaster * 'ps' display */ pgdata_opt = pg_malloc(strlen(pgdata_D) + 7); snprintf(pgdata_opt, strlen(pgdata_D) + 7, "-D \"%s\" ", pgdata_D); break; } case 'l': log_file = xstrdup(optarg); break; case 'm': set_mode(optarg); break; case 'N': register_servicename = xstrdup(optarg); break; case 'o': post_opts = xstrdup(optarg); break; case 'p': postgres_path = xstrdup(optarg); break; case 'P': register_password = xstrdup(optarg); break; case 's': silent_mode = true; break; case 'U': if (strchr(optarg, '\\')) register_username = xstrdup(optarg); else /* Prepend .\ for local accounts */ { register_username = malloc(strlen(optarg) + 3); if (!register_username) { write_stderr(_("%s: out of memory\n"), progname); exit(1); } strcpy(register_username, ".\\"); strcat(register_username, optarg); } break; case 'w': do_wait = true; wait_set = true; break; case 'W': do_wait = false; wait_set = true; break; default: write_stderr(_("%s: invalid option %s\n"), progname, optarg); do_advice(); exit(1); } } /* Process an action */ if (optind < argc) { if (ctl_command != NO_COMMAND) { write_stderr(_("%s: too many command-line arguments (first is \"%s\")\n"), progname, argv[optind]); do_advice(); exit(1); } if (strcmp(argv[optind], "start") == 0) ctl_command = START_COMMAND; else if (strcmp(argv[optind], "stop") == 0) ctl_command = STOP_COMMAND; else if (strcmp(argv[optind], "restart") == 0) ctl_command = RESTART_COMMAND; else if (strcmp(argv[optind], "reload") == 0) ctl_command = RELOAD_COMMAND; else if (strcmp(argv[optind], "status") == 0) ctl_command = STATUS_COMMAND; else if (strcmp(argv[optind], "kill") == 0) { if (argc - optind < 3) { write_stderr(_("%s: missing arguments for kill mode\n"), progname); do_advice(); exit(1); } ctl_command = KILL_COMMAND; set_sig(argv[++optind]); killproc = atol(argv[++optind]); }#if defined(WIN32) || defined(__CYGWIN__) else if (strcmp(argv[optind], "register") == 0) ctl_command = REGISTER_COMMAND; else if (strcmp(argv[optind], "unregister") == 0) ctl_command = UNREGISTER_COMMAND; else if (strcmp(argv[optind], "runservice") == 0) ctl_command = RUN_AS_SERVICE_COMMAND;#endif else { write_stderr(_("%s: unrecognized operation mode \"%s\"\n"), progname, argv[optind]); do_advice(); exit(1); } optind++; } } if (ctl_command == NO_COMMAND) { write_stderr(_("%s: no operation specified\n"), progname); do_advice(); exit(1); } /* Note we put any -D switch into the env var above */ pg_data = getenv("PGDATA"); if (pg_data) { pg_data = xstrdup(pg_data); canonicalize_path(pg_data); } if (pg_data == NULL && ctl_command != KILL_COMMAND && ctl_command != UNREGISTER_COMMAND) { write_stderr(_("%s: no database directory specified " "and environment variable PGDATA unset\n"), progname); do_advice(); exit(1); } if (!wait_set) { switch (ctl_command) { case RESTART_COMMAND: case START_COMMAND: do_wait = false; break; case STOP_COMMAND: do_wait = true; break; default: break; } } if (ctl_command == RELOAD_COMMAND) { sig = SIGHUP; do_wait = false; } if (pg_data != NULL) { snprintf(def_postopts_file, MAXPGPATH, "%s/postmaster.opts.default", pg_data); snprintf(postopts_file, MAXPGPATH, "%s/postmaster.opts", pg_data); snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data); snprintf(conf_file, MAXPGPATH, "%s/postgresql.conf", pg_data); } switch (ctl_command) { 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 KILL_COMMAND: do_kill(killproc); break;#if defined(WIN32) || defined(__CYGWIN__) 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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -