메모리

메모리

내부에배쉬 참조 매뉴얼그것은 다음과 같이 말합니다:

lithist 활성화되고 cmdhist이 옵션이 활성화되면 여러 줄 명령은 가능한 경우 세미콜론 구분 기호를 사용하는 대신 포함된 줄 바꿈을 사용하여 기록에 저장됩니다.

그래서 내 질문은 다음과 같습니다어디서/언제/어떻게 가능합니까??

내 장치에서 기능을 활성화하고 테스트해 보았습니다.GNU bash, 버전 4.4.12(1) - 릴리스이 방법:

shopts -s cmdhist
shopts -s lithist
echo -n "this is a test for a ";\
echo "multiline command"

그런 다음 나는

history | tail 

다음과 유사한 출력이 예상됩니다.

101 shopts -s cmdlist
102 shopts -s lithist
103 echo -n "this is a test for a ";\
    echo "multiline command"
104 history

하지만 이것을 얻으십시오 :

101 shopts -s cmdlist
102 shopts -s lithist
103 echo -n "this is a test for a "; echo "multiline command"
104 history

분명히 여러 줄 명령(bash 기록 번호 103)이 아직 저장되지 않았습니다."세미콜론 구분 기호를 사용하는 대신 삽입라인 나누기". 여기서는 왜 lithist불가능합니까? 내가 뭘 잘못했나요?

답변1

A는 역사에서 a를 얻는 올바른 방법이 \<new line>아닙니다 .<new line>

메모리

기록 행은 디스크가 아닌 쉘 메모리에 보관되므로 기록 행만 처리합니다.

지금까지 했던 것처럼 몇 가지 명령을 입력해 보겠습니다.

$ echo -n "this is a test for a ";\
> echo "two line command"

행이 방금 작성되었을 때 메모리에 무엇이 저장되었습니까?

$ history 2
514  echo -n "this is a test for a ";echo "two line command"
515  history 2

보시다시피 "줄 연속"(백슬래시 다음에 줄 바꿈)이 제거되었습니다.
(man bash에서) 다음과 같이 해야 합니다.

\ 쌍이 발생하고 백슬래시 자체가 따옴표로 묶이지 않은 경우 \는 줄 연속으로 처리됩니다(즉, 입력 스트림에서 제거되어 사실상 무시됩니다).

인용하면 개행 문자가 나타날 수 있습니다.

$ echo " A test of 
> a new line"
A test of 
a new line

그리고 이 시점에서 역사는 다음을 반영할 것입니다.

$ history 2
  518  echo "A test of
a new line"
  519  history 2

실제 여러 줄 명령:

여러 줄 명령의 가능한 예는 다음과 같습니다.

$ for a in one two
> do echo "test $a"
> done
test one
test two

다음과 같은 경우 기록이 한 줄로 축소됩니다 cmdhist is set.

$ shopt -p cmdhist lithist
shopt -s cmdhist                                                                                                       
shopt -u lithist

$ history 3
   24  for a in one two; do echo "test $a"; done                                                                       
   25  shopt -p cmdhist lithist                                                                                        
   26  history 3     

어느 시점에서 .clear 를 사용하여 (메모리에서) 기록을 지웠기 때문에 각 명령에 대해 숫자가 변경되었습니다 history -c.

cmdhist를 설정 해제하면 다음 메시지가 표시됩니다.

$ shopt -u cmdhist
$ for a in one two
> do echo "test $a"
> done
test one
test two

$ history 5
    5  shopt -u cmdhist
    6  for a in one two
    7  do echo "test $a"
    8  done
    9  history 5

각 줄(완전한 명령이 아님)은 기록에서 별도의 줄에 표시됩니다.

설정된 경우에도 lithist:

$ shopt -s lithist
$ for a in one two
> do echo "test $a"
> done
test one
test two
$ history 5
   12  shopt -s lithist
   13  for a in one two
   14  do echo "test $a"
   15  done
   16  history 5

그러나 둘 다 설정된 경우:

$ shopt -s cmdhist lithist
$ for a in one two
> do echo "test $a"
> done

$ history 5
   23  history 15
   24  shopt -p cmdhist lithist
   25  shopt -s cmdhist lithist
   26  for a in one two
do echo "test $a"
done
   27  history 5

명령은 for여러 줄 명령으로 저장되며 세미콜론( ;) 대신 "개행" 문자를 사용합니다. 위의 lithist가 설정되지 않은 경우와 비교해 보세요.

