]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
systemctl: add --timestamp to change timestamp print format 16221/head
authorLuca Boccassi <luca.boccassi@microsoft.com>
Fri, 19 Jun 2020 10:26:22 +0000 (11:26 +0100)
committerLuca Boccassi <luca.boccassi@microsoft.com>
Wed, 19 Aug 2020 14:30:13 +0000 (15:30 +0100)
Timestamps for unit start/stop are recorded with microsecond granularity,
but status and show truncate to second granularity by default.
Add a --timestamp=pretty|us|utc option to allow including the microseconds
or to use the UTC TZ to all timestamps printed by systemctl.

man/systemctl.xml
shell-completion/bash/systemctl.in
shell-completion/zsh/_systemctl.in
src/systemctl/systemctl.c

index 506f9ca68f870b4c87928a9833c0c29b4ac00a6e..bb3a29664530418db7b06afea848c70b0d658425 100644 (file)
@@ -2134,6 +2134,20 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--timestamp=</option></term>
+
+        <listitem>
+          <para>Takes one of <literal>pretty</literal> (the default),
+          <literal>us</literal>, <literal>µs</literal>, <literal>utc</literal>.
+          Changes the format of printed timestamps.
+          <literal>pretty</literal>: <literal>Day YYYY-MM-DD HH:MM:SS TZ</literal>
+          <literal>us</literal> or <literal>µs</literal>: <literal>Day YYYY-MM-DD HH:MM:SS.UUUUUU TZ</literal>
+          <literal>utc</literal>: <literal>Day YYYY-MM-DD HH:MM:SS UTC</literal></para>
+          <literal>us+utc</literal> or <literal>µs+utc</literal>: <literal>Day YYYY-MM-DD HH:MM:SS.UUUUUU UTC</literal>
+        </listitem>
+      </varlistentry>
+
       <xi:include href="user-system-options.xml" xpointer="host" />
       <xi:include href="user-system-options.xml" xpointer="machine" />
 
index fdbe32e5f7aeeed3ac967c6d411c34dadfdb45b4..b5bd727abf06170f468af7102902e9bfd720f301 100644 (file)
@@ -127,7 +127,7 @@ _systemctl () {
                              --quiet -q --system --user --version --runtime --recursive -r --firmware-setup
                              --show-types -i --ignore-inhibitors --plain --failed --value --fail --dry-run --wait'
         [ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --job-mode --root
-                             --preset-mode -n --lines -o --output -M --machine --message'
+                             --preset-mode -n --lines -o --output -M --machine --message --timestamp'
     )
 
     if __contains_word "--user" ${COMP_WORDS[*]}; then
@@ -176,6 +176,9 @@ _systemctl () {
             --machine|-M)
                 comps=$( __get_machines )
                 ;;
+            --timestamp)
+                comps='pretty us µs utc us+utc µs+utc'
+                ;;
         esac
         COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
         return 0
index 582d469c350e660a3eb68cd5f9cb19a2bb0678d6..c59beb157c3d834edaa8eef53421f7165b5db9d6 100644 (file)
@@ -431,6 +431,13 @@ done
         _values -s , "${_modes[@]}"
     }
 
+(( $+functions[_systemctl_timestamp] )) ||
+    _systemctl_timestamp() {
+        local -a _styles
+        _styles=(help pretty us µs utc us+utc µs+utc)
+        _values -s , "${_styles[@]}"
+    }
+
 # Build arguments for "systemctl" to be used in completion.
 local -a _modes; _modes=("--user" "--system")
 # Use the last mode (they are exclusive and the last one is used).
@@ -471,4 +478,5 @@ _arguments -s \
     '--firmware-setup[Tell the firmware to show the setup menu on next boot]' \
     '--plain[When used with list-dependencies, print output as a list]' \
     '--failed[Show failed units]' \
+    '--timestamp=[Change format of printed timestamps]:style:_systemctl_timestamp' \
     '*::systemctl command:_systemctl_commands'
index 6e6e1810a046b698ee4c625be9dad613a625f3eb..032932fd776080b5569f9ed5a541138397feb2c9 100644 (file)
@@ -170,6 +170,7 @@ static bool arg_now = false;
 static bool arg_jobs_before = false;
 static bool arg_jobs_after = false;
 static char **arg_clean_what = NULL;
+static TimestampStyle arg_timestamp_style = TIMESTAMP_PRETTY;
 
 /* This is a global cache that will be constructed on first use. */
 static Hashmap *cached_id_map = NULL;
