为什么脚本要在变量中定义常用命令?
Why do scripts define common commands in variables?
我在工作地点经常看到这个:
#!/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
?我错过了什么吗?这似乎是不必要的冗余。
欢迎来到没有什么是理所当然的企业。
这些通常被定义为确保正确的版本,或强制跨多个盒子设置环境。
https://github.com/torvalds/linux/blob/master/tools/scripts/Makefile.include#L15
这样你可以检查目录是否存在。
使用完整路径名可确保脚本正确运行,即使它是由自定义 PATH
环境变量的用户 运行 编写的,以便它找到与脚本预期不同的这些命令版本。
使用变量可以简化脚本的编写,因此您不必在每次出现在脚本中时都写下命令的完整路径名。
Is it just my company that does this?
没有
Is there a reason why you would want to spell out where these extremely common commands are?
是的。
Why would I want $CAT
to refer to /usr/bin/cat when cat
already refers to /usr/bin/cat
?
你确定 cat
总是指 /usr/bin/cat
吗?如果您的脚本恰好在路径前面有一个不同的 cat
的环境中是 运行 怎么办?或者在路径的前面只有一个用户控制的目录,用户可以在其中安装流氓 cat
命令?如果您的脚本碰巧 运行 具有更高的权限,那么您真的想让随机用户能够对您的系统做任何他们想做的事情吗?
您确定 cat
应该 总是指代 /usr/bin/cat
吗?如果脚本安装在需要不同 cat
的环境中(例如 /usr/local/bin/gnucat
),那么您更愿意修改一行还是二十行?
Am I missing something? It seems like its needlessly redundant.
是的,你错过了一些东西。
人们希望避免在他们想要 运行 cat
的任何地方写出 /usr/bin/cat
,并且人们希望能够在需要的地方选择不同的 cat
(或者更可能是不同的 make
或 grep
或 sed
)。另一方面,人们希望避免对受信任脚本的行为产生潜在的不安全外部影响。在 shell 变量中定义命令的完整路径,然后将该变量用于 运行 命令以实现这些目标。
避免这种情况并仍然具有忽略用户环境的安全性的一种方法是在脚本中明确说明变量
#!/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
可能还有其他方法:查看您在代码中使用的程序的手册页。
我在工作地点经常看到这个:
#!/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
?我错过了什么吗?这似乎是不必要的冗余。
欢迎来到没有什么是理所当然的企业。
这些通常被定义为确保正确的版本,或强制跨多个盒子设置环境。
https://github.com/torvalds/linux/blob/master/tools/scripts/Makefile.include#L15
这样你可以检查目录是否存在。
使用完整路径名可确保脚本正确运行,即使它是由自定义 PATH
环境变量的用户 运行 编写的,以便它找到与脚本预期不同的这些命令版本。
使用变量可以简化脚本的编写,因此您不必在每次出现在脚本中时都写下命令的完整路径名。
Is it just my company that does this?
没有
Is there a reason why you would want to spell out where these extremely common commands are?
是的。
Why would I want
$CAT
to refer to /usr/bin/cat whencat
already refers to/usr/bin/cat
?
你确定 cat
总是指 /usr/bin/cat
吗?如果您的脚本恰好在路径前面有一个不同的 cat
的环境中是 运行 怎么办?或者在路径的前面只有一个用户控制的目录,用户可以在其中安装流氓 cat
命令?如果您的脚本碰巧 运行 具有更高的权限,那么您真的想让随机用户能够对您的系统做任何他们想做的事情吗?
您确定 cat
应该 总是指代 /usr/bin/cat
吗?如果脚本安装在需要不同 cat
的环境中(例如 /usr/local/bin/gnucat
),那么您更愿意修改一行还是二十行?
Am I missing something? It seems like its needlessly redundant.
是的,你错过了一些东西。
人们希望避免在他们想要 运行 cat
的任何地方写出 /usr/bin/cat
,并且人们希望能够在需要的地方选择不同的 cat
(或者更可能是不同的 make
或 grep
或 sed
)。另一方面,人们希望避免对受信任脚本的行为产生潜在的不安全外部影响。在 shell 变量中定义命令的完整路径,然后将该变量用于 运行 命令以实现这些目标。
避免这种情况并仍然具有忽略用户环境的安全性的一种方法是在脚本中明确说明变量
#!/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
可能还有其他方法:查看您在代码中使用的程序的手册页。