디스크

위의 모든 내용은 셸 메모리에 저장된 명령 목록을 사용하여 해석됩니다. 디스크에 명령이 기록되지 않았습니다. (기본값) 파일이 ~/.bash_history변경되지 않습니다.

이 파일은 실행 중인 쉘이 종료되면 변경됩니다. 이때 기록은 파일을 덮어쓰거나( histappend설정되지 않은 경우) 추가됩니다.

명령을 디스크에 제출하려면 다음이 필요합니다.이 세트를 가지고:

export PROMPT_COMMAND='history -a'

이렇게 하면 각 명령줄이 각각의 새 명령줄에 있는 파일에 추가됩니다.

이제 cmdhist와 lithist에 대해 논의해 보겠습니다. 상황은 보이는 것만큼 간단하지 않습니다. 하지만 걱정하지 마세요. 곧 모든 것이 명확해질 것입니다.

아래의 모든 명령을 입력하는 데 시간이 걸렸다고 가정합니다(바로가기 없음, 별칭 없음, 기능 없음, 실제 명령이 필요합니다. 죄송합니다).
먼저 메모리( history -c)와 디스크(백업하기) ( history -w) 그런 다음 3번 시도합니다.

  • 기본값인 cmdhist(설정) 및 lithist(설정되지 않음)를 사용합니다.
  • 동시 설정
  • 둘 다 설정되지 않았습니다.
  • unset cmdhist로 lithist를 설정하는 것은 의미가 없습니다(테스트할 수 있습니다).

실행할 명령 목록:

$ history -c ; history -w           # Clear all history ( Please backup).

$ shopt -s cmdhist; shopt -u lithist
$ for a in one two
> do echo "test $a"
> done

$ shopt -s cmdhist; shopt -s lithist
$ for a in one two
> do echo "test $a"
> done

$ shopt -u cmdhist; shopt -u lithist
$ for a in one two
> do echo "test $a"
> done

당신은 (메모리에서) 다음과 같이 끝날 것입니다 :

$ history
    1  shopt -s cmdhist; shopt -u lithist
    2  for a in one two; do echo "test $a"; done
    3  shopt -s cmdhist; shopt -s lithist
    4  for a in one two
do echo "test $a"
done
    5  shopt -u cmdhist; shopt -u lithist
    6  for a in one two
    7  do echo "test $a"
    8  done
    9  history

세 개의 여러 줄 명령은 다음과 같이 끝납니다.

  • 2번 줄 중 하나(한 줄, 한 명령).
  • 4번으로 표시된 여러 줄 중 하나(여러 줄 중 하나의 명령)
  • 6부터 8까지 번호가 매겨진 여러 줄 중 하나

좋아요, 그런데 파일에서 무슨 일이 일어나고 있나요? 이미 말했지만...

마지막으로 파일에서:

간단합니다. 파일에 쓰고 고양이를 보내서 확인하세요.

$ history -w ; cat "$HISTFILE"
shopt -s cmdhist; shopt -u lithist
for a in one two; do echo "test $a"; done
shopt -s cmdhist; shopt -s lithist
for a in one two
do echo "test $a"
done
shopt -u cmdhist; shopt -u lithist
for a in one two
do echo "test $a"
done
history
history -w ; cat "$HISTFILE"

줄 번호도 없고 명령만 있으며 여러 줄이 시작하고 끝나는 위치를 알 수 있는 방법이 없습니다. 여러 줄이 있어도 판단할 방법이 없습니다.

실제로, 위와 같이 명령이 파일에 기록되면 파일을 다시 읽을 때 여러 줄에 대한 모든 정보가 손실됩니다.

구분 기호(개행 문자)는 하나만 있으며 각 줄은 명령으로 다시 읽혀집니다.

해결책이 있습니까? 예, 추가 구분 기호를 사용하십시오.
HISTTIMEFORMAT이 바로 그런 일을 합니다.

과거 시간 형식

이 변수를 값으로 설정하면 각 명령이 실행된 시간이 주석( ) 문자 뒤에 에포크(예, 항상 초) 이후의 초 수로 파일에 저장됩니다 #.

변수를 설정하고 파일을 다시 작성하면 다음과 같은 결과를 ~/.bash_history얻습니다.

