Package: shellhistory
Shell HistoryInspired bybamos/zsh-history-analysis.Visualize your usage of Bash/Zsh through a web app
thanks toFlaskandHighcharts!DurationLengthTypeExit codeHourlyDailyOver timeMarkov chainTop commandsPost your charts ideas inthis issue!RequirementsInstallationSetupUsageSome technical infoHow it worksHistory file formatHow we get the valuesLicenseRequirementsshellhistoryrequires Python 3.6 or above.To install Python 3.6, I recommend usingpyenv.# install pyenvgitclonehttps://github.com/pyenv/pyenv~/.pyenv# setup pyenv (you should also put these two lines in .bashrc or similar)exportPATH="${HOME}/.pyenv/bin:${PATH}"eval"$(pyenvinit-)"# install Python 3.6pyenvinstall3.6.7# make it available globallypyenvglobalsystem3.6.7InstallationWithpip:python3.6-mpipinstallshellhistoryWithpipx:python3-mpipinstall--userpipx

pipxinstall--pythonpython3.6shellhistorySetupshellhistoryneeds a lot of info to be able to display various charts.
The basic shell history is not enough. In order to generate the necessary
information, you have to enable the shell extension.At shell startup, in.bashrcor.zshrc, put the following:# only load it for interactive shellsif[[$-==*i*]]&&command-vshellhistory-location&>/dev/null;then.$(shellhistory-location)shellhistoryenablefi... and now use your shell normally!If you want to stopshellhistory, simply runshellhistory disable.Note:for performance reasons, you can also use the static,
absolute path to the source file.
Indeed, callingshellhistory-locationspawns a Python process
which can slow down your shell startup.
Get the path once withshellhistory-location, and use. <ABS_PATH>.
In my case it's. ~/.local/pipx/venvs/shellhistory/lib/python3.6/site-packages/shellhistory/shellhistory.sh.UsageLaunch the web app withshellhistory-web.
Now go tohttp://localhost:5000/and enjoy!You will need Internet connection since assets are not bundled.Some technical infoHow it worksWhen you enter a command,shellhistorywill compute valuesbeforeandafterthe command execution.
In Bash, it uses a trap on DEBUG and the PROMPT_COMMAND variable
(man bashfor more information).
For Zsh, it uses the preexec_functions and precmd_functions arrays
(anyone knows where to find the official documentation for these?
Some information inman zshmisc).Before the command is executed, we start a timer, compute the command type,
and store the current working directory and the command itself.After the command has finished, we store the return code, and stop the timer.History file formatFields saved along commands are start and stop timestamps, hostname, username,
uuid (generated), tty, process' parents, shell, shell level, command type,
return code, and working directory (path), in the following format::start:stop:uuid:parents:host:user:tty:path:shell:level:type:code:command.multi-line commands are prepended with a semi-colon;instead of a colon:,
starting at second linestart and stop timestamps are in microseconds since epochprocess' parents and working directory are encoded in base64 to avoid
delimiter corruption.Example (multi-line command)::1510588139930150:1510588139936608:40701d9b-1807-4a3e-994b-dde68692aa14:L2Jpbi9iYXNoCi91c3IvYmluL3B5dGhvbiAvdXNyL2Jpbi94LXRlcm1pbmFsLWVtdWxhdG9yCi91c3IvYmluL29wZW5ib3ggLS1zdGFydHVwIC91c3IvbGliL3g4Nl82NC1saW51eC1nbnUvb3BlbmJveC1hdXRvc3RhcnQgT1BFTkJPWApsaWdodGRtIC0tc2Vzc2lvbi1jaGlsZCAxMiAyMQovdXNyL3NiaW4vbGlnaHRkbQovc2Jpbi9pbml0Cg==:myhost:pawamoy:/dev/pts/1:L21lZGlhL3Bhd2Ftb3kvRGF0YS9naXQvc2hlbGxoaXN0Cg==:/bin/bash:1:builtin:0:echo "a
;b
;c" | wc -cNote:later we could use CSV formatting, quoting
strings and doubling double-quotes in those if any.
It would make the file more readable for humans,
and easily importable in other programs.
Seeissue 26.The previous example would look like this: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"How we get the valuesStart and stop time are obtained withdate '+%s%N', return code is passed
directly with$?, working directory is obtained with$PWDand command
type withtypefor Bash andwhencefor Zsh.Values for UUID, parents, hostname, and TTY are computed only once, whenshellhistory.shis sourced. Indeed they do not change during usage of the current
shell process. Hostname and TTY are obtained through commandshostnameandtty. UUID is generated with commanduuidgen. Also note that UUID
is exported in subshells so we know which shell is a subprocess of another, and
so we are able to group shell processes by "sessions", a session being an opened
terminal (be it a tab, window, pane or else). Parents are obtained with a
function that iteratively grepspsresult with PIDs (seeshellhistory.sh).Values for user, shell, and level are simply obtained through environment
variables:$USER,$SHELL(though its use here is incorrect:
seeissue 24),
and$SHLVL(also seeissue 25).The last command is obtained with the commandfc.
Usingfcallowsshellhistoryto have the same behavior as your history:if commands starting with spaces are ignored, they will be ignored
inshellhistoryas well.same for duplicates (enteringlstwo or more times
saves only the first instance). Note however that if you type the same command
as the previous one in an other terminal, it will still be appended,
unless you manage to synchronize your history between terminals,
which is another story.Additionally, if you enter an empty line,
or hit Control-C before enter, nothing will be appended either.
The trick behind this is to check the command number in the current history
(seeshellhistory.shfor technical details).LicenseSoftware licensed under theISClicense. See theLICENSEfile.