PostgreSQL Source Code git master
shell_archive.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * shell_archive.c
4 *
5 * This archiving function uses a user-specified shell command (the
6 * archive_command GUC) to copy write-ahead log files. It is used as the
7 * default, but other modules may define their own custom archiving logic.
8 *
9 * Copyright (c) 2022-2025, PostgreSQL Global Development Group
10 *
11 * IDENTIFICATION
12 * src/backend/archive/shell_archive.c
13 *
14 *-------------------------------------------------------------------------
15 */
16#include "postgres.h"
17
18#include <sys/wait.h>
19
20#include "access/xlog.h"
23#include "common/percentrepl.h"
24#include "pgstat.h"
25
28 const char *file,
29 const char *path);
31
33 .startup_cb = NULL,
34 .check_configured_cb = shell_archive_configured,
35 .archive_file_cb = shell_archive_file,
36 .shutdown_cb = shell_archive_shutdown
37};
38
41{
43}
44
45static bool
47{
48 if (XLogArchiveCommand[0] != '\0')
49 return true;
50
51 arch_module_check_errdetail("\"%s\" is not set.",
52 "archive_command");
53 return false;
54}
55
56static bool
58 const char *path)
59{
60 char *xlogarchcmd;
61 char *nativePath = NULL;
62 int rc;
63
64 if (path)
65 {
66 nativePath = pstrdup(path);
67 make_native_path(nativePath);
68 }
69
71 "archive_command", "fp",
72 file, nativePath);
73
75 (errmsg_internal("executing archive command \"%s\"",
76 xlogarchcmd)));
77
78 fflush(NULL);
79 pgstat_report_wait_start(WAIT_EVENT_ARCHIVE_COMMAND);
80 rc = system(xlogarchcmd);
82
83 if (rc != 0)
84 {
85 /*
86 * If either the shell itself, or a called command, died on a signal,
87 * abort the archiver. We do this because system() ignores SIGINT and
88 * SIGQUIT while waiting; so a signal is very likely something that
89 * should have interrupted us too. Also die if the shell got a hard
90 * "command not found" type of error. If we overreact it's no big
91 * deal, the postmaster will just start the archiver again.
92 */
93 int lev = wait_result_is_any_signal(rc, true) ? FATAL : LOG;
94
95 if (WIFEXITED(rc))
96 {
97 ereport(lev,
98 (errmsg("archive command failed with exit code %d",
99 WEXITSTATUS(rc)),
100 errdetail("The failed archive command was: %s",
101 xlogarchcmd)));
102 }
103 else if (WIFSIGNALED(rc))
104 {
105#if defined(WIN32)
106 ereport(lev,
107 (errmsg("archive command was terminated by exception 0x%X",
108 WTERMSIG(rc)),
109 errhint("See C include file \"ntstatus.h\" for a description of the hexadecimal value."),
110 errdetail("The failed archive command was: %s",
111 xlogarchcmd)));
112#else
113 ereport(lev,
114 (errmsg("archive command was terminated by signal %d: %s",
115 WTERMSIG(rc), pg_strsignal(WTERMSIG(rc))),
116 errdetail("The failed archive command was: %s",
117 xlogarchcmd)));
118#endif
119 }
120 else
121 {
122 ereport(lev,
123 (errmsg("archive command exited with unrecognized status %d",
124 rc),
125 errdetail("The failed archive command was: %s",
126 xlogarchcmd)));
127 }
128 pfree(xlogarchcmd);
129
130 return false;
131 }
132 pfree(xlogarchcmd);
133
134 elog(DEBUG1, "archived write-ahead log file \"%s\"", file);
135 return true;
136}
137
138static void
140{
141 elog(DEBUG1, "archiver process shutting down");
142}
#define arch_module_check_errdetail
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define LOG
Definition: elog.h:31
#define DEBUG3
Definition: elog.h:28
#define FATAL
Definition: elog.h:41
#define DEBUG1
Definition: elog.h:30
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
char * pstrdup(const char *in)
Definition: mcxt.c:1699
void pfree(void *pointer)
Definition: mcxt.c:1524
char * replace_percent_placeholders(const char *instr, const char *param_name, const char *letters,...)
Definition: percentrepl.c:59
const char * pg_strsignal(int signum)
Definition: pgstrsignal.c:39
void make_native_path(char *filename)
Definition: path.c:236
static void shell_archive_shutdown(ArchiveModuleState *state)
static const ArchiveModuleCallbacks shell_archive_callbacks
Definition: shell_archive.c:32
const ArchiveModuleCallbacks * shell_archive_init(void)
Definition: shell_archive.c:40
static bool shell_archive_configured(ArchiveModuleState *state)
Definition: shell_archive.c:46
static bool shell_archive_file(ArchiveModuleState *state, const char *file, const char *path)
Definition: shell_archive.c:57
ArchiveStartupCB startup_cb
Definition: regguts.h:323
bool wait_result_is_any_signal(int exit_status, bool include_command_not_found)
Definition: wait_error.c:121
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:85
static void pgstat_report_wait_end(void)
Definition: wait_event.h:101
#define WIFEXITED(w)
Definition: win32_port.h:150
#define WIFSIGNALED(w)
Definition: win32_port.h:151
#define WTERMSIG(w)
Definition: win32_port.h:153
#define WEXITSTATUS(w)
Definition: win32_port.h:152
char * XLogArchiveCommand
Definition: xlog.c:120