这个脚本有什么问题?

这个脚本有什么问题?

所以我从这个指南中得到了这个脚本:www.tldp.org/LDP/abs/abs-guide.pdf

LOG_DIR=/var/log
ROOT_UID=0
LINES=50
E_XCD=86
E_NOTROOT=87

if [ "$UID" != "$ROOT_UID" ]
then
echo "Must be root to run this script."
exit $E_NOTROOT
fi

if [ -n "$1" ]
then
lines=$1
else
lines=$LINES
fi

cd $LOG_DIR

if [ 'pwd' != "$LOG_DIR" ]
then
echo "Can't change to $LOG_DIR."
exit $E_XCD
fi

现在我在终端上执行了 sudo su 并回显了 $UID,结果返回了 0。这意味着我的 if 条件结果为假,但在运行此脚本时,我仍然收到“必须是 root 才能运行此脚本。”的提示。

此外,在原始脚本中,如果条件为

if [ "$UID" -ne "$ROOT_UID" ]

但是我收到了非法数字错误,因为显然 -ne 仅用于字符串,所以我将其更改为 !=。

答案1

而不是用

sh script.sh

执行它

bash script.sh

(或添加#!/bin/bash为第一行来设置解释器)。

shUbuntu 中的 shell是不是 bash,但一个单独的 shell 称为dashdash它没有 那么多功能bash,这使得它更高效,但这些缺失的功能有时会破坏 的脚本bash。 其中一个功能是 $UID变量,它是没有定义的dash

这意味着当脚本在 中执行时dash,比较结果将变为["" != "0"],无论哪个用户运行它,结果都将为 true。但是,如果以 root 权限运行它bash,则字符串将相等,并且脚本将正常运行。

答案2

作为麦克洛文说,自动设置的只读UID(和EUID)变量是bash(以及其他一些 shell)。它不是标准的伯恩风格的贝壳并且sh不能假定设置这些变量。特别是,sh在 Ubuntu 中(目前默认)dash,但并未设置它们。

您有两个选择:

  1. bash使您的脚本由而不是运行sh
  2. 更改您的脚本,使其更具可移植性并且不需要bash

使用以下方式运行脚本bash

你还没有告诉我们你的剧本的名字(没关系)。我打算叫它cleanup,因为这是您正在使用的指南中类似脚本的名称。

特别注意,我不是将其命名为类似cleanup.sh。这是因为我不建议您使用后缀来命名它.sh

  • 后缀.sh表明它与兼容sh
  • 大多数脚本根本没有后缀,并且带有.sh.bash后缀甚至可能被解释为暗示您的文件是一个“库”而不是“顶级”脚本。也就是说,它提供的代码可供其他脚本(例如,使用内置脚本)调用,.而不是直接运行。

但是,添加.sh后缀不会对脚本的技术行为产生任何影响。这样做没有技术上的优势或劣势。

添加哈希班线作为脚本的第一行:#!/bin/bash

使脚本可执行和。chmod +x cleanup

现在你可以运行你的脚本通过运行以下命令:

  • ./cleanup,当它位于当前目录中时。(特别是在为教育、探索、测试、娱乐或其他有限或一次性用途编写脚本时,这可能是最常见的方式。)

  • /path/to/cleanup一般来说。如果命令的第一个字包含,/则将其解释为可执行文件的路径。(这就是上述语法的原因./,因为.表示当前目录。)

    经过第一个字我的意思是直到但不包括它的第一个命令未转义空格或制表符:
    foo-bar/baz是 的第一个单词foo-bar/baz qux,而spam\ ham是 的第一个单词,spam\ ham eggs因为之前的空格ham用反斜杠转义。

  • cleanup,如果它位于您的目录中PATH(并且首先列出的目录中没有同名的可执行文件,并且它没有被shell 内置命令功能, 或者别名)。

无论是否是脚本cleanup有一个#!...hashbang 行或者该行的内容:

  • sh cleanup仍将(尝试)以其sh作为解释器来运行它。
  • bash cleanup仍将(尝试)以其bash作为解释器来运行它。

这是因为,在这些情况下,您实际上是在运行解释器(shbash)并将脚本的名称传递给解释器以运行。许多程序接受要在命令行上打开的文件的名称,并且 shell 喜欢shbash遵循此约定。

让你的脚本可移植

如果您想让您的脚本可移植,最简单的方法就是$UID根本不使用,而是使用所有 Bourne 风格 shell 可用的一些功能。

通常,没有内置的 shell 工具来确定用户 ID。但您可以使用id。这是一个外部程序,而不是 shell 内置程序,但像catls,我们有理由期待它会出现。

id本身会输出一堆信息,但id -u只提供有效的用户 ID。

因此if [ "$UID" != "$ROOT_UID" ],您可以使用:

if [ "$(id -u)" != "$ROOT_UID" ]

技术上,这并不等同。$UID给出bash真实用户 ID,并且id -u真正对应于bash$EUID。如果您确实想要 UID 而不是 EUID,请使用id -ru

相关内容