Linux 命令程序 查找顺序

发布时间 2023-11-03 00:55:53作者: fangpinz

我们使用echo $PATH查看如下:这是当前shell的PATH环境变量,

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/bin/chromedriver

我们使用env |grep PATH也能查看当前shell的PATH环境变量,

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/bin/chromedriver

我们知道在linux里面,一切皆文件,上面的PATH中显示的要么是目录(目录也是文件),要么是链接(连接也是文件),如下:

ls -al /usr/local/ |grep sbin

drwxr-xr-x  2 root root 4096  4月 20  2021 sbin

/usr/local/bin/ |grep chromedriver

lrwxrwxrwx  1 root root   29  1月 29  2022 chromedriver -> /usr/local/share/chromedriver

 

在当前shell里面执行python3,  当前shell会在当前shell的PATH中按照从左往右的顺序在目录中查找python3, 找了之后创建一个进程 运行python3的程序代码.

你可以创建一个文件 tt.py, 内容如下:

#!/usr/bin/python3 -u

import sys

import time

args = sys.argv

 

while True:

    print(f"test transfer parameters: {args}")

time.sleep(2)

然后将tt.py文件通过sudo cp tt.py /usr/bin/tt.py命令,将其放到当前shell的PATH环境变量目录/usr/bin 下, 然后在shell中执行tt.py

 

calix@calix-Precision-5820-Tower:~/fzhu$ tt.py

test transfer parameters: ['/usr/bin/tt.py']

test transfer parameters: ['/usr/bin/tt.py']

^Z

[1]+  Stopped                 tt.py

calix@calix-Precision-5820-Tower:~/fzhu$ ps -ef |grep tt.py

calix      72479   72188  0 23:15 pts/2    00:00:00 /usr/bin/python3 -u /usr/bin/tt.py

calix      72481   72188  0 23:15 pts/2    00:00:00 grep --color=auto tt.py

calix@calix-Precision-5820-Tower:~/fzhu$

如果你复制一份tt.py的代码,然后将代码中的test transfer parameters修改为TEST TRANSFER PARAMETERS,

#!/usr/bin/python3 -u

import sys

import time

args = sys.argv

 

while True:

    print(f"TEST TRANSFER PARAMETERS: {args}")

time.sleep(2)

 

然后将其拷贝一份放到/usr/sbin目录下( cp tt.py /usr/sbin/tt.py)

 

此时,在shell中执行tt.py, 会运行/usr/bin/ 下还是/usr/sbin下的tt.py文件呢?

因为在PATH环境变量中,/usr/sbin目录比/usr/bin目录要靠近左边, 所有优先在/usr/sbin目录中找tt.py

在shell中执行tt.py如下:

calix@calix-Precision-5820-Tower:~/fzhu$ tt.py

test transfer parameters: ['/usr/bin/tt.py']

test transfer parameters: ['/usr/bin/tt.py']

^CTraceback (most recent call last):

  File "/usr/bin/tt.py", line 8, in <module>

    time.sleep(2)

KeyboardInterrupt

为什么还是小写的test transfer parameters呢????

此时通过 whereis tt.py 和which tt.py来查看一下:

calix@calix-Precision-5820-Tower:~/fzhu$ whereis tt.py

tt: /usr/bin/tt.py /usr/sbin/tt.py

calix@calix-Precision-5820-Tower:~/fzhu$ which tt.py

/usr/sbin/tt.py

calix@calix-Precision-5820-Tower:~/fzhu$

没有问题啊, 为什么会这样呢? 是不是哪里设置了以/usr/bin为最优先查找tt.py的路径了呢?

如果是这样我们将/usr/bin下的tt.py删除了, 这样在/usr/bin 下找不到tt.py,就会去/usr/sbin下查找tt.py了吧.

赶紧将/usr/bin下的tt.py删掉, 删掉之后再看一下:

calix@calix-Precision-5820-Tower:~/fzhu$ whereis tt.py

