为什么脚本要将常见命令定义为变量?

8

我在工作中经常看到这种情况:

#!/bin/sh

.....

CAT=/usr/bin/cat                                  # An alias for cat
MAIL=/usr/bin/mail                                # An alias for mail
WC=/usr/bin/wc                                    # An alias for word count
GREP=/usr/bin/grep                                # An alias for grep
DIRNAME=/usr/bin/dirname                          # An alias for dirname
RM=/usr/bin/rm                                    # An alias for rm
MV=/usr/bin/mv                                    # An alias for mv

.....

这只是我们公司这样做吗?为什么要详细说明这些非常常用的命令在哪里呢?如果cat已经指向了/usr/bin/cat,为什么我还需要让$CAT也指向/usr/bin/cat?我有什么遗漏的吗?这似乎是毫无必要的冗余。

4个回答

12

使用完整路径名确保脚本的正常运行,即使运行脚本的用户自定义了PATH环境变量,使得它找到的这些命令的版本与脚本期望的不同。

使用变量简化了脚本的编写,这样你就不必每次在脚本中出现一个命令时都要写全路径名。


谢谢!我知道这背后肯定有一些原因。 - R4F6

4

这只是我的公司这样做吗?

不是。

为什么要拼出这些非常常见的命令所在的位置呢?

有原因。

为什么我希望$CAT指向/usr/bin/cat,而cat已经指向/usr/bin/cat了呢?

你确定cat总是指向/usr/bin/cat吗?如果你的脚本在存在不同的cat的环境中运行会怎么样?或者在路径中有一个用户可控制的目录,在其中用户可以安装一个恶意的cat命令。如果你的脚本以提升的权限运行,那么你真的想让随机用户能够对你的系统做任何他们想做的事情吗?

你确定cat应该总是指向/usr/bin/cat吗?如果脚本需要在需要不同的cat的环境中安装(例如/usr/local/bin/gnucat),你更喜欢修改一行还是二十行代码?

我错过了什么吗?这似乎是不必要的冗余。

是的,你错过了一些东西。

人们希望避免在每次运行cat时都写出/usr/bin/cat,并且希望能够在需要时选择不同的cat(或更可能是不同的makegrepsed)。另一方面,人们希望避免对可信脚本行为产生潜在的不安全外部影响。通过定义一个包含命令完整路径的shell变量,然后使用该变量来运行命令可以实现这些目标。


我使用最频繁的事件是通过cron作业运行脚本,其中PATH与我的用户或root不同。硬编码路径可以消除这个问题。John绝对是正确的,你不能指望你假定存在的路径存在,所以编写代码或设置PATH是一个好习惯,但从长远来看,这并不明显。像这样设置路径还可以让您根据环境使用工具的备用路径,例如在BSD或GNU / Linux中。 - Lizardx
1
关于PATH你是正确的,但别名无关紧要。别名不会被继承,在脚本中也不会被扩展,除非脚本明确启用它们。 - Barmar

3

避免这种情况并仍然保证忽略用户环境的安全性的一种方法是在脚本中明确说明变量。

#!/bin/sh

PATH=/bin:/usr/bin   # maybe you need something in /usr/sbin, add that
LC_ALL=C             # ignore the user's locale
LD_LIBRARY_PATH=something # or unset it if you want nothing

# then
cat /a/file          # have confidence you're using /bin/cat

可能还有其他的:请查看你在代码中使用的程序的手册。


1
可能不是一个现实的问题,但自定义路径不能使用例如/usr/bin/cat而不是/bin/cat - chepner

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接