해시 명령의 목적은 무엇입니까?


118

당신이 실행하는 경우 hash는 (해시 이후 실행되는 모든 명령의 경로가 마지막으로 재설정했다 보여줍니다 hash -r)

[root@c04c ~]# hash
hash: hash table empty

[root@c04c ~]# whoami
root

[root@c04c ~]# hash
hits    command
   1    /usr/bin/whoami

[root@c04c ~]# whoami
root

[root@c04c ~]# hash
hits    command
   2    /usr/bin/whoami

매뉴얼 페이지에 따르면 해시의 목적은 다음과 같습니다.

/ usr / bin / hash 유틸리티는 현재 쉘 환경이 찾은 유틸리티의 위치를 ​​기억하는 방식에 영향을줍니다. 지정된 인수에 따라 유틸리티 위치를 기억 된 위치 목록에 추가하거나 목록의 내용을 제거합니다. 인수가 지정되지 않으면 목록의 내용을보고합니다. 이 -r옵션을 사용하면 쉘이 기억 된 모든 위치를 잊게됩니다.

쉘에 내장으로 제공된 유틸리티는 해시로보고되지 않습니다.

명령을 몇 번 입력했는지 보지 않으면의 유틸리티를 볼 수 없습니다 hash.

심지어 thegeekstuff.com의 유용한 15 가지 명령에 소개되었습니다.

어떤 방법으로 hash유용합니까?

답변:


97

hashbash 내장 명령입니다. 해시 테이블은 메모리에 결과를 캐싱하여 명령을 입력 할 때마다 bash 검색하지 않아도 되는 기능입니다 $PATH. 결과를 분명히 무효화하는 이벤트 (예 : 수정 $PATH) 에서 테이블이 지워집니다.

hash해당 시스템 (중 당신이 느끼는 이유 당신이 필요)와 상호 작용하는 방법 명령은 단지이다.

일부 사용 사례 :

  • 보았 듯이 인수없이 입력하면 어떤 명령을 몇 번 쳤는지 인쇄합니다. 이것은 가장 자주 사용하는 명령을 알려줍니다.

  • 표준이 아닌 위치에서 실행 파일을 기억하는 데 사용할 수도 있습니다.

예:

[root@policyServer ~]# hash -p /lol-wut/whoami whoami
[root@policyServer ~]# whoami
Not what you're thinking
[root@policyServer ~]# which whoami
/usr/bin/whoami
[root@policyServer ~]# /usr/bin/whoami
root
[root@policyServer ~]#

외부 디렉토리에 하나의 실행 파일이있는 경우 $PATH해당 디렉토리의 모든 것을 포함하는 대신 이름을 입력하여 실행하려는 경우 유용 할 수 있습니다 (추가 한 경우 영향을 미침 $PATH).

별명도 일반적으로이 작업을 수행 할 수 있지만 현재 쉘의 동작을 수정하기 때문에 시작한 프로그램에는 매핑되지 않습니다. 고독한 실행 파일에 대한 심볼릭 링크가 여기에서 선호되는 옵션 일 것입니다. hash한 가지 방법입니다.

  • 파일 경로를 기억 해제하는 데 사용할 수 있습니다. 이것은 새로운 실행 파일이 이전 PATH디렉토리 에서 팝업 되거나 mv다른 곳으로 이동하여 bash가 파일을 찾은 것을 기억하는 마지막 위치 대신 강제로 나가서 다시 찾으려고 할 때 유용 합니다.

예:

[root@policyServer ~]# hash
hits    command
   1    /bin/ls
[root@policyServer ~]# cp /bin/ls /lol-wut
[root@policyServer ~]# hash
hits    command
   1    /bin/cp
   1    /bin/ls
[root@policyServer ~]# hash -d ls
[root@policyServer ~]# ls
default.ldif  newDIT.ldif  notes.txt  users.ldif
[root@policyServer ~]# hash
hits    command
   1    /bin/cp
   1    /lol-wut/ls
[root@policyServer ~]#

cp명령으로 인해 ls실행 파일 의 새 버전이 초기에 표시 $PATH되었지만 해시 테이블 제거가 트리거되지 않았습니다. 해시 테이블에서 hash -d항목을 선택적으로 제거하는 데 사용 했습니다 ls. Bash는 $PATH다시 한 번 살펴 보았고 새로운 위치에서 찾았습니다 (이전의 $ PATH 이전).

이 "실행 파일의 새로운 위치 찾기 $PATH"동작을 선택적으로 호출 할 수 있습니다 .

[root@policyServer ~]# hash
hits    command
   1    /bin/ls
[root@policyServer ~]# hash ls
[root@policyServer ~]# hash
hits    command
   0    /lol-wut/ls
[root@policyServer ~]#

해시 테이블에서 무언가를 원하고 로그 아웃 한 다음 다시 로그인 할 수있는 100 %가 아니거나 쉘에 대한 수정 사항을 유지하려는 경우 대부분이 작업을 수행하려고합니다.

오래된 매핑을 제거하려면 bash의 전체 해시 테이블을 효과적으로 제거하는 hash -r(또는 export PATH=$PATH) 작업을 수행 할 수도 있습니다 .

그런 작은 상황이 많이 있습니다. "가장 유용한"명령 중 하나라고 부르는지 모르겠지만 일부 사용 사례가 있습니다.


