From 9904be95d2802b901706a8820870e9503f5a205a Mon Sep 17 00:00:00 2001 From: Greg Anderson Date: Tue, 20 Nov 2012 14:57:02 -0800 Subject: [PATCH] Keep track of history for commands done during 'sudo bash' subshells in the user's original home directory --- historyrc | 114 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 32 deletions(-) diff --git a/historyrc b/historyrc index ae6ca9b..9d44ef6 100644 --- a/historyrc +++ b/historyrc @@ -5,36 +5,67 @@ shopt -s histreedit # Set the title of a Terminal window function history_settitle() { - if [ -n "$STY" ] ; then # We are in a screen session - echo "Setting screen titles to $@" - printf "\033k%s\033\\" "$@" - screen -X eval "at \\# title $@" "shelltitle $@" - else - printf "\033]0;%s\007" "$@" + if [ -n "$DISPLAY" ] ; then + if [ -n "$STY" ] ; then # We are in a screen session + echo "Setting screen titles to $@" + printf "\033k%s\033\\" "$@" + screen -X eval "at \\# title $@" "shelltitle $@" + else + printf "\033]0;%s\007" "$@" + fi fi } +# We will store all of our history files in ~/.history, and we +# will record information about our active terminals in ~/.terminal. mkdir -p $HOME/.history mkdir -p $HOME/.terminal -TTY=$(tty | tr / _) -HOSTNAME=$(hostname -s) + +# HIST_TTY records the tty that this history session is associated with, +# and HIST_IDENTIFIER identifies the host and user this history belongs to. +# Note that the user is only included if it is not already implied from $HOME +# (e.g. after `sudo bash` $HOME will be /home/origuser and $USER will be root, +# so the history file will be stored in /home/origuser/.history/bash_HOST_root_dev_pts_N) +export HIST_TTY=$(tty | tr / _) +HIST_IDENTIFIER=$(hostname -s) +# If this terminal session was initiated via an ssh session, then we will use +# the first word from '$SSH_CLIENT' instead of hostname -s in the history filename. +if [ -n "$SSH_CLIENT" ] ; then + HIST_IDENTIFIER="${SSH_CLIENT%% *}" +fi +if [ "$(basename $HOME)" != "$USER" ] +then + HIST_IDENTIFIER="${HIST_IDENTIFIER}_$USER" +fi +export HIST_IDENTIFIER # If $HISTFILE is in the home directory, then make a new history file unique to this tty if [ $(dirname "$HISTFILE") == "$HOME" ] then - export HISTFILE="$HOME/.history/bash_${HOSTNAME}${TTY}" + export HISTFILE="$HOME/.history/bash_${HIST_IDENTIFIER}${HIST_TTY}" + # If we are logged in as some other user (e.g. root), try to make + # our histfile accessible to the user that owns $HOME. + if [ "$(basename $HOME)" != "$USER" ] + then + touch $HISTFILE + chgrp $(basename $HOME) $HISTFILE + chmod g+rw $HISTFILE + fi if [ -f "$HISTFILE" ] then history -r fi fi -history_settitle "${HOSTNAME}${TTY}" -if [ -n "$(which wmctrl 2>/dev/null)" ] ; then + +trap "history_settitle $HIST_TTY; exit" 0 +export HISTORY_TITLE="${HIST_IDENTIFIER}${HIST_TTY}" +history_settitle "$HISTORY_TITLE" +if [ -n "$DISPLAY" ] && [ -n "$(which wmctrl 2>/dev/null)" ] ; then # It takes a bit before wmctrl will see the result of the settitle; # once we have the window title, write the window id into the # corresponding .terminal file. sleep 0.1 - w=$(wmctrl -l | grep "${HOSTNAME}${TTY}" | sed -e 's/ .*//') - echo $w > "$HOME/.terminal/${HOSTNAME}${TTY}" + w=$(wmctrl -l | grep "${HIST_IDENTIFIER}${HIST_TTY}" | sed -e 's/ .*//') + echo $w > "$HOME/.terminal/${HIST_IDENTIFIER}${HIST_TTY}" fi export HISTIGNORE="&:[ ]*:ls:hist.*:exit" export PROMPT_COMMAND="$PROMPT_COMMAND"'; HISTTIMEFORMAT="[%m/%d@%H:%M:%S] " history -a' @@ -89,8 +120,7 @@ function note { function task { t=$(date "+%s") task=$(echo $* | tr A-Z a-z | sed -e 's/ /_/g' -e 's/[^a-z0-9_]//g') - taskfile="$HOME/.history/task_$task" - history -a + taskfile="$HOME/.history/task_${HIST_IDENTIFIER}_$task" histpush "$taskfile" note echo "begin task: $*" // $HISTFILE echo "HISTFILE is now $HISTFILE" @@ -109,29 +139,40 @@ function finished { fi } -# Show all active nested tasks in this terminal -function tasks { +# Show all active tasks nested in this terminal +function tasklist { + # $HISTFILES contains the stack of active tasks for this terminal for f in $HISTFILE $(echo $HISTFILES | tr : ' ') ; do if [ ${f:0:1} != '/' ] then f="$HOME/.history/$f" fi l=$(grep -Hm 1 "^#[0-9]\+ >>.*$*" $f) - t=$(echo $l | sed -e 's/^[^#]*#\([0-9]\+\).*/\1/') - c=$(echo $l | sed -e 's/^[^>]*>> *//') - d=$(date --date="@$t") - n=${c#*:} - sn=${n%% //*} - echo "$(basename $f):$sn // $d" + if [ -n "$l" ] + then + t=$(echo $l | sed -e 's/^[^#]*#\([0-9]\+\).*/\1/') + c=$(echo $l | sed -e 's/^[^>]*>> *//') + d=$(date --date="@$t") + n=${c#*:} + sn=${n%% //*} + echo "$(basename $f):$sn // $d" + fi done } -# grep all history files for a command pattern -function hgrep { - ( - cd $HOME/.history - grep $* $(ls -rt | grep -v $(basename $HISTFILE)) $(basename $HISTFILE) | grep -v '^[^:]*:#' - ) +# Show all tasks that are not finished +function tasks { + for h in $(ls $HOME/.history/task_*) ; do + if [ -z "$(grep "^finished$" $h)" ] ; then + l=$(head -n 1 $h) + t=$(echo $l | sed -e 's/^[^#]*#\([0-9]\+\).*/\1/') + c=$(echo $l | sed -e 's/^[^>]*>> *//') + d=$(date --date="@$t") + n=${c#*:} + sn=${n%% //*} + echo "[$d]\$ $c" + fi + done } # Show all notes entered in the active terminal window @@ -149,10 +190,17 @@ function notes { IFS="$OLDIFS" } +# grep all history files for a command pattern +function hgrep { + ( + cd $HOME/.history + grep $* $(ls -rt | grep -v $(basename $HISTFILE)) $(basename $HISTFILE) | grep -v '^[^:]*:#' + ) +} + # Focus on the terminal specified by the user. function terminal() { - HOSTNAME=$(hostname -s) - p="${HOSTNAME}"'_.*_'"$1" + p="${HIST_IDENTIFIER}"'_.*_'"$1" t=$(ls "$HOME/.terminal" | grep "$p") if [ -f "$HOME/.terminal/$t" ] ; then w=$(cat "$HOME/.terminal/$t") @@ -207,7 +255,7 @@ function recall { else echo "# $d" echo "\$ $c" - grep "#$t :: " $HISTFILE | sed -e 's/^#[0-9]* :: //' + grep "#$t :: " $f | sed -e 's/^#[0-9]* :: //' fi fi fi @@ -224,6 +272,7 @@ function histpush { else export HISTFILES="$HISTFILES:$HISTFILE" fi + history -a export HISTFILE="$1" history -r fi @@ -233,6 +282,7 @@ function histpush { function histpop { if [ -n "$HISTFILES" ] then + history -a export HISTFILE="${HISTFILES%%:*}" history -r if [ "${HISTFILES/:/}" == "$HISTFILES" ]