$ HISTTIMEFORMAT='%F'
$ history -w ; cat "$HISTFILE"
#1490321397
shopt -s cmdhist; shopt -u lithist
#1490321397
for a in one two; do echo "test $a"; done
#1490321406
shopt -s cmdhist; shopt -s lithist
#1490321406
for a in one two
do echo "test $a"
done
#1490321418
shopt -u cmdhist; shopt -u lithist
#1490321418
for a in one two
#1490321418
do echo "test $a"
#1490321420
done
#1490321429
history
#1490321439
history -w ; cat "$HISTFILE"
#1490321530
HISTTIMEFORMAT='%FT%T '
#1490321571
history -w ; cat "$HISTFILE"

이제 어디에서 어떤 줄이 여러 줄인지 알 수 있습니다.

이 형식은 '%FT%T 'History 명령을 사용할 때만 시간을 표시합니다.

$ history
    1  2017-03-23T22:09:57 shopt -s cmdhist; shopt -u lithist
    2  2017-03-23T22:09:57 for a in one two; do echo "test $a"; done
    3  2017-03-23T22:10:06 shopt -s cmdhist; shopt -s lithist
    4  2017-03-23T22:10:06 for a in one two
do echo "test $a"
done
    5  2017-03-23T22:10:18 shopt -u cmdhist; shopt -u lithist
    6  2017-03-23T22:10:18 for a in one two
    7  2017-03-23T22:10:18 do echo "test $a"
    8  2017-03-23T22:10:20 done
    9  2017-03-23T22:10:29 history
   10  2017-03-23T22:10:39 history -w ; cat "$HISTFILE"
   11  2017-03-23T22:12:10 HISTTIMEFORMAT='%F'
   12  2017-03-23T22:12:51 history -w ; cat "$HISTFILE"
   13  2017-03-23T22:15:30 history
   14  2017-03-23T22:16:29 HISTTIMEFORMAT='%FT%T'
   15  2017-03-23T22:16:31 history
   16  2017-03-23T22:16:35 HISTTIMEFORMAT='%FT%T '
   17  2017-03-23T22:16:37 history

답변2

이것은 여러 줄 명령이 아닌 것 같습니다(귀하가 반환을 이스케이프했기 때문에). 실제 보상이 있는 일을 한다면 차이가 있습니다.

$ for i in /tmp/g*
> do echo $i
> done
/tmp/gigabyte
$ shopt -s lithist
$ for i in /tmp/g*
> do echo $i
> done
/tmp/gigabyte
$ history 
[...]
  517  for i in /tmp/g* ; do echo $i ; done
  518  shopt -s lithist
  519  for i in /tmp/g*
do echo $i
done
  520  history

답변3

iTerm은 여러 줄 명령을 완벽하게 처리하고 여러 줄 명령을 하나의 명령으로 저장한 다음 ++를 사용하여 Cmd기록을 탐색할 수 있습니다. 더 많은 iTerm 팁을 확인하세요:Shift;iTerm으로 효과적으로 작업하세요

답변4

나는 노력했다 shopt -s lithist cmdhist.

그러나 로그아웃 및 로그인 후에도 기록 복구는 ~/.bash_history여전히 여러 줄로 나누어져 있습니다.

 1953  2019-05-23 16:57:53 shopt -s cmdhist; shopt -s lithist
 1954  2019-05-23 16:57:58 for i in 1 2 3
 1955  2019-05-23 16:58:34 do echo $i
 1956  2019-05-23 16:58:34 done
 1957  2019-05-23 16:58:08 history 5
 1958  2019-05-23 16:58:27 history -a
 1959  2019-05-23 16:54:12 history 10 | less 

이 동작이 예상됩니까?

내가 가진 것은 다음과 같습니다 ~/.bash_history.

#1558601873
shopt -s cmdhist; shopt -s lithist
#1558601878
for i in 1 2 3
do echo $i
done
#1558601888
history 5
#1558601907
history -a
#1558601652
history 10 | less 

해결책

이전 ~/.bash_history를 삭제하여 문제를 해결한 다음 로그아웃하고 로그인한 후에도 여러 줄 기록이 제대로 작동했습니다.

    1  2019-06-12 13:53:11 \rm .bash_history
    2  2019-06-12 13:53:27 fx mcd
    3  2019-06-12 13:53:28 mcd () 
{ 
    mkdir $@;
    cd $1
}
    4  2019-06-12 14:55:14 nmcli-restart-hotspot -s
    5  2019-06-12 21:34:35 ssh lab
    6  2019-06-12 23:38:45 history  | less 

관련 정보