github.com/gdubicki/ets@v0.2.3-0.20240420195337-e89d6a2fdbda/README.md (about)

     1  <p align="center">A fork of <a href="https://github.com/zmwangx/ets">https://github.com/zmwangx/ets</a>, written by <a href="https://github.com/zmwangx">Zhiming Wang</a></p>
     2  <p align="center">with a release in 2024, maybe it will stay maintained, we'll see!</p>
     3  
     4  <h1 align="center"><img src="assets/logo.svg" height="50" alt="ets" /></h1>
     5  
     6  <p align="center">
     7    <a href="https://github.com/gdubicki/ets/releases"><img src="https://img.shields.io/github/v/release/gdubicki/ets" alt="GitHub release" /></a>
     8    <a href="https://github.com/gdubicki/ets/actions"><img src="https://github.com/gdubicki/ets/workflows/test/badge.svg?branch=master" alt="Build status" /></a>
     9  </p>
    10  
    11  <p align="center"><img src="assets/animation.svg" alt="ets" /></p>
    12  <p align="center"><img src="assets/animation-progressbar.svg" alt="ets" /></p>
    13  
    14  `ets` is a command output timestamper — it prefixes each line of a command's output with a timestamp.
    15  
    16  The purpose of `ets` is similar to that of moreutils [`ts(1)`](https://manpages.ubuntu.com/manpages/focal/en/man1/ts.1.html), but `ets` differentiates itself from similar offerings by running commands directly within ptys, hence solving thorny issues like pipe buffering and commands disabling color and interactive features when detecting a pipe as output. (`ets` does provide a reading-from-stdin mode if you insist.) `ets` also recognizes carriage return as a line seperator, so it doesn't choke if your command prints a progress bar. A more detailed comparison of `ets` and `ts` can be found [below](#comparison-to-moreutils-ts).
    17  
    18  `ets` currently supports macOS, Linux, and various other *ix variants.
    19  
    20  <!-- START doctoc generated TOC please keep comment here to allow auto update -->
    21  <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
    22  
    23  
    24  - [Examples](#examples)
    25  - [Installation](#installation)
    26  - [Usage](#usage)
    27  - [Comparison to moreutils ts](#comparison-to-moreutils-ts)
    28  - [Changelog](#changelog)
    29  - [License](#license)
    30  
    31  <!-- END doctoc generated TOC please keep comment here to allow auto update -->
    32  
    33  ## Examples
    34  
    35  Run a command with `ets`:
    36  
    37  ```console
    38  $ ets ping localhost
    39  [2020-06-16 17:13:03] PING localhost (127.0.0.1): 56 data bytes
    40  [2020-06-16 17:13:03] 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.036 ms
    41  [2020-06-16 17:13:04] 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.077 ms
    42  [2020-06-16 17:13:05] 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.037 ms
    43  ...
    44  ```
    45  
    46  Run a shell command:
    47  
    48  ```console
    49  $ ets 'ping localhost | grep icmp'
    50  [2020-06-16 17:13:03] 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.036 ms
    51  [2020-06-16 17:13:04] 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.077 ms
    52  [2020-06-16 17:13:05] 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.037 ms
    53  ...
    54  ```
    55  
    56  Pipe command output into stdin:
    57  
    58  ```console
    59  $ ping localhost | grep icmp | ets
    60  [2020-06-16 17:13:03] 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.036 ms
    61  [2020-06-16 17:13:04] 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.077 ms
    62  [2020-06-16 17:13:05] 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.037 ms
    63  ...
    64  ```
    65  
    66  Show elapsed time:
    67  
    68  ```console
    69  $ ets -s ping -i5 localhost
    70  [00:00:00] PING localhost (127.0.0.1): 56 data bytes
    71  [00:00:00] 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.039 ms
    72  [00:00:05] 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.031 ms
    73  [00:00:10] 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.030 ms
    74  [00:00:15] 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.045 ms
    75  ...
    76  ```
    77  
    78  Show incremental time (since last timestamp):
    79  
    80  ```console
    81  $ ets -i ping -i5 localhost
    82  [00:00:00] PING localhost (127.0.0.1): 56 data bytes
    83  [00:00:00] 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.043 ms
    84  [00:00:05] 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.047 ms
    85  [00:00:05] 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.116 ms
    86  [00:00:05] 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.071 ms
    87  ...
    88  ```
    89  
    90  Use a different timestamp format:
    91  
    92  ```console
    93  $ ets -f '%b %d %T|' ping localhost
    94  Jun 16 17:13:03| PING localhost (127.0.0.1): 56 data bytes
    95  Jun 16 17:13:03| 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.036 ms
    96  Jun 16 17:13:04| 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.077 ms
    97  Jun 16 17:13:05| 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.037 ms
    98  ...
    99  ```
   100  
   101  Millisecond precision (microsecond available too):
   102  
   103  ```console
   104  $ ets -s -f '[%T.%L]' ping -i 0.1 localhost
   105  [00:00:00.004] PING localhost (127.0.0.1): 56 data bytes
   106  [00:00:00.004] 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.032 ms
   107  [00:00:00.108] 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.038 ms
   108  [00:00:00.209] 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.051 ms
   109  [00:00:00.311] 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.049 ms
   110  ...
   111  ```
   112  
   113  Use a different timezone:
   114  
   115  ```console
   116  $ ets ping localhost  # UTC
   117  [2020-06-16 09:13:03] PING localhost (127.0.0.1): 56 data bytes
   118  [2020-06-16 09:13:03] 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.036 ms
   119  [2020-06-16 09:13:04] 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.077 ms
   120  [2020-06-16 09:13:05] 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.037 ms
   121  ```
   122  
   123  ```console
   124  $ ets -z America/Los_Angeles -f '[%F %T%z]' ping localhost
   125  [2020-06-16 02:13:03-0700] PING localhost (127.0.0.1): 56 data bytes
   126  [2020-06-16 02:13:03-0700] 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.036 ms
   127  [2020-06-16 02:13:04-0700] 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.077 ms
   128  [2020-06-16 02:13:05-0700] 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.037 ms
   129  ```
   130  
   131  Color the timestamps:
   132  
   133  ```console
   134  $ ets -c ping localhost
   135  ...
   136  ```
   137  
   138  ## Installation
   139  
   140  - On macOS you can install ets with Homebrew:
   141  
   142    ```
   143    brew tap gdubicki/ets https://github.com/gdubicki/ets
   144    brew install gdubicki/ets/ets
   145    ```
   146  
   147  - On macOS and Linux you get download a prebuilt tarball/package from the [release page](https://github.com/gdubicki/ets/releases).
   148  
   149  - On Arch Linux you can install the [ets-bin](https://aur.archlinux.org/packages/ets-bin/) binary package from AUR:
   150  
   151    ```sh
   152    pacman -S ets-bin
   153    # or
   154    yay -S ets-bin
   155    ```
   156  
   157  - On a supported platform, if you have the Go toolchain installed, you may install with
   158  
   159    ```
   160    go get github.com/gdubicki/ets
   161    ```
   162  
   163  ## Usage
   164  
   165  <!-- begin manpage -->
   166  
   167  ```
   168  
   169  ETS(1)                    BSD General Commands Manual                   ETS(1)
   170  
   171  NAME
   172       ets -- command output timestamper
   173  
   174  SYNOPSIS
   175       ets [-s | -i] [-f format] [-u | -z timezone] command [arg ...]
   176       ets [options] shell_command
   177       ets [options]
   178  
   179  DESCRIPTION
   180       ets prefixes each line of a command's output with a timestamp. Lines are
   181       delimited by CR, LF, or CRLF.
   182  
   183       The three forms in SYNOPSIS correspond to three command execution modes:
   184  
   185       o If given a single command without whitespace(s), or a command and its
   186         arguments, execute the command with exec in a pty;
   187  
   188       o If given a single command with whitespace(s), the command is treated as
   189         a shell command and executed as `SHELL -c shell_command', where SHELL
   190         is the current user's login shell, or sh if login shell cannot be
   191         determined;
   192  
   193       o If given no command, output is read from stdin, and the user is respon-
   194         sible for piping in a command's output.
   195  
   196       There are three mutually exclusive timestamp modes:
   197  
   198       o The default is absolute time mode, where timestamps from the wall clock
   199         are shown;
   200  
   201       o -s, --elapsed turns on elapsed time mode, where every timestamp is the
   202         time elapsed from the start of the command (using a monotonic clock);
   203  
   204       o -i, --incremental turns on incremental time mode, where every timestamp
   205         is the time elapsed since the last timestamp (using a monotonic clock).
   206  
   207       The default format of the prefixed timestamps depends on the timestamp
   208       mode active. Users may supply a custom format string with the -f,
   209       --format option.
   210  
   211       The timezone for absolute timestamps can be controlled via the -u, --utc
   212       and -z, --timezone options. Local time is used by default.
   213  
   214       The full list of options:
   215  
   216       -s, --elapsed
   217                Run in elapsed time mode.
   218  
   219       -i, --incremental
   220                Run in incremental time mode.
   221  
   222       -f, --format format
   223                Use custom strftime(3)-style format string format for prefixed
   224                timestamps.
   225  
   226                The default is ``[%Y-%m-%d %H:%M:%S]'' for absolute time mode
   227                and ``[%H:%M:%S]'' for elapsed and incremental time modes.
   228  
   229                See FORMATTING DIRECTIVES for details.
   230  
   231       -u, --utc
   232                Use UTC for absolute timestamps instead of local time.
   233  
   234                This option is mutually exclusive with --z, --timezone.
   235  
   236       -z, --timezone timezone
   237                Use timezone for absolute timestamps instead of local time.
   238                timezone is an IANA time zone name, e.g.
   239                ``America/Los_Angeles''.
   240  
   241                This option is mutually exclusive with -u, --utc.
   242  
   243       -c, --color
   244                Print timestamps in color.
   245  
   246  FORMATTING DIRECTIVES
   247       Formatting directives largely match strftime(3)'s directives on FreeBSD
   248       and macOS, with the following differences:
   249  
   250       o Additional directives %f for microsecond and %L for millisecond are
   251         supported.
   252  
   253       o POSIX locale extensions %E* and %O* are not supported;
   254  
   255       o glibc extensions %-*, %_*, and %0* are not supported;
   256  
   257       o Directives %G, %g, and %+ are not supported.
   258  
   259       Below is the full list of supported directives:
   260  
   261       %A    is replaced by national representation of the full weekday name.
   262  
   263       %a    is replaced by national representation of the abbreviated weekday
   264             name.
   265  
   266       %B    is replaced by national representation of the full month name.
   267  
   268       %b    is replaced by national representation of the abbreviated month
   269             name.
   270  
   271       %C    is replaced by (year / 100) as decimal number; single digits are
   272             preceded by a zero.
   273  
   274       %c    is replaced by national representation of time and date.
   275  
   276       %D    is equivalent to ``%m/%d/%y''.
   277  
   278       %d    is replaced by the day of the month as a decimal number (01-31).
   279  
   280       %e    is replaced by the day of the month as a decimal number (1-31);
   281             single digits are preceded by a blank.
   282  
   283       %F    is equivalent to ``%Y-%m-%d''.
   284  
   285       %f    is replaced by the microsecond as a decimal number (000000-999999).
   286  
   287       %H    is replaced by the hour (24-hour clock) as a decimal number
   288             (00-23).
   289  
   290       %h    the same as %b.
   291  
   292       %I    is replaced by the hour (12-hour clock) as a decimal number
   293             (01-12).
   294  
   295       %j    is replaced by the day of the year as a decimal number (001-366).
   296  
   297       %k    is replaced by the hour (24-hour clock) as a decimal number (0-23);
   298             single digits are preceded by a blank.
   299  
   300       %L    is replaced by the millisecond as a decimal number (000-999).
   301  
   302       %l    is replaced by the hour (12-hour clock) as a decimal number (1-12);
   303             single digits are preceded by a blank.
   304  
   305       %M    is replaced by the minute as a decimal number (00-59).
   306  
   307       %m    is replaced by the month as a decimal number (01-12).
   308  
   309       %n    is replaced by a newline.
   310  
   311       %p    is replaced by national representation of either "ante meridiem"
   312             (a.m.)  or "post meridiem" (p.m.)  as appropriate.
   313  
   314       %R    is equivalent to ``%H:%M''.
   315  
   316       %r    is equivalent to ``%I:%M:%S %p''.
   317  
   318       %S    is replaced by the second as a decimal number (00-60).
   319  
   320       %s    is replaced by the number of seconds since the Epoch, UTC (see
   321             mktime(3)).
   322  
   323       %T    is equivalent to ``%H:%M:%S''.
   324  
   325       %t    is replaced by a tab.
   326  
   327       %U    is replaced by the week number of the year (Sunday as the first day
   328             of the week) as a decimal number (00-53).
   329  
   330       %u    is replaced by the weekday (Monday as the first day of the week) as
   331             a decimal number (1-7).
   332  
   333       %V    is replaced by the week number of the year (Monday as the first day
   334             of the week) as a decimal number (01-53).  If the week containing
   335             January 1 has four or more days in the new year, then it is week 1;
   336             otherwise it is the last week of the previous year, and the next
   337             week is week 1.
   338  
   339       %v    is equivalent to ``%e-%b-%Y''.
   340  
   341       %W    is replaced by the week number of the year (Monday as the first day
   342             of the week) as a decimal number (00-53).
   343  
   344       %w    is replaced by the weekday (Sunday as the first day of the week) as
   345             a decimal number (0-6).
   346  
   347       %X    is replaced by national representation of the time.
   348  
   349       %x    is replaced by national representation of the date.
   350  
   351       %Y    is replaced by the year with century as a decimal number.
   352  
   353       %y    is replaced by the year without century as a decimal number
   354             (00-99).
   355  
   356       %Z    is replaced by the time zone name.
   357  
   358       %z    is replaced by the time zone offset from UTC; a leading plus sign
   359             stands for east of UTC, a minus sign for west of UTC, hours and
   360             minutes follow with two digits each and no delimiter between them
   361             (common form for RFC 822 date headers).
   362  
   363       %%    is replaced by `%'.
   364  
   365  SEE ALSO
   366       ts(1), strftime(3)
   367  
   368  HISTORY
   369       The name ets comes from ``enhanced ts'', referring to moreutils ts(1).
   370  
   371  AUTHORS
   372       Zhiming Wang <i@zhimingwang.org>
   373  
   374                                   July 3, 2020
   375  ```
   376  
   377  <!-- end manpage -->
   378  
   379  ## Comparison to moreutils ts
   380  
   381  Advantages:
   382  
   383  - Runs commands in ptys, making ets mostly transparent and avoiding pipe-related issues like buffering and lost coloring and interactivity.
   384  - Recognizes carriage return as line separator, does not choke on progress bars.
   385  - Has better operating defaults (uses monotonic clock where appropriate) and better formatting defaults (subjective).
   386  - Supports alternative time zones.
   387  - Is written in Go, not Perl, so you install a single executable, not script plus modules.
   388  - Has an executable name that doesn't conflict with other known packages. moreutils as a whole is a conflicting hell, and ts alone conflicts with at least task-spooler.
   389  
   390  Disadvantages:
   391  
   392  - Needs an additional `-f` for format string, because ets reserves positional arguments for its core competency. Hopefully offset by better default.
   393  - Does not support the `-r` mode of ts. It's a largely unrelated mode of operation and I couldn't even get `ts -r` to work anywhere, maybe because optional dependencies aren't satisfied, or maybe I misunderstood the feature altogether. Anyway, not interested.
   394  - Supports fewer formatting directives. Let me know if this is actually an issue, it could be fixable.
   395  
   396  ## Changelog
   397  
   398  See [here](./CHANGELOG.md).
   399  
   400  ## License
   401  
   402  Copyright © 2020 Zhiming Wang <i@zhimingwang.org>
   403  
   404  The project is distributed under [the MIT license](https://opensource.org/licenses/MIT).
   405  
   406  Special thanks to DinosoftLab on None Project for the [hourglass icon](https://thenounproject.com/term/hourglass/1674538/) used in the logo, and [termtosvg](https://github.com/nbedos/termtosvg) for the animated terminal recording.