Bash Command Logger - linux

I was wondering, out of curiosity, if it is possible to code a bash script logs all the command run in a Bash/SSH session. I know history is suppose to log all the commands run but it seems to be very unreliable!
I have been messing about this morning and came up with the following bash script which does log what the user runs in the terminal but does not run all the commands correctly.
prompt_read() {
echo -n “$(whoami)#$(hostname):$(pwd)~$ “
read userinput
}
prompt_read
while :; do
if [[ $userinput != exit ]]; then
logger "logit $userinput"
bash -c "$userinput"
prompt_read
else
kill -1 $PPID
fi
done
Is anyone aware of anything that logs commands better and more reliably than history
Cheers

The reason why history seems unreliable to you is because it only writes to history at the end of a BASH session, so you could lose commands.
I have a few things in my bash profile:
HISTFILESIZE=10000 # how many lines of history to store in the history file
HISTSIZE=10000 # how many lines of history to store in a session ( I think )
HISTCONTROL=ignoredups # ignore duplicate commands
shopt -s histappend # append history, rather than having sessions obliterate existing history
PROMPT_COMMAND="history -a;$PROMPT_COMMAND"
The last few are the important ones, setting your PROMPT_COMMAND with history -a will make history append immediately, rather than post-session. And setting shopt -s histappend will make bash sessions append to the history file, rather than overwrite existing histories.
Some more info: http://linuxcommando.blogspot.com/2007/11/keeping-command-history-across-multiple.html
Additionally, if this is useful to you, you can change the name of the history file you use for a particular bash session with the HISTFILE environment variable.

Check out script: http://bashshell.net/commands/using-the-script-command/
It records everything that appear on the terminal to a file, and iirc it can play back the recorded session.
You can set this as the user's shell to make it record everything upon login.

You can find a script here to log all 'bash' commands/builtins into a text-file or a 'syslog' server without using a patch or a special executable tool.
You can also write directly without syslog to a logfile.
It is very easy to deploy, as it is a simple shell script that need to be called once at the initialization of the 'bash'.

Related

script gets a bug when I record Shell output

I wanted to know how to record all the input and output of my terminal.
Of course, I can use the script command but I am going to record every user's input and output. So I put script into file: .barhrc for every user's home directory.
Just like this:
script -a -f -q $RECORDFILE
But I met a bug when other program or Shell script executed source ~/.bashrc. Because source ~/.bashrc go into a new shell environment,so it stops my script from going any further util I use the exit command and stop the recording.
I'm sorry for my poor English.
Thanks in advance!
You can set a variable and also check that input is a TTY:
if [[ -z "$RECORDING" && -t 0 ]]
then
RECORDING="YES" exec script -afq "$RECORDFILE"
fi
The variable ensures that you will not start recording in a session that is already being recorded.
Checking that input is a terminal ensures that any script running from cron or similar will not try to start recording, even if such a script runs source ~/.bashrc to try to set up some variables.
You should also see whether ~/.bash_profile is a better place to start recording. This file runs only on login, and scripts usually don't try to source it. However, some terminal emulators will not start up with login shells, so they may not start recording.

Bash History Scope

Defined in .bashrc
function gitpullsite(){
echo "Enter GIT username";
read gituname;
echo "Enter GIT password";
read -s gitpword;
giturl=https://$gituname:$gitpword#github.com/whateveruser/whateverrepo.git
repopath=/home/whateveruser/html/whateverrepo/;
sudo rm -r $repopath;
sudo git clone $giturl $repopath;
}
and then run in terminal gitpullsite I want to remove gituname and gitpword from history but I cannot find such entries in history anywhere. I have no process in place to remove such entries so where is this history stored ? Is it ignored as within the scope of the function and not the shell ?
What I don't want is an unknown trail of usernames and passwords stored somewhere I don't know about - an obvious security issue should a system be compromised.
The aim is to add further different 'nested' repos but the user only needs to enter credentials once.
You may want to try https://github.com/dvorka/hstr which, in addition to history management i.e. deleting particular command(s) from history, allows for "suggest box style" filtering.
It can be easily bound to Ctrl-r and/or Ctrl-s
One possible solution would be to not log part of your commands at all.
Multiple ways to do so :
1
To stop logging bash history is:
set +o history
and to reset, that is to start logging again:
set -o history
2
You can also use add ignorespace to your HISTCONTROL environment variable. Then any command line that begins with a space won't be entered into your history.
methods for avoiding bash history logging
Can you prevent a command from going into the bash shell command history?

combine history across tty

