8

当我通过 ssh 将历史命令的输出存储在一个文件中时,我得到了这样的结果

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

输出

#1337431451
command

据我所知,这个哈希字符串代表一个时间戳。如何将其更改为所需格式的字符串

PS-在 ssh 中使用历史记录不输出时间戳。几乎什么都试过了。所以我想下一个最好的办法是自己将这些 # 时间戳转换为可读的日期时间格式。我该怎么做?

4

3 回答 3

6

您可以使用粘贴命令组合行:

paste -sd '#\n' .bash_history

并在 awk 中使用 strftime 转换日期:

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

因此,带有时间戳的 bash 历史记录可以由下一个命令解析:

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

转换:

#1461137765
echo lala
#1461137767
echo bebe

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

您也可以使用以下内容创建脚本,例如/usr/local/bin/fhistory

#!/bin/bash

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

并使用下一个命令快速解析 bash 历史文件:

fhistory .bash_history
于 2016-04-20T07:38:57.793 回答
3

有趣的问题:我已经尝试过了,但没有找到简单而干净的解决方案来访问非交互式 shell 中的历史记录。不过历史文件的格式比较简单,可以写一个脚本来解析。下面的 python 脚本可能很有趣。调用它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)
于 2012-05-19T13:55:55.887 回答
2

仅使用 Awk 并以稍微更准确的方式:

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

这仅解析以时间戳 ( ) 开头的行/^#1[0-9]{9}$/,编译所有后续行直到下一个时间戳,将多行命令与" "(1 个空格) 组合并以类似于history包含编号的格式打印命令。

请注意,如果有多行命令,编号不会(必然)匹配。

没有编号和用换行符分解多行命令:

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

最后,使用 GNU Awk (gawk) 对列表进行排序的快速而肮脏的解决方案:

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]
    }
}'
于 2016-09-17T11:31:51.697 回答