Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

converting the hash tag timestamps in history file to desired string

when i store the output of history command via ssh in a file i get something like this

ssh -i private_key user@ip 'export HISTFILE=~/.bash_history; export HISTTIMEFORMAT="%D-%T "; set -o history; history' > myfile.txt

OUTPUT

#1337431451
command

as far as ive learnt this hash string represents a timestamp. how do i change this to a string of my desired format

P.S- using history in ssh is not outputting with timestamps. Tried almost everything. So i guess the next best thing to do would be to convert these # timestamps to a readable date time format myself. How do i go about it?

like image 950
user1356163 Avatar asked May 19 '12 12:05

user1356163


3 Answers

you can combine rows with paste command:

paste -sd '#\n' .bash_history

and convert date with strftime in awk:

echo 1461136015 | awk '{print strftime("%d/%m/%y %T",$1)}'

as a result bash history with timestamp can be parsed by the next command:

paste -sd '#\n' .bash_history | awk -F"#" '{d=$2 ; $2="";print NR" "strftime("%d/%m/%y %T",d)" "$0}'

which converts:

#1461137765
echo lala
#1461137767
echo bebe

to

1 20/04/16 10:36:05   echo lala
2 20/04/16 10:36:07   echo bebe

also you can create script like /usr/local/bin/fhistory with content:

#!/bin/bash

paste -sd '#\n' $1 | awk -F"#" '{d=$2 ; $2="";print NR" "strftime("%d/%m/%y %T",d)" "$0}'

and quickly parse bash history file with next command:

fhistory .bash_history
like image 52
tmf glzkv Avatar answered Oct 28 '22 20:10

tmf glzkv


Interesting question: I have tried it but found no simple and clean solution to access the history in a non-interactive shell. However, the format of the history file is simple, and you can write a script to parse it. The following python script might be interesting. Invoke it with ssh -i private_key user@ip 'path/to/script.py .bash_history':

#! /usr/bin/env python3

import re
import sys
import time

if __name__ == '__main__':
    pattern = re.compile(br'^#(\d+)$')
    out = sys.stdout.buffer
    for pathname in sys.argv[1:]:
        with open(pathname, 'rb') as f:
            for line in f:
                timestamp = 0
                while line.startswith(b'#'):
                    match = pattern.match(line)
                    if match: timestamp, = map(int, match.groups())
                    line = next(f)
                out.write(time.strftime('%F %T ', time.localtime(timestamp)).encode('ascii'))
                out.write(line)
like image 38
nosid Avatar answered Oct 28 '22 20:10

nosid


Using just Awk and in a slightly more accurate way:

awk -F\# '/^#1[0-9]{9}$/ { if(cmd) printf "%5d  %s  %s\n",n,ts,cmd;
  ts=strftime("%F %T",$2); cmd=""; n++ }
  !/^#1[0-9]{9}$/ { if(cmd)cmd=cmd " " $0; else cmd=$0 }' .bash_history

This parses only lines starting with something that looks like a timestamp (/^#1[0-9]{9}$/), compiles all subsequent lines up until the next timestamp, combines multi-line commands with " " (1 space) and prints the commands in a format similar to history including a numbering.

Note that the numbering does not (necessarily) match if there are multi-line commands.

Without the numbering and breaking up multi-line commands with a newline:

awk -F\# '/^#1[0-9]{9}$/ { if(cmd) printf "%s  %s\n",ts,cmd;
  ts=strftime("%F %T",$2); cmd="" }
  !/^#1[0-9]{9}$/ { if(cmd)cmd=cmd "\n" $0; else cmd=$0 }' .bash_history

Finally, a quick and dirty solution using GNU Awk (gawk) to also sort the list:

gawk -F\# -v histtimeformat="$HISTTIMEFORMAT" '
    /^#1[0-9]{9}$/ { i=$2 FS NR; cmd[i]="" }
    !/^#1[0-9]{9}$/ { if(cmd[i]) cmd[i]=cmd[i] "\n" $0; else cmd[i]=$0 }
    END { PROCINFO["sorted_in"] = "@ind_str_asc"
       for (i in cmd) { split(i,arr)
       print strftime(histtimeformat,arr[1]) cmd[i]
    }
}'
like image 2
xebeche Avatar answered Oct 28 '22 20:10

xebeche