使用 mount 输出作为变量的 Bash 脚本会引发大量错误

使用 mount 输出作为变量的 Bash 脚本会引发大量错误

Ubuntu 18.04 服务器 + LXDE。我无法掌握这个 bash 脚本。
这是我的脚本“开始”(带行号):

#!/bin/bash
reply=sudo mount 192.168.0.2:/home/dk/NFS /home/dk/NFS
if $reply == 0
then 
    echo "NFS mounted OK"
else 
    echo "Mounting NFS failed: $reply"
fi

reply=sudo mount LABEL="60GB" /home/dk/60GB
if $reply == 0
then 
    echo "60GB mounted OK"
else 
    echo "Mounting 60GB failed: $reply"
fi
exit 0

运行结果如下:

$ ./scripts/start
mount: only root can do that
./start: line 3: ==: command not found
Mounting NFS failed: 
mount: only root can do that
./start: line 11: ==: command not found
Mounting 60GB failed: 
$ 
  • 为什么它忽略了sudo之前的mount
  • 为什么它不if被视为一个命令?
  • 为什么它没有打印(非零)值$reply

答案1

嗯,你错误地分配了命令的输出。应该是:

reply=$(sudo mount 192.168.0.2:/home/dk/NFS /home/dk/NFS)

这称为命令替换。有时,您会在旧的 Bourne shell 语法中看到使用反引号代替 的情况$(...),但现在不建议这样做,因为反引号不能轻易嵌套,而您可以嵌套$( cmd1 $(cmd2))

为什么它不认为“如果”是一个命令?

如果语句对命令进行操作,但您给出的是变量$reply,它只是暂时存在的(请参阅后面的答案),因此它只存在于mount命令的环境中,但运行脚本的 shell 对此一无所知 - 它不存在。要比较字符串[,请使用,是的,它是一个命令,也称为test。所以这样做

if test "$reply" == 0

看到引号了吗?这很重要,否则如果有空格,shell 会将变量扩展为两个或多个单独的实体,而不是一个。

但是如果你想检查命令的退出状态,只需这样做

if mount 192.168.0.2:/home/dk/NFS /home/dk/NFS

没看到sudo?这是因为在脚本中多次使用 sudo 通常是多余的。只需使用 sudo 调用脚本本身,所有命令都将具有 root 权限。

我还想说 echo 是多余的,因为 mount 命令已经可以将错误打印到终端,但如果你想要自定义消息,你可以这样做

if mount 192.168.0.2:/home/dk/NFS /home/dk/NFS 1> /dev/null
then
       echo "Success"
else
       echo "Fail"
fi

因为1>正常输出被抑制(实际上是专门为此目的重定向/dev/null)但如果出现任何问题就会显示错误。

为什么它忽略了“mount”之前的“sudo”?

至于为什么你会收到错误消息,那是因为表单

reply=sudo mount 192.168.0.2:/home/dk/NFS /home/dk/NFS

被视为envvariable=value command arg1 arg2,即您将带有result值的变量sudo放入命令环境中mount。命令会知道这一点,但在命令退出后 - 变量也会消失。

为什么它没有打印 $reply 的(非零)值?

因为reply如前所述,它不存储退出状态。实际上 shell 已经提供了一个变量,$?因此使用它作为

if [ $? -eq 0 ] 

冲洗并重复对脚本中其他语句的建议。

祝你好运

答案2

除了 Sergiy 的好答案之外,您还可以考虑使用 AND 和 OR 列表来快速检查命令是否返回退出状态零(成功),例如

command && echo "command succeeded" || echo "command failed"

以下为摘录man bash

AND 和 OR 列表是一个或多个管道的序列,分别由&&||控制运算符分隔。AND 和 OR 列表以左结合性执行。AND 列表的形式为

      command1 && command2

当且仅当 command1 返回退出状态零时,才会执行 command2。

OR 列表的形式为

      command1 || command2

当且仅当 command1 返回非零退出状态时,才会执行 command2。AND 和 OR 列表的返回状态是列表中执行的最后一个命令的退出状态。

您可以将它们组合起来,并且如果需要还可以查看退出状态,例如:

sudo mount 192.168.0.2:/home/dk/NFS /home/dk/NFS && \
echo "NFS mounted OK" || echo "Mounting NFS failed: $?"

答案3

您的脚本存在问题:

  • 您错过了`命令sudo mount ..。要执行命令,您需要将其放回引号`command`或。您也$(command)可以使用捕获脚本的返回值。$?
  • 如果循环构造错误

    if [ $var -eq/-lt/-gt "string"/number ]
    then
    echo "...."
    else
    echo "..."
    fi; <=== Most users miss this.
    

** 编辑脚本**

#!/bin/bash

reply=`sudo mount 192.168.0.2:/home/dk/NFS /home/dk/NFS`

if [ $reply -eq "0" ]
then 
echo "NFS mounted OK"
else 
echo "Mounting NFS failed: $reply"
fi;

reply=`sudo mount LABEL="60GB" /home/dk/60GB`
if[ $reply -eq "0" ]
then 
    echo "60GB mounted OK"
else 
    echo "Mounting 60GB failed: $reply"
fi;
exit 0

相关内容