At any given time I have 3 logins to the same server. Sure, I often use screen, but assume this purpose allows me to have:
1 session running something
1 session looking at output
1 session shuffling files to/from various places
If at any point I lose all three connections, I lose 2/3 of my history, as when I log back in, I get the history from a random 1 of my three connections.
Is there a way to stop this and combine all three history files into 1?
Alternatively, is there a way to declare each login as "ttyN" thus keeping each with its separate history separate, but retrievable / re-connectable?
Thanks!
Possible solution?
After you have opened your Terminal /Screen
start your shell with a History-File setting:
HISTFILE=$HOME/session1-history bash
and continue to work with this bash.
To run a different session history
HISTFILE=$HOME/session2-history bash
etc.
Just add this in your .bashrc file.
# Avoid duplicates..
export HISTCONTROL=ignoredups:erasedups
# Append history entries..
shopt -s histappend
# After each command, save and reload history
export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"
Found this answer at this Unix Stackexchange post.
I tried this and it seems to work on multiple terminals simultaneously, only catch is you've to execute a command for the terminal to fetch the latest history from .bash_history.
So for example, if I open the first terminal and type echo check 1 and then open a second terminal and type echo check 2. Now if I go back to the first terminal and press the up key, I won't get echo check 2, since the last time the history was fetched from the history file was when I executed the previous command. So I can just press Enter without specifying a command and it will fetch the last history entries. Now if I press the up key, it will show up echo check 2, which is the expected behavior.
There is an open source shell history logger for bash and zsh which would solve your problem (disclaimer: I wrote and maintain it).
https://github.com/barabo/advanced-shell-history
The idea is that your commands are written into a sqlite3 database using a builtin bash hook. If you really needed to go back and figure out what commands you entered / how long they ran / what their exit codes were - you should give it a try.
It's saved me many times.
There are numerous options you can set to prevent Bash instances from overwriting each others history. See this FAQ for a full explanation:
In your .bashrc, add
HISTFILESIZE=400000000
HISTSIZE=10000
PROMPT_COMMAND="history -a"
export HISTSIZE PROMPT_COMMAND
shopt -s histappend
If I've understood your requirements right you have multiple terminal sessions open and want commands entered in one session to be available via history in other sessions.
You need to put these lines on top of your ~/.bashrc:
export HISTFILESIZE=100000
export HISTSIZE=100000
# avoid & erase dups
export HISTCONTROL=ignoredups:erasedups
shopt -s histappend
# save & reload history after each command enter in shell
export PROMPT_COMMAND="\history -a; \history -c; \history -r; $PROMPT_COMMAND"
Most important is histappend which makes sure that new history lines are appended to the history file each time.
PS: You need to press enter to see most recently added history in each session.
For more robust solution see: http://ptspts.blogspot.in/2011/03/how-to-automatically-synchronize-shell.html

How can I debug the bash prompt?

I've been editing .bashrc files and other init files, and it seems that I've left behind a few code snippets or two that are causing a few errors at the prompt (e.g. file missing), but I can't find them.
How do I debug the prompt to find out what init scripts I've carelessly hacked?
Most of the shells have debug flags that show the commands being executed. Bash may even have one that shows a command before expansion of variables and after. Have you tried checking (I believe) -c -x or -X flags and see if they show the information you are looking for.
You can set them as first thing in the rc files (most global one) or just pass it down into bash command by invoking it from another shell.
In fact, if you invoke bash from another shell, you can also use script command to record everything you see and do into the file, which makes postmortem analysis so much easier.
Try invoking bash with the -x flag, then sourcing your .bashrc or .bash_profile or whatever you're using. That ought to be prolix enough to find your problem
ie:
bash -x
source .bashrc
The easiest way to get a clean initial state is to SSH into your current host, but instead of letting SSH launch your shell with default settings, you provide an explicit command which prevents .bashrc from being read.
ssh -tt localhost /bin/bash --norc
The -tt forces SSH to allocate a TTY, which is what would normally happen when you open a shell connection, but is not default when running an explicit command.
The --norc prevents bash from reading your settings file (since we want to do that ourselves).
You should now be at a bash prompt, in a clean environment. This is useful for examining what variable are set to before your .bashrc runs etc. Enable tracing and source your .bashrc:
set -x # Enable tracing
source .bashrc
Try to see where you've defined prompt - probably it in some dot file in your home directory:
grep PS1 ~/.*
You can see current value of prompt by just printing it:
echo $PS1
HTH
Check the .bash_history file in your home directory to find out what commands you have been running. If you used commands like vi filename to open the init scripts, it will find them in the command history.

Retrieving command line history

I use ubuntu 11.04, and the question must be common to any bash shell. Pressing the up arrow key on your terminal will retrieve the previous command you had executed at your terminal.
My question is where(in which file) will all these command history be stored? Can I read that file?
the history filename was stored in variable : $HISTFILE
echo $HISTFILE
will give you the right file.
Usually in bash it would be ~/.bash_history, however it could be changed by configuration.
also notice that sometimes the very last commands is not stored in that file. running
history -a
will persistent.
history -r
will clean those command not yet written to the file.
For bash, it is by default in ~/.bash_history (check the HISTFILE environment variable if it isn't). You can directly cat the file or use the history command.

Resources