2019年8月16日 星期五

Linux Shell命令搜索路径

1. Linux shell外部命令及搜索路径
如果命令不是shell中内置的——大多数命令都不是内置的,那么shell必须查找出合适的程序来执行。例如,当输入date命令时,shell必须查找date程序,然后运行它。因为,date就是一条外部命令。
shell如何知道在什么地方查找外部命令?shell检查PATH环境变量。与所有的变量一样,PATH包含一串字符,这串字符就是一系列目录名称,我们称之为搜索路径。
我们需要知道程序都存储在文件中,而每个文件都位于目录之中。搜索路径是包含所有外部命令的程序的目录列表。因此,搜索路径中的一个目录中将包含存放date程序的文件。
如果希望查看搜索路径,那么显示PATH变量的值即可:


echo $PATH
下面是一些典型的输出:

/bin: /usr /bin: /usr /ucb: /usr /local /bin: /home /harley /bin
在这个例子中,搜索路径包含下述5个目录:

/bin
/usr /bin
/usr /ucb
/usr /local /bin
/home /harley /bin


您的系统中的搜索路径可能与此例有所不同,但是,在最大程度上,Unix系统对存放外部命令的目录倾向于使用标准的名称。例如,我见过的每个Unix系统都有一个/bin和一个/usr/bin目录,同时许多系统有/usr/ucb目录。
在我们的例子中,前3个目录/bin/usr /bin和/usr /ucb存放系统中所有用户使用的程序。前两个目录位于所有的Unix系统上,并在Unix安装时自动设置/usr /ucb只位于一些系统上。它的任务是存放派生自伯克利Unix的程序。名称ucb是University of California at Berkeley(加利福尼亚大学伯克利分校)的缩写。
接下来的两个目录是定制目录:/usr /local /bin由系统管理员设置,用来存放为本地使用而安装的存储;/home /harley /bin指用户标识harley的home目录中一个名为bin的目录,使用它存放自己的程序。
当shell需要查找外部命令时,它在搜索路径中按指定的顺序逐个检查每个目录。在我们的例子中,shell首先查看/bin目录。如果在这个目录中找不到期望的程序,那么shell将在/usr /bin目录中查找期望的程序。接下来,shell沿着指定的顺序依次查找余下的各个目录。
当shell查找到期望的外部命令时,它就停止搜索并执行程序。如果没有一个目录包含期望的程序,那么shell将放弃搜索并显示一个错误信息。例如,如果输入了命令weddly,那么系统将显示一个类似于下面的信息:

weedly: command not found

2.修改Linux shell 命令搜索路径
在大多数系统上,一般情况下不必自己定义搜索路径,因为系统已经设置好PATH变量。但是,在特定环境中,可能需要修改搜索路径,下面将示范如何修改搜索路径。基本思想就是修改PATH变量的命令放到登录时自动执行的初始化文件中。
首先,我们讨论如何将PATH变量设置成一个特定的值。我们将分贝考虑Bourne shell和C-shell家族的处理情况,因为它们的命令有点不同。
对于Bourn shell家族(Bash、Korn shell)来说,使用export命令设置PATH。使用export命令可以使PATH变量成为环境变量,这意味着shell及所有随后生成的进程都可以使用它。下面是完成该任务的一条典型命令:

export PATH= “/bin: /usr /bin: /usr/ucb: /usr/local/bin”
该命令本身非常直接:将PATH的值设置成一个包含若干目录名称的字符串。可以看出,各个名称之间用冒号隔开,而且等号的两边没有空格。
为了自己设置PATH的值,需要将这条命令(或者类似的命令)放到自己的“登录文件”中,“登录文件”是每次登录时自动执行的初始化文件。如果要修改搜索路径,只需修改登录文件即可。
对于C-shell家族(C-shell、Tcsh)来说,需要使用一个稍微不同的命令,因为设置的是shell变量path,而不是环境变量PATH:

set path=(/bin /usr/bin /usr/ucb /usr/local/bin)
无论何时,当修改path时,shell都会自自动重置PATH。因此,对于PATH变量来说,这条命令和前面的Bourne shell命令都生成相同的设置。
但是,注意语法上的不同。在Bourne shell命令中,我们将环境变量(PATH)的值设置成一个长的字符串。而在C-shell命令中,我们将shell变量(path)的值设置为一列名称。在C-Shell语法中,一列名称包含一个或多个元素,用空格隔开,并且这一列元素用圆括号括起来。
刚才提到设置PATH环境变量的Bourne shell命令应该放在登录文件中。设置path的C-shell命令应该放在“环境文件”中,环境文件是一个不同的初始化文件,在每次新shell启动时都会自动地执行。
在大多数系统上,定义PATH变量的命令早已设置好,因此不必使用刚才讨论的命令。但是,您可能希望修改默认的搜索路径,以适合自己使用。例如,如果您编写自己的shell脚本和程序,并将它们存放在自己的bin目录($HOME/bin)中,那么您将希望把这个目录的每次添加到搜索路径中。
下面是两条展示如何完成这已工作的命令。第一条命令是针对Bourne shell家族的,第二条命令针对C-Shell家族。