'해시'라는 이름이 어디에서 유래했는지 궁금합니다. 그렇다면 "캐시"는 어떻습니까? :).
Michael

2
@Michael이 hash명령은 내부적으로 해시 테이블을 사용하여 매핑을 저장하기 때문입니다. en.wikipedia.org/wiki/Hash_table
jlliagre

10
그주의해야 hash되지 않습니다 bash(명령의 경로를 해싱의 기능에서 유래하지만 명령이 SVR2의 Bourne 쉘에서 유래, 특정 csh그 전에) 모든 Bourne의 같은과 POSIX 쉘에서 발견된다.
Stéphane Chazelas

1
export PATH=$PATH테이블을 지우는 대신 hash -r충분해야합니다.
ravron

1
또 다른 사용 사례는 프로그램의 두 번째 사본을 $ PATH의 이전 부분에 설치할 때입니다. hash -r$ PATH는 변경되지 않았으므로 Bash는 이전 (더 높은 우선 순위) 디렉토리에서 동일한 프로그램을로드 할 수 있다는 것을 인식하지 못하므로 이전 버전이 필요합니다 . 자세한 내용은 conda.pydata.org/docs/… 를 참조하십시오.
존 즈 빙크

37

다음은 고전적인 사용법입니다.

# My PATH contains /home/rici/bin as well as the Usual Suspects:
# (the real one has lots more)
$ echo $PATH
/home/rici/bin:/usr/local/bin:/usr/bin:/bin

# I've installed a program called hello in /usr/local/bin
$ $ cat /usr/local/bin/hello
#!/bin/bash

echo Hello, world. I live at $0

# The program works.
$ hello
Hello, world. I live at /usr/local/bin/hello

# Now I want to create a better hello, just for me. I put it in
# my own bin directory, and according to my PATH, it should come first.
$ cp /usr/local/bin/hello ~/bin/hello

# So now I will try running it
$ hello
Hello, world. I live at /usr/local/bin/hello

# WTF? Oh, forgot to run hash.
# Tell bash to update where to look for hello
$ hash hello
$ hello
Hello, world. I live at /home/rici/bin/hello

# Ah, all is well.

여기에서 언급 한 것처럼 단일 명령으로 해시 테이블의 선택적 업데이트를 호출 할 수 있습니다 hash hello.
Ioannis Filippidis

@ johntex : 좋아, 변경되었습니다.
rici

해시 테이블이 존재하기 전에 이상한 버그가 발생할 가능성을 상상해보십시오! 해시 테이블이 자동으로 새로 고쳐지는 환경 목록이 있습니까?
벤 지민

@ benji : 자동으로 (전체적으로) 새로 고쳐지지 않습니다. posix 모드에서 bash를 실행하거나 setopt -s checkhash명령에 대한 해시 실행 파일이 더 이상 존재하지 않으면 해당 명령의 해시 항목이 업데이트됩니다. 그러나 모든 bash 세션에는 자체 해시 테이블이 있으므로 세션을 닫고 새 세션을 시작하면 효과적으로 해시가 비워집니다. ( hash -r보다 쉬운 방법입니다.)
rici

을 업데이트 $PATH하거나 새 bash 터미널을 시작하면 테이블을 정리하는 것으로 보입니다.
벤 지민

17

유용한 사용법은 다음과 같습니다 hash.

hash php 2> /dev/null || hash -p /usr/local/foobar/php/bin/php php 2> /dev/null

PHP가 PATH에 없으면 다음을 사용하십시오.

/usr/local/foobar/php/bin/

8

예, Bash Reference Manual 은 다음과 같이 말합니다.

$ PATH의 디렉토리 전체 검색은 명령이 해시 테이블에없는 경우에만 수행됩니다.

그러나 다음을 사용하여 해싱을 비활성화 할 수 있습니다 set +h.

-h-명령을 실행할 때 찾아서 (해시) 명령을 기억합니다. 이 옵션은 기본적으로 활성화되어 있습니다.

시험:

set +h
hash # prints bash: hash: hashing disabled
echo $? # prints 1

동일입니다 hash -r, hash NAME

"명령 감지"(예 : 또는 저것 )가 작동하지 않습니다.

set -h
hash ls >/dev/null 2>&1 || echo "Please install ls" >&2 # prints nothing

set +h
hash ls >/dev/null 2>&1 || echo "Please install ls" >&2 # prints Please install ls

다음과 같이 작성할 수 있습니다.

old_options="$-"
set -h
hash ls >/dev/null 2>&1 || echo "Please install ls" >&2
[[ "$old_options" =~ "h" ]] || set +h

또는 새로운 변수를 할당하거나 테스트를 할 필요없이 (@mikeserv 덕분에)

set -h -- "-${-:--}" "$@"
hash ls >/dev/null 2>&1 || echo "Please install ls" >&2
set +h "$@"

1
당신의 old_options일을 위해 -나는 보통 이런 식으로합니다 : set -h -- "-${-:--}" "$@"; hash ...; set +h "$@"그래서 그것은 새로운 변수를 할당하거나 테스트를하지 않고도 자동으로 제자리에 빠집니다.
mikeserv

5

명령 사용 가능 여부를 쉽게 감지 :

CMD=gzip
if hash bzip2; then
    CMD=$_
fi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.