• Stars
    star
    109
  • Rank 319,077 (Top 7 %)
  • Language
    Go
  • License
    MIT License
  • Created over 4 years ago
  • Updated 7 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Command output timestamper

ets

GitHub release Build status

ets

ets

ets is a command output timestamper โ€”ย it prefixes each line of a command's output with a timestamp.

The purpose of ets is similar to that of moreutils ts(1), 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.

ets currently supports macOS, Linux, and various other *ix variants.

Examples

Run a command with ets:

$ ets ping localhost
[2020-06-16 17:13:03] PING localhost (127.0.0.1): 56 data bytes
[2020-06-16 17:13:03] 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.036 ms
[2020-06-16 17:13:04] 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.077 ms
[2020-06-16 17:13:05] 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.037 ms
...

Run a shell command:

$ ets 'ping localhost | grep icmp'
[2020-06-16 17:13:03] 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.036 ms
[2020-06-16 17:13:04] 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.077 ms
[2020-06-16 17:13:05] 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.037 ms
...

Pipe command output into stdin:

$ ping localhost | grep icmp | ets
[2020-06-16 17:13:03] 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.036 ms
[2020-06-16 17:13:04] 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.077 ms
[2020-06-16 17:13:05] 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.037 ms
...

Show elapsed time:

$ ets -s ping -i5 localhost
[00:00:00] PING localhost (127.0.0.1): 56 data bytes
[00:00:00] 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.039 ms
[00:00:05] 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.031 ms
[00:00:10] 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.030 ms
[00:00:15] 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.045 ms
...

Show incremental time (since last timestamp):

$ ets -i ping -i5 localhost
[00:00:00] PING localhost (127.0.0.1): 56 data bytes
[00:00:00] 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.043 ms
[00:00:05] 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.047 ms
[00:00:05] 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.116 ms
[00:00:05] 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.071 ms
...

Use a different timestamp format:

$ ets -f '%b %d %T|' ping localhost
Jun 16 17:13:03| PING localhost (127.0.0.1): 56 data bytes
Jun 16 17:13:03| 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.036 ms
Jun 16 17:13:04| 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.077 ms
Jun 16 17:13:05| 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.037 ms
...

Millisecond precision (microsecond available too):

$ ets -s -f '[%T.%L]' ping -i 0.1 localhost
[00:00:00.004] PING localhost (127.0.0.1): 56 data bytes
[00:00:00.004] 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.032 ms
[00:00:00.108] 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.038 ms
[00:00:00.209] 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.051 ms
[00:00:00.311] 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.049 ms
...

Use a different timezone:

$ ets ping localhost  # UTC
[2020-06-16 09:13:03] PING localhost (127.0.0.1): 56 data bytes
[2020-06-16 09:13:03] 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.036 ms
[2020-06-16 09:13:04] 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.077 ms
[2020-06-16 09:13:05] 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.037 ms
$ ets -z America/Los_Angeles -f '[%F %T%z]' ping localhost
[2020-06-16 02:13:03-0700] PING localhost (127.0.0.1): 56 data bytes
[2020-06-16 02:13:03-0700] 64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.036 ms
[2020-06-16 02:13:04-0700] 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.077 ms
[2020-06-16 02:13:05-0700] 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.037 ms

Color the timestamps:

$ ets -c ping localhost
...

Installation

  • On macOS you can install ets with Homebrew:

    brew tap zmwangx/ets https://github.com/zmwangx/ets
    brew install zmwangx/ets/ets
    
  • On macOS and Linux you get download a prebuilt tarball/package from the release page.

  • On Arch Linux you can install the ets-bin binary package from AUR:

    pacman -S ets-bin
    # or
    yay -S ets-bin
  • On a supported platform, if you have the Go toolchain installed, you may install with

    go get github.com/zmwangx/ets
    

Usage


ETS(1)                    BSD General Commands Manual                   ETS(1)

NAME
     ets -- command output timestamper

SYNOPSIS
     ets [-s | -i] [-f format] [-u | -z timezone] command [arg ...]
     ets [options] shell_command
     ets [options]