@@ -4195,7 +4196,7 @@ static void print_status_info(
                                                                             i->active_exit_timestamp;
 
         s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
-        s2 = format_timestamp(since2, sizeof(since2), timestamp);
+        s2 = format_timestamp_style(since2, sizeof(since2), timestamp, arg_timestamp_style);
 
         if (s1)
                 printf(" since %s; %s\n", s2, s1);
@@ -4229,7 +4230,7 @@ static void print_status_info(
                 dual_timestamp_get(&nw);
                 next_elapse = calc_next_elapse(&nw, &next);
                 next_rel_time = format_timestamp_relative(tstamp1, sizeof tstamp1, next_elapse);
-                next_time = format_timestamp(tstamp2, sizeof tstamp2, next_elapse);
+                next_time = format_timestamp_style(tstamp2, sizeof tstamp2, next_elapse, arg_timestamp_style);
 
                 if (next_time && next_rel_time)
                         printf("%s; %s\n", next_time, next_rel_time);
@@ -4254,7 +4255,7 @@ static void print_status_info(
                 int n = 0;
 
                 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
-                s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
+                s2 = format_timestamp_style(since2, sizeof(since2), i->condition_timestamp, arg_timestamp_style);
 
                 printf("  Condition: start %scondition failed%s at %s%s%s\n",
                        ansi_highlight_yellow(), ansi_normal(),
@@ -4276,7 +4277,7 @@ static void print_status_info(
 
         if (!i->assert_result && i->assert_timestamp > 0) {
                 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
-                s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
+                s2 = format_timestamp_style(since2, sizeof(since2), i->assert_timestamp, arg_timestamp_style);
 
                 printf("     Assert: start %sassertion failed%s at %s%s%s\n",
                        ansi_highlight_red(), ansi_normal(),
@@ -5037,7 +5038,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                         while ((r = sd_bus_message_read(m, "(sst)", &base, &spec, &next_elapse)) > 0) {
                                 char timestamp[FORMAT_TIMESTAMP_MAX] = "n/a";
 
-                                (void) format_timestamp(timestamp, sizeof(timestamp), next_elapse);
+                                (void) format_timestamp_style(timestamp, sizeof(timestamp), next_elapse, arg_timestamp_style);
                                 bus_print_property_valuef(name, expected_value, value,
                                                           "{ %s=%s ; next_elapse=%s }", base, spec, timestamp);
                         }
@@ -5077,8 +5078,8 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                                                   strna(info.path),
                                                                   strna(tt),
                                                                   strna(o),
-                                                                  strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
-                                                                  strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
+                                                                  strna(format_timestamp_style(timestamp1, sizeof(timestamp1), info.start_timestamp, arg_timestamp_style)),
+                                                                  strna(format_timestamp_style(timestamp2, sizeof(timestamp2), info.exit_timestamp, arg_timestamp_style)),
                                                                   info.pid,
                                                                   sigchld_code_to_string(info.code),
                                                                   info.status,
@@ -5090,8 +5091,8 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
                                                                   strna(info.path),
                                                                   strna(tt),
                                                                   yes_no(info.ignore),
-                                                                  strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
-                                                                  strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
+                                                                  strna(format_timestamp_style(timestamp1, sizeof(timestamp1), info.start_timestamp, arg_timestamp_style)),
+                                                                  strna(format_timestamp_style(timestamp2, sizeof(timestamp2), info.exit_timestamp, arg_timestamp_style)),
                                                                   info.pid,
                                                                   sigchld_code_to_string(info.code),
                                                                   info.status,
@@ -5754,7 +5755,7 @@ static int show_system_status(sd_bus *bus) {
         printf("   Failed: %" PRIu32 " units\n", mi.n_failed_units);
 
         printf("    Since: %s; %s\n",
-               format_timestamp(since2, sizeof(since2), mi.timestamp),
+               format_timestamp_style(since2, sizeof(since2), mi.timestamp, arg_timestamp_style),
                format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
 
         printf("   CGroup: %s\n", mi.control_group ?: "/");
@@ -7804,6 +7805,11 @@ static int systemctl_help(void) {
                "     --boot-loader-entry=NAME\n"
                "                         Boot into a specific boot loader entry on next boot\n"
                "     --plain             Print unit dependencies as a list instead of a tree\n"
+               "     --timestamp=FORMAT  Change format of printed timestamps.\n"
+               "                         'pretty' (default): 'Day YYYY-MM-DD HH:MM:SS TZ\n"
+               "                         'us': 'Day YYYY-MM-DD HH:MM:SS.UUUUUU TZ\n"
+               "                         'utc': 'Day YYYY-MM-DD HH:MM:SS UTC\n"
+               "                         'us+utc': 'Day YYYY-MM-DD HH:MM:SS.UUUUUU UTC\n"
                "\nSee the %2$s for details.\n"
                , program_invocation_short_name
                , link
@@ -8052,6 +8058,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 ARG_WAIT,
                 ARG_WHAT,
                 ARG_REBOOT_ARG,
+                ARG_TIMESTAMP_STYLE,
         };
 
         static const struct option options[] = {
@@ -8106,6 +8113,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 { "show-transaction",    no_argument,       NULL, 'T'                     },
                 { "what",                required_argument, NULL, ARG_WHAT                },
                 { "reboot-argument",     required_argument, NULL, ARG_REBOOT_ARG          },
+                { "timestamp",           required_argument, NULL, ARG_TIMESTAMP_STYLE     },
                 {}
         };
 
@@ -8505,6 +8513,19 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         arg_reboot_argument = optarg;
                         break;
 
+                case ARG_TIMESTAMP_STYLE:
+                        if (streq(optarg, "help")) {
+                                DUMP_STRING_TABLE(timestamp_style, TimestampStyle, _TIMESTAMP_STYLE_MAX);
+                                return 0;
+                        }
+
+                        arg_timestamp_style = timestamp_style_from_string(optarg);
+                        if (arg_timestamp_style < 0)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "Invalid value: %s.", optarg);
+
+                        break;
+
                 case '.':
                         /* Output an error mimicking getopt, and print a hint afterwards */
                         log_error("%s: invalid option -- '.'", program_invocation_name);
@@ -9130,7 +9151,7 @@ static int logind_schedule_shutdown(void) {
                 return log_warning_errno(r, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error, r));
 
         if (!arg_quiet)
-                log_info("%s scheduled for %s, use 'shutdown -c' to cancel.", log_action, format_timestamp(date, sizeof(date), arg_when));
+                log_info("%s scheduled for %s, use 'shutdown -c' to cancel.", log_action, format_timestamp_style(date, sizeof(date), arg_when, arg_timestamp_style));
         return 0;
 #else
         return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),