tt: /usr/sbin/tt.py

calix@calix-Precision-5820-Tower:~/fzhu$ which tt.py

/usr/sbin/tt.py

calix@calix-Precision-5820-Tower:~/fzhu$

现在在shell里运行tt.py 

calix@calix-Precision-5820-Tower:~/fzhu$ tt.py

-bash: /usr/bin/tt.py: No such file or directory

calix@calix-Precision-5820-Tower:~/fzhu$

为什么提示在/usr/bin 下找不到tt.py,  为什么还会在/usr/bin下找tt.py呢?

此时, 应该有什么想法, 明明tt.py 在/usr/bin 下被删除了, 不可能在/usr/bin下找到啊, PATH路径中这么多目录可以找,为什么一定要在/usr/bin这一个目录下找呢? 在/usr/bin目录下找不到,可以去其他目录中找啊, 此时就想到了bash查找应该有缓存机制, 在网上搜一下还真有.可以通过在当前shell中执行hash命令,查看到当前shell在其hash表里记住了哪些命令:

calix@calix-Precision-5820-Tower:~/fzhu$ hash

hits    command

   3    /usr/bin/mv

   4    /usr/bin/python3

   8    /usr/bin/which

   1    /usr/bin/cp

  12    /usr/bin/ls

   3    /usr/bin/tt.py

   5    /usr/bin/cat

   3    /usr/bin/mkdir

   9    /usr/bin/whereis

   4    /usr/bin/sudo

calix@calix-Precision-5820-Tower:~/fzhu$

calix@calix-Precision-5820-Tower:~/fzhu$ hash --help

hash: hash [-lr] [-p pathname] [-dt] [name ...]

    Remember or display program locations.

   

    Determine and remember the full pathname of each command NAME.  If

    no arguments are given, information about remembered commands is displayed.

   

    Options:

      -d        forget the remembered location of each NAME

      -l        display in a format that may be reused as input

      -p pathname       use PATHNAME as the full pathname of NAME

      -r        forget all remembered locations

      -t        print the remembered location of each NAME, preceding

                each location with the corresponding NAME if multiple

                NAMEs are given

    Arguments:

      NAME      Each NAME is searched for in $PATH and added to the list

                of remembered commands.

   

    Exit Status:

    Returns success unless NAME is not found or an invalid option is given.

calix@calix-Precision-5820-Tower:~/fzhu$

 

calix@calix-Precision-5820-Tower:~/fzhu$ hash -d tt.py

calix@calix-Precision-5820-Tower:~/fzhu$ hash

hits    command

   3    /usr/bin/mv

   4    /usr/bin/python3

   8    /usr/bin/which

   1    /usr/bin/cp

  12    /usr/bin/ls

   5    /usr/bin/cat

   3    /usr/bin/mkdir

   9    /usr/bin/whereis

   4    /usr/bin/sudo

calix@calix-Precision-5820-Tower:~/fzhu$

 

用hash -d tt.py 清除了当前shell的命令缓存hash表中的/usr/bin/tt.py 命令之后,继续执行tt.py如下:

calix@calix-Precision-5820-Tower:~/fzhu$ tt.py

TEST TRANSFER PARAMETERS: ['/usr/sbin/tt.py']

TEST TRANSFER PARAMETERS: ['/usr/sbin/tt.py']

^CTraceback (most recent call last):

  File "/usr/sbin/tt.py", line 8, in <module>

    time.sleep(2)

KeyboardInterrupt

 

calix@calix-Precision-5820-Tower:~/fzhu$

 

至此 shell的命令查找顺序我们总结为:

优先从shell的命令缓存hash表中查找, 找到之后按照绝对路径执行, 如果没有对应的命令,就去PATH目录中去找, 如果找到按照绝对路径执行,如果都没有找到则报错.  Whereis 和which命令帮助确认文件在当前文件系统中的位置.