notify: add --stopping + --reloading switches

These wrap RELOADING=1 and STOPPING=1 messages. The former is
particularly useful, since we want to insert the MONOTONIC_USEC= field
into the message automatically, which is easy from C but harder from
shell.
This commit is contained in:
Lennart Poettering 2023-01-03 12:55:50 +01:00
parent 5d71e463f4
commit fd0f4da545
2 changed files with 86 additions and 40 deletions

View file

@ -30,20 +30,18 @@
<refsect1>
<title>Description</title>
<para><command>systemd-notify</command> may be called by daemon
scripts to notify the init system about status changes. It can be
used to send arbitrary information, encoded in an
environment-block-like list of strings. Most importantly, it can be
used for start-up completion notification.</para>
<para><command>systemd-notify</command> may be called by service scripts to notify the invoking service
manager about status changes. It can be used to send arbitrary information, encoded in an
environment-block-like list of strings. Most importantly, it can be used for start-up completion
notification.</para>
<para>This is mostly just a wrapper around
<function>sd_notify()</function> and makes this functionality
<para>This is mostly just a wrapper around <function>sd_notify()</function> and makes this functionality
available to shell scripts. For details see
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para>
<para>The command line may carry a list of environment variables
to send as part of the status update.</para>
<para>The command line may carry a list of environment variables to send as part of the status
update.</para>
<para>Note that systemd will refuse reception of status updates from this command unless
<varname>NotifyAccess=</varname> is appropriately set for the service unit this command is called
@ -52,9 +50,9 @@
details.</para>
<para>Note that <function>sd_notify()</function> notifications may be attributed to units correctly only
if either the sending process is still around at the time PID 1 processes the message, or if the sending
process is explicitly runtime-tracked by the service manager. The latter is the case if the service
manager originally forked off the process, i.e. on all processes that match
if either the sending process is still around at the time the service manager processes the message, or
if the sending process is explicitly runtime-tracked by the service manager. The latter is the case if
the service manager originally forked off the process, i.e. on all processes that match
<varname>NotifyAccess=</varname><option>main</option> or
<varname>NotifyAccess=</varname><option>exec</option>. Conversely, if an auxiliary process of the unit
sends an <function>sd_notify()</function> message and immediately exits, the service manager might not be
@ -84,22 +82,42 @@
<varlistentry>
<term><option>--ready</option></term>
<listitem><para>Inform the init system about service start-up
completion. This is equivalent to <command>systemd-notify
READY=1</command>. For details about the semantics of this
option see
<listitem><para>Inform the invoking service manager about service start-up or configuration reload
completion. This is equivalent to <command>systemd-notify READY=1</command>. For details about the
semantics of this option see
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--reloading</option></term>
<listitem><para>Inform the invoking service manager about the beginning of a configuration reload
cycle. This is equivalent to <command>systemd-notify RELOADING=1</command> (but implicitly also sets
a <varname>MONOTONIC_USEC=</varname> field as required for <varname>Type=notify-reload</varname>
services, see
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
for details). For details about the semantics of this option see
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--stopping</option></term>
<listitem><para>Inform the invoking service manager about the beginning of the shutdown phase of the
service. This is equivalent to <command>systemd-notify STOPPING=1</command>. For details about the
semantics of this option see
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--pid=</option></term>
<listitem><para>Inform the service manager about the main PID of the daemon. Takes a PID as
<listitem><para>Inform the service manager about the main PID of the service. Takes a PID as
argument. If the argument is specified as <literal>auto</literal> or omitted, the PID of the process
that invoked <command>systemd-notify</command> is used, except if that's the service manager. If the
argument is specified as <literal>self</literal>, the PID of the <command>systemd-notify</command>
command itself is used, and if <literal>parent</literal> is specified the calling process' PID is
used — even if it is the service manager. This is equivalent to <command>systemd-notify
used — even if it is the service manager. The latter is equivalent to <command>systemd-notify
MAINPID=$PID</command>. For details about the semantics of this option see
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
@ -124,27 +142,26 @@
<varlistentry>
<term><option>--status=</option></term>
<listitem><para>Send a free-form status string for the daemon
to the init systemd. This option takes the status string as
argument. This is equivalent to <command>systemd-notify
STATUS=…</command>. For details about the semantics of this
option see
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
<listitem><para>Send a free-form human readable status string for the daemon to the service
manager. This option takes the status string as argument. This is equivalent to
<command>systemd-notify STATUS=…</command>. For details about the semantics of this option see
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>. This
information is shown in
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
<command>status</command> output, among other places.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--booted</option></term>
<listitem><para>Returns 0 if the system was booted up with
systemd, non-zero otherwise. If this option is passed, no
message is sent. This option is hence unrelated to the other
options. For details about the semantics of this option, see
<listitem><para>Returns 0 if the system was booted up with systemd, non-zero otherwise. If this
option is passed, no message is sent. This option is hence unrelated to the other options. For
details about the semantics of this option, see
<citerefentry><refentrytitle>sd_booted</refentrytitle><manvolnum>3</manvolnum></citerefentry>. An
alternate way to check for this state is to call
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
with the <command>is-system-running</command> command. It will
return <literal>offline</literal> if the system was not booted
with systemd. </para></listitem>
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> with
the <command>is-system-running</command> command. It will return <literal>offline</literal> if the
system was not booted with systemd. </para></listitem>
</varlistentry>
<varlistentry>
@ -176,9 +193,8 @@
<example>
<title>Start-up Notification and Status Updates</title>
<para>A simple shell daemon that sends start-up notifications
after having set up its communication channel. During runtime it
sends further status updates to the init system:</para>
<para>A simple shell daemon that sends start-up notifications after having set up its communication
channel. During runtime it sends further status updates to the init system:</para>
<programlisting>#!/bin/sh
@ -207,5 +223,4 @@ done</programlisting>
<citerefentry><refentrytitle>sd_booted</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View file

@ -23,6 +23,8 @@
#include "user-util.h"
static bool arg_ready = false;
static bool arg_reloading = false;
static bool arg_stopping = false;
static pid_t arg_pid = 0;
static const char *arg_status = NULL;
static bool arg_booted = false;
@ -42,7 +44,10 @@ static int help(void) {
"\n%sNotify the init system about service status updates.%s\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --ready Inform the init system about service start-up completion\n"
" --ready Inform the service manager about service start-up/reload\n"
" completion\n"
" --reloading Inform the service manager about configuration reloading\n"
" --stopping Inform the service manager about service shutdown\n"
" --pid[=PID] Set main PID of daemon\n"
" --uid=USER Set user to send from\n"
" --status=TEXT Set status text\n"
@ -81,6 +86,8 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_READY = 0x100,
ARG_RELOADING,
ARG_STOPPING,
ARG_VERSION,
ARG_PID,
ARG_STATUS,
@ -93,6 +100,8 @@ static int parse_argv(int argc, char *argv[]) {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "ready", no_argument, NULL, ARG_READY },
{ "reloading", no_argument, NULL, ARG_RELOADING },
{ "stopping", no_argument, NULL, ARG_STOPPING },
{ "pid", optional_argument, NULL, ARG_PID },
{ "status", required_argument, NULL, ARG_STATUS },
{ "booted", no_argument, NULL, ARG_BOOTED },
@ -120,6 +129,14 @@ static int parse_argv(int argc, char *argv[]) {
arg_ready = true;
break;
case ARG_RELOADING:
arg_reloading = true;
break;
case ARG_STOPPING:
arg_stopping = true;
break;
case ARG_PID:
if (isempty(optarg) || streq(optarg, "auto")) {
arg_pid = getppid();
@ -176,6 +193,8 @@ static int parse_argv(int argc, char *argv[]) {
if (optind >= argc &&
!arg_ready &&
!arg_stopping &&
!arg_reloading &&
!arg_status &&
!arg_pid &&
!arg_booted) {
@ -187,10 +206,10 @@ static int parse_argv(int argc, char *argv[]) {
}
static int run(int argc, char* argv[]) {
_cleanup_free_ char *status = NULL, *cpid = NULL, *n = NULL;
_cleanup_free_ char *status = NULL, *cpid = NULL, *n = NULL, *monotonic_usec = NULL;
_cleanup_strv_free_ char **final_env = NULL;
char* our_env[4];
unsigned i = 0;
char* our_env[7];
size_t i = 0;
pid_t source_pid;
int r;
@ -212,9 +231,21 @@ static int run(int argc, char* argv[]) {
return r <= 0;
}
if (arg_reloading) {
our_env[i++] = (char*) "RELOADING=1";
if (asprintf(&monotonic_usec, "MONOTONIC_USEC=" USEC_FMT, now(CLOCK_MONOTONIC)) < 0)
return log_oom();
our_env[i++] = monotonic_usec;
}
if (arg_ready)
our_env[i++] = (char*) "READY=1";
if (arg_stopping)
our_env[i++] = (char*) "STOPPING=1";
if (arg_status) {
status = strjoin("STATUS=", arg_status);
if (!status)