3

The requirement is to capture command line history in a file with specific date and time of commands, when they were executed.

The below script captures history with date and time but it also assigns the current date and time for older commands. Also I want to extend the script to take incremental backup of the history output file.

#!/bin/bash
. ~/.bash_profile
HISTFILE=~/.bash_history
set -o history
history >/home/user/hist_`date "+%d%b%y%T"`
Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232
SunLynx
  • 101

2 Answers2

7

Not quite what you wanted, but you can get bash to add timestamps to each line in the history automatically. Simply set, for your example:

HISTTIMEFORMAT="%d%b%y%T "

The history command with no arguments will then show your history entries like this:

23Jul1515:48:14 ls -ld .

The history -w command however always writes the history file in the internal format of:

#1437659315
ls -ld .

i.e. on 2 lines, the first line holds the time in seconds "since the epoch" (i.e. 1 jan 1970) with a # in front so that it will not be confused with a command.

meuh
  • 51,383
  • I want to capture history on daily basis, above script works but it assign current date to all commands. Also after every command one number generates, which I don't want. If anybody can help, that will be really helpful – SunLynx Jul 21 '15 at 13:40
  • I dont know what you mean by "one number generates". Could you edit your original question with an example of what files you want to get, and their contents? – meuh Jul 21 '15 at 14:17
  • 598 05Jul15 00:00:01less .bash_history 599 05Jul15 00:00:01#1435987168 600 05Jul15 00:00:01man rsync 601 05Jul15 00:00:01#1435988263 602 05Jul15 00:00:01ls -lrt /srv/cloud-* 603 05Jul15 00:00:01#1435988281 604 05Jul15 00:00:01crontab -l 605 05Jul15 00:00:01#1435988290 606 05Jul15 00:00:01cat /srv/cloud-user_hist.sh – SunLynx Jul 23 '15 at 13:24
  • like this messages generates – SunLynx Jul 23 '15 at 13:25
  • it is hard to read this in a comment. remove your comments and edit the question you originally wrote, please. – meuh Jul 23 '15 at 13:26
4

In bash, there is an option that instructs bash to record a timestamp with each command. You do this by assigning a useful value to the environment variable HISTTIMEFORMAT. From the bash manpage:

If this variable is set and not null, its value is used as a format string for strftime(3) to print the time stamp associated with each history entry displayed by the history builtin. If this variable is set, time stamps are written to the history file so they may be preserved across shell sessions. This uses the history comment character to distinguish timestamps from other history lines.

Note, after having activated HISTTIMEFORMAT then ~/.bash_history will have always two lines per each recorded command:

  • First a line starting with a hash "#" symbol, immediately followed by a Unix timestamp (seconds since start of the Unix epoch).
  • Second a line which is the command as you typed it.
    #1671097644
    cd ~/bin
    #1671097645
    ls -l
    

In my environment, I use

HISTTIMEFORMAT="%s (%H:%M:%S):"

When you invoke history that tool formats the timestamp on the fly with your defined format. I use above formatting so that commands may be sorted easily (%s is timestamp in seconds) and human-readable. In my shell, when I type history, I see something like the following:

3  1437664568 (17:16:08):man bash
4  1437664699 (17:18:19):history

Note: All commands prior your activation of timestamp recording, are only the command without the prefixed timestamp line. Hence they show the date/timestamp when you logged into your current session. If that annoys you, then simply do a find/replace of your legacy lines to prefix them with an artificial timestamp. And add a note on the boundary line for documentation purposes. Like this:

#1671058800
ls -l
#1671058800
exit
#1671094600
echo Activated timestamp recording in the history file now.
#1671094610
echo All commands prior got the artificial timestamp 2022-12-15 00:00:00 (1671058800).
#1671094622
cd /
#1671094627
exit

EDIT: OPs question not fully answered.

Also I want to extend the script to take incremental backup of the history output file

I'm not sure what you mean by "incremental backup" of the history file. Perhaps you simply want the history backed up periodically. There are a couple of approaches you can take:

  • Set PROMPT_COMMAND variable with history -a to continually update the history command after every invocation (as opposed to waiting for logout).
  • Trap the DEBUG signal with a function you define. Every time a command is entered, the function will be called. From within the function you can do everything. (Slightly more reliable than PROMPT_COMMAND).
  • cronjob to periodically copy/archive the history file.
porg
  • 574
Otheus
  • 6,138
  • Thanks for suggestions but I've tested above. Can you please elaborate more about history -a. Shell script is working fine but wrong time stamps. This is the one problem and another is one number after every command which starting with #. for e.g. #1435987168. – SunLynx Jul 24 '15 at 08:02
  • 2
    The #1435987168 in the history file is the timestamp! There are a couple of ways to convert that into user-friendly format, including: load the history file into bash with history -n _filename_ and then history. Or you can do something like this: perl -lane '{ /^#(\d+)$/&&print "#".localtime($1) or print;}' $HISTFILE to display the history with the timestamps.

    So it's probably that the timestamps are correct, but you have a locale or timezone problem?

    – Otheus Jul 24 '15 at 13:02
  • Elaborate on history -a?? The man page is a little misleading. It appends the current session history to the file designated by $HISTFILE. Subsequent calls will append the history generated since the last invocation (it doesn't overwrite the whole file over and over again) – Otheus Jul 24 '15 at 13:02
  • Thanks! zsh (or only the oh-my-zsh variant that I use?) has a timestamped history in its default configuration, which I loved. This answer explained me how to get that in bash too. Thanks! – porg Dec 15 '22 at 10:13
  • 1
    @porg Nice additions! Thanks! – Otheus Jan 18 '23 at 11:24