How to can i log all commands typed in a Bash shell?
Written by: J Dawg
Our small company runs an Ubuntu Server 11.10, to which a couple of people have SSH access. The actual terminals are sometimes used, too. How can we locally log all Bash commands run, along with user and time stamp?
We can assume that no-one is nefarious and actively trying to avoid the logging, but we’d still prefer the users not to have direct write-access to their log files. Simultaneous sessions must be handled correctly.
For BASH shells, edit the system-wide BASH runtime config file:
sudo -e /etc/bash.bashrc
Append to the end of that file:
export PROMPT_COMMAND='RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]+[ ]*//" ) [$RETRN_VAL]"'
Set up logging for “local6” with a new file:
sudo -e /etc/rsyslog.d/bash.conf
And the contents…
sudo service rsyslog restart
Log out. Log in. Voila!
But I forgot about log rotation:
sudo -e /etc/logrotate.d/rsyslog
There is a list of log files to rotate the same way…
/var/log/mail.warn /var/log/mail.err [...] /var/log/message
So add the new bash-commands log file in that list:
A process accounting system may be helpful in this regard, particularly the acct package that provides the lastcomm and ac commands
The ac commands prints out statistics about users’ connection time, in hours. This is the amount of time that the user has been connected to the system, either remotely via SSH or a serial terminal, or while on the console.
The lastcomm command displays information about the previously executed commands. The most recent entries are given at the top of the list. Also displayed is the total amount of CPU time that each process used.
An old tutorial that may be helpful is here:
Other accounting commands like last and so on can be found in this tutorial:
You can find here a script to log all bash commands/built-ins into a text-file or a syslog server without using a patch or a special executable tool.
Very easy to deploy, as it is a simple shell script that need to be called once at the initialization of the bash.
It is free and I hope it suit your needs.
To take care of multiple sessions not over-writing the history file, you will have to put “shopt -s histappend” in a Bash startup file. See, also this question on the same problem.
try this (the solutions above will not work 100% with bash 4.3):
export HISTTIMEFORMAT="%Y-%m-%d %T " export PROMPT_COMMAND='trap "" 1 2 15; history -a >(tee -a ~/.bash_history | while read line; do if [[ $line =~ ^#[0-9]*$ ]]; then continue; fi; logger -p user.info -t "bash[$$]" "($USER) $line"; done); trap 1 2 15;'
this does the logging AND it prevents logging of timestamps that are used for the bash history file. the trap is needed, since bash will send the signals to the “subjob” after pressing strg+c multiple times (tested with bash 4.3). this will force the logout of the current user (e.g. logged in with sudo)