DESCRIPTION
     ets prefixes each line of a command's output with a timestamp. Lines are
     delimited by CR, LF, or CRLF.

     The three forms in SYNOPSIS correspond to three command execution modes:

     o If given a single command without whitespace(s), or a command and its
       arguments, execute the command with exec in a pty;

     o If given a single command with whitespace(s), the command is treated as
       a shell command and executed as `SHELL -c shell_command', where SHELL
       is the current user's login shell, or sh if login shell cannot be
       determined;

     o If given no command, output is read from stdin, and the user is respon-
       sible for piping in a command's output.

     There are three mutually exclusive timestamp modes:

     o The default is absolute time mode, where timestamps from the wall clock
       are shown;

     o -s, --elapsed turns on elapsed time mode, where every timestamp is the
       time elapsed from the start of the command (using a monotonic clock);

     o -i, --incremental turns on incremental time mode, where every timestamp
       is the time elapsed since the last timestamp (using a monotonic clock).

     The default format of the prefixed timestamps depends on the timestamp
     mode active. Users may supply a custom format string with the -f,
     --format option.

     The timezone for absolute timestamps can be controlled via the -u, --utc
     and -z, --timezone options. Local time is used by default.

     The full list of options:

     -s, --elapsed
              Run in elapsed time mode.

     -i, --incremental
              Run in incremental time mode.

     -f, --format format
              Use custom strftime(3)-style format string format for prefixed
              timestamps.

              The default is ``[%Y-%m-%d %H:%M:%S]'' for absolute time mode
              and ``[%H:%M:%S]'' for elapsed and incremental time modes.

              See FORMATTING DIRECTIVES for details.

     -u, --utc
              Use UTC for absolute timestamps instead of local time.

              This option is mutually exclusive with --z, --timezone.

     -z, --timezone timezone
              Use timezone for absolute timestamps instead of local time.
              timezone is an IANA time zone name, e.g.
              ``America/Los_Angeles''.

              This option is mutually exclusive with -u, --utc.

     -c, --color
              Print timestamps in color.

FORMATTING DIRECTIVES
     Formatting directives largely match strftime(3)'s directives on FreeBSD
     and macOS, with the following differences:

     o Additional directives %f for microsecond and %L for millisecond are
       supported.

     o POSIX locale extensions %E* and %O* are not supported;

     o glibc extensions %-*, %_*, and %0* are not supported;

     o Directives %G, %g, and %+ are not supported.

     Below is the full list of supported directives:

     %A    is replaced by national representation of the full weekday name.

     %a    is replaced by national representation of the abbreviated weekday
           name.

     %B    is replaced by national representation of the full month name.

     %b    is replaced by national representation of the abbreviated month
           name.

     %C    is replaced by (year / 100) as decimal number; single digits are
           preceded by a zero.

     %c    is replaced by national representation of time and date.

     %D    is equivalent to ``%m/%d/%y''.

     %d    is replaced by the day of the month as a decimal number (01-31).

     %e    is replaced by the day of the month as a decimal number (1-31);
           single digits are preceded by a blank.

     %F    is equivalent to ``%Y-%m-%d''.

     %f    is replaced by the microsecond as a decimal number (000000-999999).

     %H    is replaced by the hour (24-hour clock) as a decimal number
           (00-23).

     %h    the same as %b.

     %I    is replaced by the hour (12-hour clock) as a decimal number
           (01-12).

     %j    is replaced by the day of the year as a decimal number (001-366).

     %k    is replaced by the hour (24-hour clock) as a decimal number (0-23);
           single digits are preceded by a blank.

     %L    is replaced by the millisecond as a decimal number (000-999).

     %l    is replaced by the hour (12-hour clock) as a decimal number (1-12);
           single digits are preceded by a blank.

     %M    is replaced by the minute as a decimal number (00-59).

     %m    is replaced by the month as a decimal number (01-12).

     %n    is replaced by a newline.

     %p    is replaced by national representation of either "ante meridiem"
           (a.m.)  or "post meridiem" (p.m.)  as appropriate.

     %R    is equivalent to ``%H:%M''.

     %r    is equivalent to ``%I:%M:%S %p''.

     %S    is replaced by the second as a decimal number (00-60).

     %s    is replaced by the number of seconds since the Epoch, UTC (see
           mktime(3)).

     %T    is equivalent to ``%H:%M:%S''.

     %t    is replaced by a tab.

     %U    is replaced by the week number of the year (Sunday as the first day
           of the week) as a decimal number (00-53).

     %u    is replaced by the weekday (Monday as the first day of the week) as
           a decimal number (1-7).

     %V    is replaced by the week number of the year (Monday as the first day
           of the week) as a decimal number (01-53).  If the week containing
           January 1 has four or more days in the new year, then it is week 1;
           otherwise it is the last week of the previous year, and the next
           week is week 1.

     %v    is equivalent to ``%e-%b-%Y''.

     %W    is replaced by the week number of the year (Monday as the first day
           of the week) as a decimal number (00-53).

     %w    is replaced by the weekday (Sunday as the first day of the week) as
           a decimal number (0-6).

     %X    is replaced by national representation of the time.

     %x    is replaced by national representation of the date.

     %Y    is replaced by the year with century as a decimal number.

     %y    is replaced by the year without century as a decimal number
           (00-99).

     %Z    is replaced by the time zone name.

     %z    is replaced by the time zone offset from UTC; a leading plus sign
           stands for east of UTC, a minus sign for west of UTC, hours and
           minutes follow with two digits each and no delimiter between them
           (common form for RFC 822 date headers).

     %%    is replaced by `%'.

SEE ALSO
     ts(1), strftime(3)

HISTORY
     The name ets comes from ``enhanced ts'', referring to moreutils ts(1).

AUTHORS
     Zhiming Wang <[email protected]>

                                 July 3, 2020

Comparison to moreutils ts

