1

I have a Bash one-liner that redirects the output of a command to a new, fresh file each time the command is run. Logging the output of each time the command is run is important (I'm using ls here as an example, but the actual command is ansible-playbook and is unlikely to be anything else):

$ ls -hl | tee logs/$(date "+%Y-%m-%d_%H:%M:%S").log

This is cumbersome to type and hard to remember, but it does what I require (as long as I do not run the command more than once per second). Running the command multiple times will produce logs in the /logs folder such as:

$ ls logs/
2018-12-21_10:28:20.log
2018-12-21_10:28:21.log
2018-12-21_10:31:11.log
2018-12-21_10:32:07.log

What I'd like to know is: is there an existing Bash command I'm unaware of that will achieve the same, or something quite similar? The format of the log's name is important (date or Unix epoch preferred).

7
  • Do you want to do this with the output of many different commands, or just ls -hl?
    – JigglyNaga
    Dec 21, 2018 at 11:17
  • @JigglyNaga Edited to clarify actual command I'm using.
    – Vaughany
    Dec 21, 2018 at 11:20
  • You could use mktemp to guarantee a new filename, but it will be about as cumbersome as the above. Is it acceptable to put this in an alias, function or script?
    – JigglyNaga
    Dec 21, 2018 at 11:25
  • Automatic renaming of logfiles is typically done by the logrotate command, but that may be overkill here. See also unix.stackexchange.com/questions/241959/…
    – JigglyNaga
    Dec 21, 2018 at 11:32
  • You can write a short script in a file including the command you're running, i guess that would do.
    – ashish_k
    Dec 21, 2018 at 11:34

1 Answer 1

2

Turning it into a shell function:

dolog () {
    local logdir="${1:-$HOME/logs}"
    mkdir -p "$logdir" &&
    tee "$logdir/$(date "+%F_%T").log"
}

This would go in your ~/.bashrc file and would be active in the next new interactive shell.

This function could be used in two ways:

utility | dolog

This saves the output to a dated file under ~/logs.

utility | dolog /some/path

This saves the output to a dated file under /some/path (using . would save the log in the current directory). If the directory /some/path (or ~/logs in the first example) does not exist, it is created.

A slightly more advanced version that will revert to just passing the data through to standard output if it can't be written to the logfile for whatever reason (the directory can't be created, or the logfile can't be written to). This ensures that the command that is being piped does not die if there's a logging problem.

dolog () {
    local logdir="${1:-$HOME/logs}"

    mkdir -p "$logdir" && tee "$logdir/$(date "+%F_%T").log" || cat
}

Example:

$ touch ~/logs  # this creates a file in my home directory
$ ls -l | dolog
mkdir: /home/myself/logs: Not a directory
total 0
-rw-r--r--  1 myself  staff  0 Dec 21 13:08 logs

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .