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-2023, 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"
21 #include "archive/archive_module.h"
22 #include "archive/shell_archive.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 
45 static bool
47 {
48  return XLogArchiveCommand[0] != '\0';
49 }
50 
51 static bool
53  const char *path)
54 {
55  char *xlogarchcmd;
56  char *nativePath = NULL;
57  int rc;
58 
59  if (path)
60  {
61  nativePath = pstrdup(path);
62  make_native_path(nativePath);
63  }
64 
66  "archive_command", "fp",
67  file, nativePath);
68 
69  if (nativePath)
70  pfree(nativePath);
71 
73  (errmsg_internal("executing archive command \"%s\"",
74  xlogarchcmd)));
75 
76  fflush(NULL);
78  rc = system(xlogarchcmd);
80 
81  if (rc != 0)
82  {
83  /*
84  * If either the shell itself, or a called command, died on a signal,
85  * abort the archiver. We do this because system() ignores SIGINT and
86  * SIGQUIT while waiting; so a signal is very likely something that
87  * should have interrupted us too. Also die if the shell got a hard
88  * "command not found" type of error. If we overreact it's no big
89  * deal, the postmaster will just start the archiver again.
90  */
91  int lev = wait_result_is_any_signal(rc, true) ? FATAL : LOG;
92 
93  if (WIFEXITED(rc))
94  {
95  ereport(lev,
96  (errmsg("archive command failed with exit code %d",
97  WEXITSTATUS(rc)),
98  errdetail("The failed archive command was: %s",
99  xlogarchcmd)));
100  }
101  else if (WIFSIGNALED(rc))
102  {
103 #if defined(WIN32)
104  ereport(lev,
105  (errmsg("archive command was terminated by exception 0x%X",
106  WTERMSIG(rc)),
107  errhint("See C include file \"ntstatus.h\" for a description of the hexadecimal value."),
108  errdetail("The failed archive command was: %s",
109  xlogarchcmd)));
110 #else
111  ereport(lev,
112  (errmsg("archive command was terminated by signal %d: %s",
113  WTERMSIG(rc), pg_strsignal(WTERMSIG(rc))),
114  errdetail("The failed archive command was: %s",
115  xlogarchcmd)));
116 #endif
117  }
118  else
119  {
120  ereport(lev,
121  (errmsg("archive command exited with unrecognized status %d",
122  rc),
123  errdetail("The failed archive command was: %s",
124  xlogarchcmd)));
125  }
126 
127  return false;
128  }
129 
130  pfree(xlogarchcmd);
131 
132  elog(DEBUG1, "archived write-ahead log file \"%s\"", file);
133  return true;
134 }
135 
136 static void
138 {
139  elog(DEBUG1, "archiver process shutting down");
140 }
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1156
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int errhint(const char *fmt,...)
Definition: elog.c:1316
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#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 ereport(elevel,...)
Definition: elog.h:149
static void const char fflush(stdout)
char * pstrdup(const char *in)
Definition: mcxt.c:1644
void pfree(void *pointer)
Definition: mcxt.c:1456
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:42
void make_native_path(char *filename)
Definition: path.c:167
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:52
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
@ WAIT_EVENT_ARCHIVE_COMMAND
Definition: wait_event.h:84
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:271
static void pgstat_report_wait_end(void)
Definition: wait_event.h:287
#define WIFEXITED(w)
Definition: win32_port.h:160
#define WIFSIGNALED(w)
Definition: win32_port.h:161
#define WTERMSIG(w)
Definition: win32_port.h:163
#define WEXITSTATUS(w)
Definition: win32_port.h:162
char * XLogArchiveCommand
Definition: xlog.c:123