我的shell脚本有些出乎意料

时间:2018-01-12 05:23:31

标签: shell

此脚本用于检测USB驱动器输入,将任何一些日志文件复制到USB。 在第47行, cp "/home/root/io/log/${end}.txt" "${USB}/log" && let sfile++ || let err3=1  无论cp命令是否成功,都会执行三个命令。如果我用49行交换这一行  cp "/home/root/io/log/${begin}.txt" "${USB}/log" && let sfile++ || let err3=1 ,只有代码的上面一行没有按预期工作。

echo $USB > /dev/null
echo $FILE > /dev/null
echo $begin > /dev/null
echo $end > /dev/null
echo $destfile > /dev/null
echo $tmp > /dev/null
echo $err > /dev/null
echo $sfile > /dev/null
echo $DATE > /dev/null

echo 84 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio84/direction


while true
do
    USB=""
    FILE=""
    begin=""
    end=""
    destfile=""
    DATE=""
    let err1=0
    let err2=0
    let err3=0
    let err4=0
    let err=0
    let sfile=0
    ls /dev/sda1 > /dev/null 2>&1 || rm -rf /media/sda1
    ls /media/sda1 > /dev/null 2>&1 && USB="/media/sda1"
    if [[ "$USB" != "" ]]; then
        ls $USB | grep 'cp.txt' > /dev/null && FILE="cp.txt"
        if [[ "$FILE" != "" ]]; then

            ls "${USB}/log" > /dev/null 2>&1 && rm -rf "${USB}/log"
            mkdir "${USB}/log" && echo 0 >> /dev/null || let err1=1

            begin=$(cat "${USB}/${FILE}" | cut -d 'd' -f 2)
            end=$(cat "${USB}/${FILE}" | cut -d 'd' -f 3)

            cp "/home/root/io/log/${end}.txt" "${USB}/log" && let sfile++ || let err3=1

            cp "/home/root/io/log/${begin}.txt" "${USB}/log" && let sfile++ || let err2=1

            destfile=$(ls /home/root/io/log)
            destfile=${destfile#*${begin}.txt}
            destfile=${destfile%${end}.txt*}
            echo $destfile

            while [[ "$(echo $destfile | cut -d ' ' -f 1)" != "" ]]; do
                tmp=""
                tmp=$(echo $destfile | cut -d ' ' -f 1)
                destfile=${destfile#*$tmp}
                cp "/home/root/io/log/${tmp}" "${USB}/log" && let sfile++ || let err4=1
            done
            DATE=$(date +%Y%m%d-%H%M%S)
            LOG="${DATE} Requested: from-${begin} to-${end}. Succeed:${sfile} err1:${err1}err2:${err2}err3:${err3}err4:${err4}"
            echo $LOG >> /home/root/io/cplog/cplog.txt
            echo $LOG >> /media/sda1/cplog.txt
            if [[ err -eq 0 ]]; then
                echo 1 > /sys/class/gpio/gpio84/value
                sleep 1
                echo 0 > /sys/class/gpio/gpio84/value
            else
                for (( i = 0; i < 10; i++ )); do
                    echo 1 > /sys/class/gpio/gpio84/value
                    sleep 0.05
                    echo 0 > /sys/class/gpio/gpio84/value
                    sleep 0.05
                done
            fi
            umount "${USB}"
        fi
    fi
    sleep 2
done

1 个答案:

答案 0 :(得分:0)

我猜您使用的是bash,但除非您坚持POSIX兼容性,否则请始终指明您正在使用的shell。假设bash,如果你有一个命令序列X && Y || Z,并且如果X返回非零退出状态,则Y不会被执行。

除此之外,您的脚本中确实存在逻辑缺陷。请注意,let也会设置退出状态。如果要计算的表达式的值为0,则退出状态为1,否则退出状态为0。现在关于let sfile++,表达式的值是sfile在递增之前的值。

在循环的第一次迭代中,sfile为零。假设cp返回退出代码0,sfile将递增,let命令返回退出代码 1 let err4=1也将执行。

在随后的迭代中,这不再发生,因为let sfile++返回退出代码 0

我的建议是不要过于喜欢命令序列混合&amp;&amp;和||。在这种情况下,简单的if将是更好的选择:

if cp ...
then
  let ...
else
  let
fi