IT Share you

현재 디렉토리를 bash 기록에 저장

shareyou 2020. 12. 8. 20:26
반응형

현재 디렉토리를 bash 기록에 저장


히스토리에서 명령과 함께 각 명령이 실행 된 현재 디렉터리를 저장하고 싶습니다. 엉망이되지 않도록 줄 끝에 주석으로 현재 디렉터리를 추가 할 생각이었습니다. 예가 도움이 될 수 있습니다.

$ cd /usr/local/wherever
$ grep timmy accounts.txt

bash가 마지막 명령을 다음과 같이 저장하고 싶습니다.

grep timmy accounts.txt # /usr/local/wherever

아이디어는 이렇게하면 내가 명령을 내린 위치를 즉시 볼 수 있다는 것입니다.


한 줄 버전

다음은 한 줄짜리 버전입니다. 원본입니다. 또한 몇 가지 추가 된 기능이 있는 짧은 기능 버전긴 기능 버전게시했습니다 . 나는 함수 버전이 당신의 환경에서 다른 변수를 방해하지 않고 한 줄보다 훨씬 더 읽기 쉽기 때문에 좋아합니다. 이 게시물에는 다른 항목에서 중복되지 않을 수있는 모든 작업 방식에 대한 정보가 있습니다.

~/.bashrc파일에 다음을 추가 하십시오.

export PROMPT_COMMAND='hpwd=$(history 1); hpwd="${hpwd# *[0-9]*  }"; if [[ ${hpwd%% *} == "cd" ]]; then cwd=$OLDPWD; else cwd=$PWD; fi; hpwd="${hpwd% ### *} ### $cwd"; history -s "$hpwd"'

이렇게하면 다음과 같은 내역 항목이 생성됩니다.

rm subdir/file ### /some/dir

내가 사용하는 ###사용자가 입력 할 수 있습니다 당신은 빈 명령 행에 입력 누르면 축적 다른 것 이전 경로의 주석을 제거 할 때 충돌의 가능성을 줄일 수 있다는 의견과 차별화를 설정하는 주석 구분 기호로. 불행히도 부수적 인 영향은 echo " ### "매우 드물지만 같은 명령 이 망가진다는 것입니다.

어떤 사람들은 내가 같은 변수 이름을 재사용하는 것이 불쾌하다는 사실을 알게 될 것입니다. 보통은 그렇지 않지만 여기서는 발자국을 최소화하려고합니다. 어떤 경우에도 쉽게 변경됩니다.

HISTTIMEFORMAT다른 방식으로 히스토리를 사용 하거나 수정 하지 않는다고 맹목적으로 가정합니다 . 기능 date대신 주석에 명령 을 추가하는 것은 쉽습니다 HISTTIMEFORMAT. 그러나 어떤 이유로 든 사용해야하는 경우 자동으로 설정 해제되므로 하위 셸에서 계속 작동합니다.

$ htf="%Y-%m-%d %R "    # save it for re-use
$ (HISTTIMEFORMAT=$htf; history 20)|grep 11:25

그것에는 몇 가지 아주 작은 문제가 있습니다. 하나는 다음 history과 같은 명령 을 사용하는 경우입니다 .

$ history 3
echo "hello world" ### /home/dennis
ls -l /tmp/file ### /home/dennis
history 3

결과는 history위쪽 화살표를 누르거나 다른 history명령을 실행 하면 표시 되더라도 명령 자체 에 대한 주석을 표시하지 않습니다 .

다른 하나는 줄 바꿈이 포함 된 명령이 주석 처리 된 복사본과 함께 기록에 주석 처리되지 않은 복사본을 남긴다는 것입니다.

다른 문제가 나타날 수 있습니다. 찾으면 알려주세요.

작동 원리

Bash PROMPT_COMMANDPS1기본 프롬프트가 실행될 때 마다 변수에 포함 된 명령을 실행합니다 . 이 작은 스크립트는이를 활용하여 기록의 마지막 명령을 가져 와서 주석을 추가하고 다시 저장합니다.

여기에서는 주석으로 분리됩니다.

hpwd=$(history 1)              # grab the most recent command
hpwd="${hpwd# *[0-9]*  }"      # strip off the history line number
if [[ ${hpwd%% *} == "cd" ]]   # if it's a cd command, we want the old directory
then                           #   so the comment matches other commands "where *were* you when this was done?"
    cwd=$OLDPWD
else
    cwd=$PWD
fi
hpwd="${hpwd% ### *} ### $cwd" # strip off the old ### comment if there was one so they 
                               #   don't accumulate, then build the comment
history -s "$hpwd"             # replace the most recent command with itself plus the comment

hcmnt-긴 기능 버전

다음은 함수 형태의 긴 버전입니다. 그것은 괴물 이지만 몇 가지 유용한 기능을 추가합니다. 또한 한 줄짜리 (원본)와 더 짧은 기능을 게시했습니다. 나는 함수 버전이 당신의 환경에서 다른 변수를 방해하지 않고 한 줄보다 훨씬 더 읽기 쉽기 때문에 좋아합니다. 작동 방식과 몇 가지 제한 사항에 대한 추가 정보는 한 줄짜리 항목과 아래 기능의 설명을 읽으십시오. 좀 더 체계적으로 유지하기 위해 각 버전을 자체 답변으로 게시했습니다.

라는 파일에 저장이 하나를 사용하여 hcmnt같은 위치에 /usr/local/bin(당신은 할 수 있습니다 chmod +x당신이 원하는 경우) 다음 소스를 당신의에서 ~/.bashrc이 같은 :

source /usr/local/bin/hcmnt
export hcmntextra='date "+%Y%m%d %R"'
export PROMPT_COMMAND='hcmnt'

PROMPT_COMMAND또는 hcmntextra설정된 위치에서 함수의 파일을 편집하지 마십시오 . 기본값으로 유지되도록 그대로 두십시오. 당신에 포함 .bashrc에 대한 옵션 설정에 표시된대로 위의 편집 그들이 hcmnt또는 변경 또는 해제에 hcmntextra. 짧은 기능과 달리이 기능을 사용하려면 hcmntextra변수를 설정 하고-e 해당 기능이 작동하도록 옵션을 사용해야합니다 .

함수의 주석에 몇 가지 예제와 함께 문서화 된 여러 옵션을 추가 할 수 있습니다. 한 가지 주목할만한 기능은 주석이 추가 된 기록 항목을 파일에 기록하고 실제 기록은 그대로 두는 것입니다. 이 기능을 사용하려면 다음 과 같이 -l 파일 이름 옵션을 추가하십시오 .

export PROMPT_COMMAND="hcmnt -l ~/histlog"

-n-t상호 배타적 인 것을 제외하고 모든 옵션 조합을 사용할 수 있습니다 .

#!/bin/bash
hcmnt() {

# adds comments to bash history entries (or logs them)

# by Dennis Williamson - 2009-06-05 - updated 2009-06-19
# http://stackoverflow.com/questions/945288/saving-current-directory-to-bash-history
# (thanks to Lajos Nagy for the idea)

# the comments can include the directory
# that was current when the command was issued
# plus optionally, the date or other information

# set the bash variable PROMPT_COMMAND to the name
# of this function and include these options:

    # -e - add the output of an extra command contained in the hcmntextra variable
    # -i - add ip address of terminal that you are logged in *from*
    #      if you're using screen, the screen number is shown
    #      if you're directly logged in, the tty number or X display number is shown
    # -l - log the entry rather than replacing it in the history
    # -n - don't add the directory
    # -t - add the from and to directories for cd commands
    # -y - add the terminal device (tty)
    # text or a variable

# Example result for PROMPT_COMMAND='hcmnt -et $LOGNAME'
#     when hcmntextra='date "+%Y%m%d %R"'
# cd /usr/bin ### mike 20090605 14:34 /home/mike -> /usr/bin

# Example for PROMPT_COMMAND='hcmnt'
# cd /usr/bin ### /home/mike

# Example for detailed logging:
#     when hcmntextra='date "+%Y%m%d %R"'
#     and PROMPT_COMMAND='hcmnt -eityl ~/.hcmnt.log $LOGNAME@$HOSTNAME'
#     $ tail -1 ~/.hcmnt.log
#     cd /var/log ### dave@hammerhead /dev/pts/3 192.168.1.1 20090617 16:12 /etc -> /var/log


# INSTALLATION: source this file in your .bashrc

    # will not work if HISTTIMEFORMAT is used - use hcmntextra instead
    export HISTTIMEFORMAT=

    # HISTTIMEFORMAT still works in a subshell, however, since it gets unset automatically:

    #   $ htf="%Y-%m-%d %R "    # save it for re-use
    #   $ (HISTTIMEFORMAT=$htf; history 20)|grep 11:25

    local script=$FUNCNAME

    local hcmnt=
    local cwd=
    local extra=
    local text=
    local logfile=

    local options=":eil:nty"
    local option=
    OPTIND=1
    local usage="Usage: $script [-e] [-i] [-l logfile] [-n|-t] [-y] [text]"

    local newline=$'\n' # used in workaround for bash history newline bug
    local histline=     # used in workaround for bash history newline bug

    local ExtraOpt=
    local LogOpt=
    local NoneOpt=
    local ToOpt=
    local tty=
    local ip=

    # *** process options to set flags ***

    while getopts $options option
    do
        case $option in
            e ) ExtraOpt=1;;        # include hcmntextra
            i ) ip="$(who --ips -m)" # include the terminal's ip address
                ip=($ip)
                ip="${ip[4]}"
                if [[ -z $ip ]]
                then
                    ip=$(tty)
                fi;;
            l ) LogOpt=1            # log the entry
                logfile=$OPTARG;;
            n ) if [[ $ToOpt ]]
                then
                    echo "$script: can't include both -n and -t."
                    echo $usage
                    return 1
                else
                    NoneOpt=1       # don't include path
                fi;;
            t ) if [[ $NoneOpt ]]
                then
                    echo "$script: can't include both -n and -t."
                    echo $usage
                    return 1
                else
                    ToOpt=1         # cd shows "from -> to"
                fi;;
            y ) tty=$(tty);;
            : ) echo "$script: missing filename: -$OPTARG."
                echo $usage
                return 1;;
            * ) echo "$script: invalid option: -$OPTARG."
                echo $usage
                return 1;;
        esac
    done

    text=($@)                       # arguments after the options are saved to add to the comment
    text="${text[*]:$OPTIND - 1:${#text[*]}}"

    # *** process the history entry ***

    hcmnt=$(history 1)              # grab the most recent command

    # save history line number for workaround for bash history newline bug
    histline="${hcmnt%  *}"

    hcmnt="${hcmnt# *[0-9]*  }"     # strip off the history line number

    if [[ -z $NoneOpt ]]            # are we adding the directory?
    then
        if [[ ${hcmnt%% *} == "cd" ]]    # if it's a cd command, we want the old directory
        then                             #   so the comment matches other commands "where *were* you when this was done?"
            if [[ $ToOpt ]]
            then
                cwd="$OLDPWD -> $PWD"    # show "from -> to" for cd
            else
                cwd=$OLDPWD              # just show "from"
            fi
        else
            cwd=$PWD                     # it's not a cd, so just show where we are
        fi
    fi

    if [[ $ExtraOpt && $hcmntextra ]]    # do we want a little something extra?
    then
        extra=$(eval "$hcmntextra")
    fi

    # strip off the old ### comment if there was one so they don't accumulate
    # then build the string (if text or extra aren't empty, add them plus a space)
    hcmnt="${hcmnt% ### *} ### ${text:+$text }${tty:+$tty }${ip:+$ip }${extra:+$extra }$cwd"

    if [[ $LogOpt ]]
    then
        # save the entry in a logfile
        echo "$hcmnt" >> $logfile || echo "$script: file error." ; return 1
    else

        # workaround for bash history newline bug
        if [[ $hcmnt != ${hcmnt/$newline/} ]] # if there a newline in the command
        then
            history -d $histline # then delete the current command so it's not duplicated
        fi

        # replace the history entry
        history -s "$hcmnt"
    fi

} # END FUNCTION hcmnt

# set a default (must use -e option to include it)
export hcmntextra='date "+%Y%m%d %R"'      # you must be really careful to get the quoting right

# start using it
export PROMPT_COMMAND='hcmnt'

업데이트 2009-06-19 : 로깅에 유용한 옵션 (ip 및 tty) 추가, 중복 항목 문제에 대한 해결 방법, 불필요한 null 할당 제거


또는 히스토리를 sqlite 데이터베이스에 쓰는 오픈 소스 도구 인 Advanced Shell History를 설치할 수 있습니다. 이것은 현재 작업 디렉토리, 명령 종료 코드, 명령 시작 및 중지 시간, 세션 시작 및 중지 시간, tty 등을 기록합니다.bashzsh