export PATH= “$PATH: $HOME/bin”
set path = ($path $HOME/bin)


注意命令的语法。该语法意味着“将搜索路径的值修改为旧值加上$HOME/bin”。换句话说,就是将名称$HOME/bin追加到已有搜索路径的末尾。
另外,您也可能希望在已有的搜索路径的开头插入一个新目录。命令如下:

export PATH= “$HOME/bin: $PATH”
set path = ($HOME/bin$path)


正如这些例子所示,可以基于变量的当前值修改变量的值。这是一个重要的理念,因此不要只是记住这种模式。要在此花一点时间,确保准确理解所有的内容。
现在,既然已经知道了如何将自己的目录添加到搜索路径中,那么这里有一个问题:应该把自己的目录放在列表的开头还是末尾呢?这取决于自己的意愿。
如果将自己的目录放在搜索路径的末尾,那么shell将最后检查该目录。如果将自己的目录放在搜索路径的开头,那么shell第一个检查它。例如,假设您编写了一个叫date的程序,并将它保存在$HOME/bin中。现在您输入:

date

如果将自己的目录放在目录放在搜索路径的开头,shell将运行您自己的date程序,而不是标准的date程序。通过这种方法,可以有效地将任何外部命令替换为自己的程序。另外如果将自己的目录放在搜索路径的末尾,那么shell将运行标准的date程序,而不是您自己编写的。这样可以防止偶然用相同名称的文件替代程序。选择哪一种方式由您自己来决定。
作为一名程序员,可能还希望向搜索路径中添加另外一个目录。如果指定一个点(.)字符,将向搜索路径添加自己的“工作目录”(工作目录就是当前正在工作的目录。)
下面举一个可以帮助你澄清这个概念的例子。下述命令都将$HOME/bin目录和工作目录添加到当前路径的末尾(且采取该顺序)。第一条目录针对Bourne shell家族,第二条命令针对C-shell家族:

export PATH= “$PATH: $HOME/bin: .”
set path = ($path $HOME/bin .)

这样就告诉shell,当查看程序时,最后一个要查看的目录就是当前工作的目录。
对搜索路径的详细讨论已经超出了您掌握的范围。通常,您只需要使用已经默认设置好的搜索路径,在必要时进行微小的修改。
提示:
除非您是一名专家,否则最好谨慎行事,将自己的目录放在搜索路径的末尾。

2.黑客如何使用搜索路径
将工作目录(.)放到搜索路径中比较方便,但是超级用户(root)或者其他拥有特殊权限的的用户标识最好不要这样做。这样可能会导致安全灾难,例如……
您是一名系统管理员,出于方便,您将工作目录放在了root的搜索路径的开头。有一名用户——其实他是一名黑客,请求您帮助,因此您以root登录,切换到该用户的home目录(一种常见的情况)。然后输入ls命令列举用户目录中的内容(也是一种常见的情况)。
您不知道的是这名黑客已经创建了了另一个版本的ls程序,将这一程序放在他的home目录中。这个伪造的ls程序就像真的ls程序一样。但是当root账户运行它时,它会产生一个副作用,即创建一个拥有特殊权限的秘密文件。然后,黑客可以使用这个文件(称之为后门)为他获取超级用户的访问权限。
下面是发生过程,当您切换到用户的home目录时,用户的home目录就成为您的工作目录。当输入ls命令时,shell查看工作目录,发现黑客版本地ls程序并运行它。接下来的事情您已经知道了,黑客接管了系统,您的生活暴露无遗。
实际上,这是以前的黑客惯用的伎俩:寻找一种以root账户运行已经被修改的程序的方法,然后创建一个以后可以使用的后门。这个故事有什么教训呢?那就是,在修改任何用于系统管理的用户标识的搜索路径之前,一定要好好的斟酌一番。
提示:
确保所有系统管理员用户标识(包括root)使用的搜索路径中没有包含工作目录,或者用户可能访问的其他任何目录。

沒有留言:

張貼留言