美文网首页
在Ubuntu /etc/rc.local中处理非零返回值

在Ubuntu /etc/rc.local中处理非零返回值

作者: 我要牛肉面面 | 来源:发表于2019-08-04 10:30 被阅读0次

    1 需求

    /etc/rc.local中编写并执行函数,使其实现下列功能:

    1. 每次开机时,如果检测到Transmission要使用的指定硬盘分区,则将其挂载到指定目录,否则无操作。
      这一点有点像Windows分配盘符的机制,操作系统事先不会通过/etc/fstab强制要求某个分区必须存在,对移动硬盘、热插拔硬盘位、NAS、SAN等使用模式更加友好。
    2. 如果上一步检测到分区并挂载成功,则sleep一段时间后启动Transmission。
    3. 如果检测到分区但挂载失败,则记录mount命令的返回值并输出。

    2 尝试实现

    实现前两项功能的函数代码很简单,没什么坑,如下所示:

    selective_start_transmission(){
        if [ -b "$TRANSMISSION_SCRATCH_DRIVE_LINK" -a -d "$TRANSMISSION_SCRATCH_DRIVE_MOUNTPOINT" ]; then
            mount "$TRANSMISSION_SCRATCH_DRIVE_LINK" "$TRANSMISSION_SCRATCH_DRIVE_MOUNTPOINT"
            ERRLVL=$?
            if [ "x0" = "x"${ERRLVL} ]; then
                echo "mount: success"
                sleep 5
                if [ -d "$TRANSMISSION_SCRATCH_DIR" ]; then
                    systemctl start transmission-daemon
                fi
            else
                echo "mount: error level $ERRLVL"
            fi
        fi
    }
    

    然而在处理mount命令的返回值(代码中将其保存到$ERRLVL)时遇到了坑。mount命令返回非零值时,脚本直接退出,第二个if代码块以及后面的脚本都执行不到。

    [root@localhost ~]# /etc/rc.local selective_start_transmission
    mount: /dev/sdj1 is already mounted or /mnt/WD30EZRX-00 busy
           /dev/sdj1 is already mounted on /mnt/WD30EZRX-00
    [root@localhost ~]# echo $?
    32
    

    (函数中的两个echo都没有执行)

    3 解决方法

    如果只是想处理错误的话,把mount写到第二个if [ ]里面就可以,但是这样就拿不到返回值了。
    先后查了Bash中try-catch的实现括号的用法$-的含义set命令等资料,没有任何头绪。

    于是用了一个比较丑陋的方法解决,也就是mount后面直接跟着ERRLVL=$?,而且无论成功失败都会执行。

        if [ -b "$TRANSMISSION_SCRATCH_DRIVE_LINK" -a -d "$TRANSMISSION_SCRATCH_DRIVE_MOUNTPOINT" ]; then
            ERRLVL='"unset"'
            mount "$TRANSMISSION_SCRATCH_DRIVE_LINK" "$TRANSMISSION_SCRATCH_DRIVE_MOUNTPOINT" && ERRLVL=$? || ERRLVL=$?
            if [ "x0" = "x"${ERRLVL} ]; then
                ......
    

    4 兔子洞大冒险

    随后我在这里看到了
    #!/bin/bash -x
    这种写法,于是看了一眼/etc/rc.local的第一行:

    #!/bin/sh -e
    

    我想知道这里的-e是什么意思,于是随手man sh了一下,然后才注意到这里的sh默认是dash,不过也可以在bash和dash间切换
    -edash中的含义是:

       Argument List Processing
         All of the single letter options that have a corresponding name can be
         used as an argument to the -o option.  The set -o name is provided next
         to the single letter option in the description below.  Specifying a dash
         “-” turns the option on, while using a plus “+” disables the option.  The
         following options can be set from the command line or with the set
         builtin (described later).
         ...
               -e errexit       If not interactive, exit immediately if any
                                untested command fails.  The exit status of a com‐
                                mand is considered to be explicitly tested if the
                                command is used to control an if, elif, while, or
                                until; or if the command is the left hand operand
                                of an “&&” or “||” operator.
    

    也就是说要try的命令必须立即test,或者放到&&或者||操作符的左侧,否则一旦命令失败,dash会立即终止脚本的运行。这一点和set -e的含义相似,但不完全相同。
    -edash中的执行效果如下:

    [root@localhost ~]# echo $$
    8269
    [root@localhost ~]# dash -e
    # echo $$
    11142
    # false
    [root@localhost ~]# echo $$
    8269
    

    -ebash中的执行效果是一样的:

    [root@localhost ~]# echo $$
    8269
    [root@localhost ~]# bash -e
    [root@localhost ~]# echo $$
    11157
    [root@localhost ~]# false
    [root@localhost ~]# echo $$
    8269
    

    相关文章

      网友评论

          本文标题:在Ubuntu /etc/rc.local中处理非零返回值

          本文链接:https://www.haomeiwen.com/subject/ueyedctx.html