히스토리 데이터베이스를 쿼리하려는 경우 고유 한 SQL 쿼리를 작성하고 저장 한 다음 번들 ash_query도구 내에서 사용할 수 있도록 할 수 있습니다 . 몇 가지 유용한 미리 패키지 된 쿼리가 있지만 SQL을 잘 알고 있기 때문에 일반적으로 데이터베이스를 열고 무언가를 찾아야 할 때 대화식으로 쿼리합니다.

그러나 내가 매우 유용하다고 생각하는 한 가지 쿼리는 현재 작업 디렉토리의 기록을 보는 것입니다. 작업 할 때 중단했던 부분을 기억하는 데 도움이됩니다.

vagrant@precise32:~$ ash_query -q CWD
session
    when                   what
1
    2014-08-27 17:13:07    ls -la
    2014-08-27 17:13:09    cd .ash
    2014-08-27 17:16:27    ls
    2014-08-27 17:16:33    rm -rf advanced-shell-history/
    2014-08-27 17:16:35    ls
    2014-08-27 17:16:37    less postinstall.sh
    2014-08-27 17:16:57    sudo reboot -n

현재 작업 디렉토리 (및 그 아래의 모든 항목)를 사용한 동일한 기록 :

vagrant@precise32:~$ ash_query -q RCWD
session
    where
        when                   what
1
    /home/vagrant/advanced-shell-history
        2014-08-27 17:11:34    nano ~/.bashrc
        2014-08-27 17:12:54    source /usr/lib/advanced_shell_history/bash
        2014-08-27 17:12:57    source /usr/lib/advanced_shell_history/bash
        2014-08-27 17:13:05    cd
    /home/vagrant
        2014-08-27 17:13:07    ls -la
        2014-08-27 17:13:09    cd .ash
    /home/vagrant/.ash
        2014-08-27 17:13:10    ls
        2014-08-27 17:13:11    ls -l
        2014-08-27 17:13:16    sqlite3 history.db
        2014-08-27 17:13:43    ash_query
        2014-08-27 17:13:50    ash_query -Q
        2014-08-27 17:13:56    ash_query -q DEMO
        2014-08-27 17:14:39    ash_query -q ME
        2014-08-27 17:16:26    cd
    /home/vagrant
        2014-08-27 17:16:27    ls
        2014-08-27 17:16:33    rm -rf advanced-shell-history/
        2014-08-27 17:16:35    ls
        2014-08-27 17:16:37    less postinstall.sh
        2014-08-27 17:16:57    sudo reboot -n

FWIW-저는 프로젝트의 작성자이자 관리자입니다.


hcmnts-짧은 기능 버전

다음은 함수 형태의 짧은 버전입니다. 또한 한 줄짜리 (원본)와 몇 가지 추가 기능이있는 더 긴 기능을 게시했습니다. 나는 함수 버전이 당신의 환경에서 다른 변수를 방해하지 않고 한 줄보다 훨씬 더 읽기 쉽기 때문에 좋아합니다. 이것이 작동하는 방법과 몇 가지 제한 사항에 대한 추가 정보는 한 줄짜리 항목을 읽으십시오. 좀 더 체계적으로 유지하기 위해 각 버전을 자체 답변으로 게시했습니다.

라는 파일에 저장이 하나를 사용하여 hcmnts같은 위치에 /usr/local/bin(당신은 할 수 있습니다 chmod +x당신이 원하는 경우) 다음 소스를 당신의에서 ~/.bashrc이 같은 :

source /usr/local/bin/hcmnts

hcmntextra날짜와 시간을 원하지 않는 경우 설정하는 줄을 주석으로 처리합니다 (또는 형식을 변경하거나 이외의 다른 명령을 사용할 수 있음 date).

그게 전부입니다.

