使用Highcharts可视化您的shell使用情况!
项目描述
Shell历史记录
受bamos/zsh-history-analysis启发。
通过Flask和Highcharts使用Web应用程序可视化Bash/Zsh的使用情况!
持续时间 |
长度 |
类型 |
退出代码 |
每小时 |
每日 |
随时间变化 |
马尔可夫链 |
最常用命令 |
在此问题中发布您的图表想法!
需求
shellhistory
需要Python 3.6或更高版本。
要安装Python 3.6,我推荐使用pyenv
。
# install pyenv
git clone https://github.com/pyenv/pyenv ~/.pyenv
# setup pyenv (you should also put these two lines in .bashrc or similar)
export PATH="${HOME}/.pyenv/bin:${PATH}"
eval "$(pyenv init -)"
# install Python 3.6
pyenv install 3.6.7
# make it available globally
pyenv global system 3.6.7
安装
使用 pip
python3.6 -m pip install shellhistory
使用pipx
python3 -m pip install --user pipx
pipx install --python python3.6 shellhistory
设置
shellhistory
需要大量信息来显示各种图表。基本的shell历史记录是不够的。为了生成必要的信息,您必须启用shell扩展。
在shell启动时,在.bashrc
或.zshrc
中添加以下内容:
# only load it for interactive shells
if [[ $- == *i* ]] && command -v shellhistory-location &>/dev/null; then
. $(shellhistory-location)
shellhistory enable
fi
... 现在正常使用您的shell!
如果您想停止shellhistory
,只需运行shellhistory disable
。
注意:出于性能原因,您还可以使用到源文件的静态、绝对路径。实际上,调用shellhistory-location
会启动一个Python进程,这可能会减慢您的shell启动速度。使用shellhistory-location
获取路径一次,并使用. <ABS_PATH>
。以我的情况为例,它是. ~/.local/pipx/venvs/shellhistory/lib/python3.6/site-packages/shellhistory/shellhistory.sh
。
用法
使用shellhistory-web
启动Web应用。现在转到http://localhost:5000/并享受!
由于资源未捆绑,您需要网络连接。
一些技术信息
它是如何工作的
当您输入命令时,shellhistory
将在命令执行前后计算值。在Bash中,它使用DEBUG上的陷阱和PROMPT_COMMAND变量(有关更多信息,请参阅man bash
)。对于Zsh,它使用preexec_functions和precmd_functions数组(有人知道在哪里可以找到这些官方文档吗?man zshmisc
中有一些信息)。
在执行命令之前,我们启动计时器,计算命令类型,并存储当前工作目录和命令本身。
在命令完成后,我们存储返回代码,并停止计时器。
历史文件格式
随命令保存的字段包括开始和停止时间戳、主机名、用户名、UUID(生成)、tty、进程的父进程、shell、shell级别、命令类型、返回代码和工作目录(路径),格式如下::start:stop:uuid:parents:host:user:tty:path:shell:level:type:code:command
。
- 多行命令从第二行开始使用分号
;
而不是冒号:
。 - 开始和停止时间戳以自纪元以来的微秒为单位。
- 进程的父进程和工作目录使用base64编码以避免分隔符损坏。
示例(多行命令)
:1510588139930150:1510588139936608:40701d9b-1807-4a3e-994b-dde68692aa14:L2Jpbi9iYXNoCi91c3IvYmluL3B5dGhvbiAvdXNyL2Jpbi94LXRlcm1pbmFsLWVtdWxhdG9yCi91c3IvYmluL29wZW5ib3ggLS1zdGFydHVwIC91c3IvbGliL3g4Nl82NC1saW51eC1nbnUvb3BlbmJveC1hdXRvc3RhcnQgT1BFTkJPWApsaWdodGRtIC0tc2Vzc2lvbi1jaGlsZCAxMiAyMQovdXNyL3NiaW4vbGlnaHRkbQovc2Jpbi9pbml0Cg==:myhost:pawamoy:/dev/pts/1:L21lZGlhL3Bhd2Ftb3kvRGF0YS9naXQvc2hlbGxoaXN0Cg==:/bin/bash:1:builtin:0:echo "a
;b
;c" | wc -c
注意:稍后我们可能使用CSV格式,在必要时引用字符串,并双重引用双引号。这将使文件对人类更易于阅读,并易于导入到其他程序中。请参阅问题26。
前一个示例看起来像这样
1510588139930150,1510588139936608,40701d9b-1807-4a3e-994b-dde68692aa14,"/bin/bash
/usr/bin/python /usr/bin/x-terminal-emulator
/usr/bin/openbox --startup /usr/lib/x86_64-linux-gnu/openbox-autostart OPENBOX
lightdm --session-child 12 21
/usr/sbin/lightdm
/sbin/init",myhost,pawamoy,/dev/pts/1,"/media/pawamoy/Data/git/shellhist",/bin/bash,1,builtin,0,"echo ""a
b
c"" | wc -c"
我们如何获取这些值
使用date '+%s%N'
获取开始和停止时间,返回代码直接通过$?
传递,使用$PWD
获取工作目录,使用Bash中的type
和Zsh中的whence
获取命令类型。
UUID、父进程、主机名和TTY的值仅在shellhistory.sh
源文件时计算一次。实际上,它们在当前shell进程的使用过程中不会改变。主机名和TTY通过命令hostname
和tty
获取。UUID通过命令uuidgen
生成。注意,UUID在子shell中导出,这样我们知道哪个shell是另一个shell的子进程,因此我们可以按“会话”分组shell进程,会话是打开的终端(无论是标签页、窗口、面板还是其他)。
用户、shell和级别的值通过环境变量简单地获取:$USER
、$SHELL
(尽管在这里的使用是错误的:请参阅问题24)和$SHLVL
(也请参阅问题25)。
最后一个命令可以通过fc
命令获得。使用fc
命令可以使shellhistory
具有与您历史记录相同的行为。
- 如果忽略以空格开始的命令,它们在
shellhistory
中也会被忽略。 - 对于重复的命令(多次输入
ls
只保存第一次)。但是请注意,如果您在其他终端中输入与前一个命令相同的命令,它仍然会被追加,除非您能够同步终端之间的历史记录,这又是另一个话题。
此外,如果您输入一个空行,或者在输入前按下Control-C,则也不会追加。这个技巧背后的原理是检查当前历史记录中的命令编号(有关技术细节,请参阅shellhistory.sh
)。
许可
项目详情
下载文件
下载您平台上的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。