Advantages:

  • Runs commands in ptys, making ets mostly transparent and avoiding pipe-related issues like buffering and lost coloring and interactivity.
  • Recognizes carriage return as line separator, does not choke on progress bars.
  • Has better operating defaults (uses monotonic clock where appropriate) and better formatting defaults (subjective).
  • Supports alternative time zones.
  • Is written in Go, not Perl, so you install a single executable, not script plus modules.
  • 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.

Disadvantages:

  • Needs an additional -f for format string, because ets reserves positional arguments for its core competency. Hopefully offset by better default.
  • 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.
  • Supports fewer formatting directives. Let me know if this is actually an issue, it could be fixable.

License

Copyright ยฉ 2020 Zhiming Wang [email protected]

The project is distributed under the MIT license.

Special thanks to DinosoftLab on None Project for the hourglass icon used in the logo, and termtosvg for the animated terminal recording.

More Repositories

1

rust-ffmpeg

Safe FFmpeg wrapper.
Rust
1,246
star
2

rust-ffmpeg-sys

FFmpeg bindings for Rust.
Rust
120
star
3

caterpillar

Hardened HLS merger
Python
50
star
4

metadata

Media file metadata for human consumption
Rust
46
star
5

homebrew-npm-noob

Generate Homebrew formulae for npm packages
Python
38
star
6

rule30

Python implementation of Stephen Wolfram's elementary cellular automata (in particular, Rule 30)
Python
30
star
7

storyboard

Customizable video storyboard generator. (Deprecated. Use https://github.com/zmwangx/metadata.)
Python
27
star
8

dotfiles

My config files on macOS (also works on Linux, but with limited testing).
Shell
23
star
9

Typeset-EGA-SGA

Typeset version of EGA and SGA by Grothendieck.
12
star
10

pm

Preview man page in your browser as you edit
C++
11
star
11

ddg-bangs

DuckDuckGo bangs scraper and registry
Python
11
star
12

mDNSSupervisor

Monitor mDNSResponder and restart it when it's out of control
Go
10
star
13

pyonedrive

OneDrive API/CLI client written in Python (OneDrive API v1.0)
Python
8
star
14

xdgappdirs

A small Python module for determining appropriate platform-specific dirs, e.g. a "user data dir".
Python
7
star
15

dropzone3-actions

My Dropzone 3 custom actions
Ruby
7
star
16

miller-rabin

Fast, deterministic* Miller-Rabin primality test for Python
C
6
star
17

dim

Single module HTML parser and simple DOM implementation with CSS selector support
Python
6
star
18

YODO

Dead simple ephemeral file hosting service
Python
5
star
19

debounce

lodash debounce/throttle ported to Go
Go
4
star
20

AreYouSure

Are you really sure?
TypeScript
3
star
21

repocards

Auto-generate GitHub-style repository cards with GitHub Actions
JavaScript
3
star
22

release-feeds

Software release feeds w/ GitHub Actions and GitHub Pages bootstrapped on Debian's watch infrastructure
Python
3
star
23

imgur

CLI authorization, authentication, and upload wrapper around PyImgur
Python
2
star
24

ncov

Another 2019-nCoV stats gathering and visualization project
Python
2
star
25

YouTubeLiveRecorder

Simple cross-platform Qt GUI for recording YouTube livestreams
Python
2
star
26

instatools

Instagram scraping tools
Python
1
star
27

chocolatey-googler

Python
1
star
28

docker-arm64v8-rust-ffmpeg

Development-oriented arm64 Docker images w/ Rust toolchain and FFmpeg devel libs
Dockerfile
1
star
29

ghuc

Upload images/documents to GitHub as issue attachments
Python
1
star
30

homebrew-track

๐Ÿ๐ŸŽ Search homebrew/core's issue/pr trackers from the command line
Python
1
star
31

DirectLinks

Makes indirect links on Google and Facebook direct.
JavaScript
1
star
32

Project-Euler

Project Euler mathematical/computer programming challenge
Jupyter Notebook
1
star
33

pyzmwangx

A collection of small Python utilities used in my day-to-day scripts.
Python
1
star
34

ham-radio-test-prep

Interactive front-end to ARRL's technician class question pool
HTML
1
star
35

pypi-release-bot

Bot for automatically publishing releases to PyPI
Python
1
star
36

em2a

Emoji to ASCII art
Ruby
1
star
37

pymccusb

Python interface for Measurement Computing Corp (MCC) data acquisition devices
Python
1
star
38

diceware

C implementation of the Diceware passphrase generation scheme. http://world.std.com/~reinhold/diceware.html
C
1
star
39

wchardet

chardet in web browser w/ Rust & Wasm
Rust
1
star
40

docker-selenium-python

Python 3, selenium, Chromium/chromedriver or Firefox/geckodriver.
Dockerfile
1
star
41

bilibili-feedgen

Bilibili user feed generator
Python
1
star
42

cloudfloat

Dynamic DNS client for Cloudflare
Go
1
star
43

Fortune

fortune(6) in your new tab page
HTML
1
star