#!/bin/bash
hcmnts() {
    # adds comments to bash history entries

    # the *S*hort version of hcmnt (which has many more features)

    # by Dennis Williamson
    # http://stackoverflow.com/questions/945288/saving-current-directory-to-bash-history
    # (thanks to Lajos Nagy for the idea)

    # INSTALLATION: source this file in your .bashrc

    # will not work if HISTTIMEFORMAT is used - use hcmntextra instead
    export HISTTIMEFORMAT=

    # HISTTIMEFORMAT still works in a subshell, however, since it gets unset automatically:

    #   $ htf="%Y-%m-%d %R "    # save it for re-use
    #   $ (HISTTIMEFORMAT=$htf; history 20)|grep 11:25

    local hcmnt
    local cwd
    local extra

    hcmnt=$(history 1)
    hcmnt="${hcmnt# *[0-9]*  }"

    if [[ ${hcmnt%% *} == "cd" ]]
    then
        cwd=$OLDPWD
    else
        cwd=$PWD
    fi

    extra=$(eval "$hcmntextra")

    hcmnt="${hcmnt% ### *}"
    hcmnt="$hcmnt ### ${extra:+$extra }$cwd"

    history -s "$hcmnt"
}
export hcmntextra='date +"%Y%m%d %R"'
export PROMPT_COMMAND='hcmnts'

zsh에서 이것을 원하는 사람들을 위해 Jeet Sukumaran의 구현 및 percol을 수정 하여 명령 또는 실행 된 경로의 대화식 키워드 검색 및 추출을 허용했습니다. 중복 명령을 필터링하고 필드 (날짜, 명령, 통로)


Gentleman this works better .. 내가 알아낼 수없는 유일한 것은 로그인시 syslog에 스크립트를 기록하지 않고 기록의 마지막 명령을 기록하는 방법입니다. 그러나 지금까지는 매력처럼 작동합니다.

#! / bin / bash

trackerbash () {
    # bash 히스토리 항목에 주석을 추가합니다.

    # by Dennis Williamson
    # http://stackoverflow.com/questions/945288/saving-current-directory-to-bash-history
    # (아이디어에 대해 Lajos Nagy에게 감사드립니다)

    #QXT로 향상된 저녁 식사


    # INSTALLATION :이 파일을 .bashrc에 저장하십시오.

    export HISTTIMEFORMAT=
#    export HISTTIMEFORMAT='%F   %T    '

    local hcmnt
    local cwd
    local extra
    local thistty
    local whoiam
    local sudouser
    local shelldate
    local TRACKIP
    local TRACKHOST


            thistty=`/usr/bin/tty|/bin/cut -f3-4 -d/`
            whoiam=`/usr/bin/whoami`
            sudouser=`last |grep $thistty |head -1 | awk '{ print $1 }' |cut -c 1-10`
            hcmnt=$(history 1)
            hcmnt="${hcmnt# *[0-9]*  }"
            cwd=`pwd`



            hcmnt="${hcmnt% ### *}"
            hcmnt=" $hcmnt ${extra:+$extra }"

            shelldate=`date +"%Y %b %d %R:%S"`
            TRACKHOST=`whoami | sed -r "s/.*\((.*)\).*/\\1/"`
            TRACKIP=`last |grep $thistty |head -1 | awk '{ print $3 }'`


            logger -p local1.notice -t bashtracker -i -- "$sudouser ${USER}: $thistty: $TRACKIP: $shelldate: $cwd : $hcmnt"
            history -w 

}
export PROMPT_COMMAND='trackerbash'


Full disclosure: I'm the author of the FOSS-tool
shournal - A (file-) journal for your shell:
Using it's bash integration, the working directory of a command is also stored within shournal's sqlite-database and can be retrieved via

shournal --query -cmdcwd "$PWD"

Querying for sub-working-directories can be done with

shournal --query -cmdcwd -like "$PWD/%"

Here's a one liner of what I use. Sticking it here because it's vastly simpler, and I have no problem with per-session history, I just also want to have a history with the working directory.

Also the one-liner above mucks with your user interface too much.

export PROMPT_COMMAND='if [ "$(id -u)" -ne 0 ]; then echo "$(date "+%Y-%m-%d.%H:%M:%S") $(pwd) $(history 1)" >> ~/.bash.log; fi'

Since my home dir is typically a cross-mounted gluster thingy, this has the side effect of being a history of everything I've ever done. Optionally add $(hostname) to the echo command above... depending on your working environment.

Even with 100k entries, grep is more than good enough. No need to sqlite log it. Just don't type passwords on the command line and you're good. Passwords are 90's tech anyway!

Also, for searching I tend to do this:

function hh() {
    grep "$1" ~/.bash.log
}

참고URL : https://stackoverflow.com/questions/945288/saving-current-directory-to-bash-history

반응형