# history_logger() side effects: # sets global variable '_last_history_number_logged' # $HISTCMD special variable should actually provide this, # But it appears unavailable in functions or at PROMPT_COMMAND eval time. # function history_logger() {
local last_exit_code=$? # must be the first command we run in this function local last_history_line=$(history 1)
local _match_me="^ ?([0-9]+)"
# Only log if we are not root: if [ "$(id -u)" -ne 0 ]; then # only log if history number changes: if [[ ${last_history_line} =~ ${_match_me} ]] &&
[[ ${BASH_REMATCH[1]} != $_last_history_number_logged ]] ; then _last_history_number_logged=${BASH_REMATCH[1]} ; echo "$(date)] ${HOSTNAME%%.*}[$$:S${WINDOW}:${last_exit_code}] ${PWD/~/\~} ${last_history_line}" >> ~/.shell.log; fi ; fi } # the plumbing that makes it work: export PROMPT_COMMAND='history_logger'A few explanatory comments, as inline comments aren't available:
• HISTCMD does not appear to be available at function call or PROMPT_COMMAND time,
so we use the [[ history =~ regex && BASH_REMATCH ]] to hack it
• the assignment to ${_match_me} is because regex matching doesn't work correctly otherwise.
• the shell out to $(date) seems unavoidable.
• gnu screen is setting $WINDOW
• ${PWD/~/\~} is an exercise left to the reader.
I've seen other folks try to do this –– the best I found folks doing involved calling other bash scripts from the PROMPT_COMMAND.
I hit the same problem (inside a PROMPT_COMMAND, $HISTNUM is always == 1).
My solution uses a regex to capture the last history number, and doesn't require calling a separate script or set of scripts.
Comments welcome.