Lệnh `which` của tôi có thể sai (đôi khi)?


17

Tôi đã biên dịch phiên bản emacs cuối cùng từ mã nguồn (v24.2) vì phiên bản được cài đặt trên máy của tôi (khá) cũ đối với tôi (v21.3). Tôi đã làm như thường lệ:

$configure --prefix=$HOME
make 
make install

Bây giờ tôi đang thử nghiệm các emacs và nhận ra rằng nó vẫn khởi chạy phiên bản trước đó ... trong khi $HOME/binđường dẫn của tôi được cho là ghi đè lên hệ thống một (vì nó được đặt trước $ PATH trong .bashrctệp của tôi ).

Suy nghĩ đầu tiên của tôi là để xem whichđầu ra lệnh. Và thật bất ngờ, nó đưa ra con đường đến các emacs mới. Tôi không thể hiểu sự khác biệt ở đâu. Trong cùng một phiên ở đây là các đầu ra khác nhau:

$ emacs --version
GNU Emacs 21.3.1

$ `which emacs` --version
GNU Emacs 24.2.1

Tôi không có bí danh liên quan đến emacs. Ở tất cả.

$ alias | grep emacs
$

Bất cứ ý tưởng những gì đang xảy ra xin vui lòng?


những gì emacs trở lại?
Ulrich Dangel

Câu trả lời:


29

Ba khả năng xuất hiện trong đầu tôi:

  • Một bí danh tồn tại cho emacs(mà bạn đã kiểm tra)
  • Một chức năng tồn tại cho emacs
  • Cái mới emacsNhị phân không có trong hàm băm PATH của shell của bạn.

Bạn có thể kiểm tra nếu bạn có một chức năng emacs :

bash-3.2$ declare -F | fgrep emacs
declare -f emacs

Và xóa nó:

unset -f emacs

Shell của bạn cũng có hàm băm PATH chứa tham chiếu đến từng nhị phân trong PATH của bạn. Nếu bạn thêm một nhị phân mới có cùng tên với một nhị phân hiện có ở nơi khác trong PATH của bạn, trình bao cần được thông báo bằng cách cập nhật hashtable:

hash -r

Giải thích thêm:

which không biết về các hàm, vì nó không phải là hàm dựng sẵn:

bash-3.2$ emacs() { echo 'no emacs for you'; }
bash-3.2$ emacs
no emacs for you
bash-3.2$ which emacs
/usr/bin/emacs
bash-3.2$ `which emacs` --version | head -1
GNU Emacs 22.1.1

Hành vi băm nhị phân mới được thể hiện bằng kịch bản này.

bash-3.2$ PATH=$HOME/bin:$PATH
bash-3.2$ cd $HOME/bin

bash-3.2$ cat nofile
cat: nofile: No such file or directory
bash-3.2$ echo echo hi > cat
bash-3.2$ chmod +x cat
bash-3.2$ cat nofile
cat: nofile: No such file or directory

bash-3.2$ hash -r
bash-3.2$ cat nofile
hi
bash-3.2$ rm cat
bash-3.2$ cat nofile
bash: /Users/mrb/bin/cat: No such file or directory

bash-3.2$ hash -r
bash-3.2$ cat nofile
cat: nofile: No such file or directory

Mặc dù tôi đã không gọi nó, nhưng which catsẽ luôn trả lại cái đầu tiên cattrong PATH của tôi, vì nó không sử dụng hàm băm của shell.


1
Trong khi có thông tin tốt ở đây, nó bỏ lỡ typelệnh.
jordanm

Cảm ơn, tôi đã gặp vấn đề tương tự với phiên bản mới được biên dịch của sqlite3, điều này khiến tôi trở nên điên rồ (điều này thực sự đã trả lại đúng đường dẫn, nhưng trình bao không gọi đúng sqlite3 cli). hash -rđã khắc phục vấn đề của tôi.
mpm

12

Có, không sử dụng :

  • Trên một số hệ thống, đó là một lệnh bên ngoài được triển khai dưới dạng tập lệnh csh, có thể đọc cấu hình thay đổi PATH.
  • Có một nội dung cho điều đó. Hai, thậm chí: typecommand. Cách POSIX:

    command -v emacs       # machine-readable format
    type emacs             # human-only format

    Trong bash, bạn cũng có thể sử dụng type -p emacsđể chỉ xem đường dẫn của lệnh bên ngoài.

Tuy nhiên, ở đây, whichlà thực sự đúng. Bash giữ thông tin về vị trí của một lệnh trong bộ nhớ, để nó có thể thực thi lệnh nhanh hơn vào lần tiếp theo. Bạn đã cài đặt một emacstệp thực thi mới trên máy của bạn PATH, nhưng bash vẫn có vị trí cũ trong bộ đệm. Chạy hash emacsđể tra cứu emacslại hoặc hash -rđể trống bộ đệm.


1

Bạn đã đăng xuất và đăng nhập để làm cho .bashrctập tin đăng nhập cập nhật của bạn được đọc lại? Nếu không, môi trường của phiên hiện tại của bạn đã không được cập nhật.


Nếu đó là trường hợp, `which emacs` --versionsẽ đồng ý với emacs --version, bởi vì whichthừa hưởng PATH của nó từ vỏ hiện tại.
mrb

@mrb: Điểm cũng được thực hiện.
JRFerguson
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.