2

Sometime back, we had a requirement to log commands run on the terminal in the Bash shell. This was solved by means of a startup script with essentially the following contents:

#!/bin/bash

SESSION_LAST_COMMAND=

log_last_command() {
    local command

    command=$(history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//")

    if [[ -n "$SESSION_LAST_COMMAND" ]]; then
        logger -p local3.notice "shell user [$$]: Executed command: $command"
    fi

    SESSION_LAST_COMMAND="$command"
}

export PROMPT_COMMAND=log_last_command

It works fine except that pressing ENTER logs the last command again. This happens as many times as the enter key is pressed. And some users do have this habit! Is there a way to avoid these extra logs? Also, an obvious expectation from the solution will that a distinction between just pressing enter a few times and actually re-running the command be possible.

pdp
  • 307
  • You mean like $history does? what you need to do is not process blank readlines. I will look into this later. – j0h Dec 20 '13 at 17:11
  • That script might look like working fine, but it is likely not. If the user puts a space on the line before the command, then that command won't be logged in history, and because of that it won't be logged in your script also. – falconer Dec 20 '13 at 17:57

2 Answers2

3

I managed to solve the problem of repeated command logging triggered by the ENTER key by replacing the "history 1" invocation by "history -a >(tee -a $HISTFILE)". Subsequently, after the last command has been found and logged, "history -c; history -r" is run to remove all entries from the Bash's in-memory command list and regenerate the list from whatever has been saved in the history file. This is necessary to get only a single command the next time "history -a" is executed. Here is the solution:

session_log_command() {
    local status=$?
    local command
    local cwd

    cwd=$PWD

    command=$(history -a >(tee -a $HISTFILE))

    if [[ -n "$command" ]]; then
        logger -p local3.notice "shell user [$$]: Executing command [CWD=$cwd ; $status]: $command"
        history -c; history -r
    fi
}

export PROMPT_COMMAND=session_log_command
pdp
  • 307
0

If you look in each user's home directory, they should be a file called .bash_history. This is a hidden file, so in Nautilus you need to press Ctrl+H to view it, or with ls you need to use the -a option. This will contain the last 1000 commands the user has entered. So I would of thought you could just regularly log that file, instead of using the history command...

Wilf
  • 30,194
  • 17
  • 108
  • 164
  • The method of logging commands via "logger" gets the message finally to /var/log/messages, which is less susceptible to get deleted than a file in a user's home directory. Also, this method helps log commands for all users and not just that of mine. – pdp Mar 05 '14 at 15:12