เหตุใด `ประเภทที่` บอกว่า `ซึ่งถูก hashed '


31

ในกรณีของ shell-builtins (เช่นtypeตัวมันเอง):

$ type type
type is a shell builtin

$ which type
<Doesn't return anything since it's a shell builtin, silently exits>

ในกรณีของคำสั่ง (ปกติ) (เช่นpython):

$ type python
python is /usr/bin/python

$ which python
/usr/bin/python

ในกรณีของwhich(ซึ่งเป็นคำสั่งตั้งอยู่ที่/usr/bin/which)

$ type which
which is hashed (/usr/bin/which)
$ which which
/usr/bin/which

ทำไมถึงtype whichพูดอย่างนั้นwhich is hashed? ความสำคัญของwhichการถูกแฮชคืออะไรและมันหมายถึงอะไรจริง ๆ ?

คำตอบ:


40

คุณน่าจะมีชุด PATH ที่มีความยาวและในการค้นหาไฟล์สั่งการเชลล์จำเป็นต้องค้นหาพา ธ เพื่อหลีกเลี่ยงกระบวนการที่ต้องใช้เวลาทุกครั้งที่คุณต้องการเรียกใช้โปรแกรมเชลล์อาจเก็บรายการโปรแกรมที่พบแล้ว รายการนั้นเรียกว่า "แฮช" เมื่อเชลล์บอกว่าwhichถูกแฮชหมายความว่ามันทำการค้นหา PATH เรียบร้อยแล้วและพบwhichและบันทึกตำแหน่งของมันไว้ในแฮช

man bash อธิบายได้ดังนี้

Bash ใช้ตารางแฮชเพื่อจดจำชื่อพา ธ เต็มของไฟล์ที่เรียกใช้งานได้ (ดูที่แฮชภายใต้คำสั่ง SHELL BUILTIN คำสั่งด้านล่าง) การค้นหาไดเรกทอรีทั้งหมดใน PATH จะดำเนินการเฉพาะในกรณีที่ไม่พบคำสั่งในตารางแฮช

ในขณะที่แฮชจะเร่งความเร็วการทำงานของเชลล์โดยทั่วไปจะมีกรณีหนึ่งที่ทำให้เกิดปัญหา หากคุณอัปเดตระบบของคุณและด้วยเหตุนี้บางไฟล์ที่รันได้จะย้ายไปยังตำแหน่งใหม่เชลล์อาจสับสน วิธีแก้ปัญหาคือการทำงานhash -rซึ่งทำให้เชลล์ลืมตำแหน่งที่ถูกแฮชทั้งหมดและค้นหา PATH ตั้งแต่เริ่มต้น

เหตุใดบางไฟล์ประมวลผลจึงหายไปจากแฮช

การปฏิบัติการไม่ได้อยู่ในแฮชจนกว่าคุณจะดำเนินการอย่างน้อยหนึ่งครั้ง สังเกต:

$ type python
python is /usr/bin/python
$ python --version
Python 2.7.3
$ type python
python is hashed (/usr/bin/python)

python ถูกแฮชหลังจากที่ถูกเรียกใช้งานเท่านั้น

วิธีตรวจสอบสิ่งที่อยู่ในแฮชของ bash

เนื้อหาของกัญชาที่มีอยู่ในอาร์เรย์bash คุณสามารถมองเห็นสิ่งที่อยู่ในนั้นด้วยคำสั่งBASH_CMDS declare -p BASH_CMDSเมื่อเปิดเชลล์หรือเชลล์ย่อยใหม่แฮชจะว่างเปล่า คำสั่งจะถูกเพิ่มทีละคำตามที่ใช้ จากเปลือกที่เพิ่งเปิดใหม่สังเกต:

$ declare -p BASH_CMDS
declare -A BASH_CMDS='()'
$ which which
/bin/which
$ declare -p BASH_CMDS
declare -A BASH_CMDS='([which]="/bin/which" )'
$ python --version
Python 2.7.3
$ declare -p BASH_CMDS
declare -A BASH_CMDS='([which]="/bin/which" [python]="/usr/bin/python" )'

+1 คำอธิบายที่ดีงาม แต่ทำไมwhichและไม่ใช่เพื่อpython?
jobin

@Jobin ดูคำตอบที่อัพเดตแล้ว
John1024

2
ดูเหมือนว่าแฮชจะยังคงอยู่จนกว่าจะถึงเวลาที่เราจะไม่ออกจากเปลือก เมื่อเรารีสตาร์ทเทอร์มินัลก็ไม่ได้บอกว่าคำสั่งถูกแฮช
Aditya

1
@Aditya ใช่ ฉันได้เพิ่มหัวข้อในคำตอบ
John1024

hash -lจะใช้งานง่ายกว่าdeclare -p BASH_CMDS
phuclv
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.