shell脚本中获取返回值异常

写一个简单的自动格式化数据盘sdb并自动挂载到/data的脚本。
脚本中获取分区是否存在的时候,shell脚本有时能成功,有时候失败。搞不懂是怎么回事。脚本如下:

#!/usr/bin/env bash

#格式化并挂载数据盘到/data目录
#disk_name只能写如:sdb,sdc,vdb,vdc,即不能带路径斜线
disk_name="sdb"
#定义磁盘要挂在到哪个目录,必须写完整路径
disk_mount_directory="/data"

#1、判断数据目录是否存在
#source /etc/profile
source /root/.bash_profile
if [ ! -d "${disk_mount_directory}" ]; then
    mkdir -p "${disk_mount_directory}"
    echo "info: 目录已创建 ${disk_mount_directory}"
else
    echo "info: 目录已存在 ${disk_mount_directory}"
fi
#判断/data里是否有文件或目录,如果有就退出报错
disk_mount_directory_length=`ls -l ${disk_mount_directory} |head -n 1 |awk '{print $2}'`
if [ ${disk_mount_directory_length} -ne 0 ];then
    echo -e "\e[1;31mERROR... : disk_mount_directory ${disk_mount_directory}  under have file \e[0m"
    exit 1
else
    echo "info: success, ${disk_mount_directory} is clean"
fi


#2、判断sdb是否存在,并分区磁盘
/usr/bin/lsblk | grep ${disk_name} > /dev/null 2>&1
if [ $? -eq 0 ]; then
    /usr/sbin/parted -s -a optimal /dev/${disk_name} mklabel gpt -- mkpart primary xfs 1 -1
    echo "info: disk ${disk_name} is exist."
else
    echo "error: Data disk ${disk_name} is not exist ..."
    exit 1
fi


echo "----------1"
#3、判断分区是否成功
echo "----------${disk_name}1"
/usr/bin/lsblk | grep "${disk_name}1"
if [ $? -gt 0 ]; then
    echo "error: 分区不存在,请检查分区是否成功..."
    echo "    info-error: `lsblk | grep ${disk_name}1`"
    exit 1
else
    echo "    info-success: `lsblk | grep ${disk_name}1`"
fi
echo "----------1"

诡异的是脚本的在【/usr/bin/lsblk | grep “${disk_name}1”】执行后,获取它的返回值($?),有时是0,有时候竟然是非0。不知道是我写的哪里有问题?还是系统bug?

有大神帮忙看看啥原因吗?

执行这一段后有返回截取的结果吗,若有结果 $? 就是 0

[root@euler122 scripts]# sh mountsdb.sh 
info: 目录已存在 /data
info: success, /data is clean
info: disk sdb is exist.
----------1
----------sdb1
└─sdb1               8:17   0    2G  0 part 
    info-success: └─sdb1               8:17   0    2G  0 part 
----------1
[root@euler122 scripts]# sh mountsdb.sh 
info: 目录已存在 /data
info: success, /data is clean
info: disk sdb is exist.
----------1
----------sdb1
error: 分区不存在,请检查分区是否成功...
    info-error: └─sdb1               8:17   0    2G  0 part 
[root@euler122 scripts]# 
[root@euler122 scripts]# sh mountsdb.sh 
info: 目录已存在 /data
info: success, /data is clean
info: disk sdb is exist.
----------1
----------sdb1
└─sdb1               8:17   0    2G  0 part 
    info-success: └─sdb1               8:17   0    2G  0 part 
----------1

上面就是运行的结果,一会是0,一会非0。



最后一张图返回值变成 1 是正确的,因为 grep 没有截取到任何东西,要看一下为啥 grep 为啥没有截取到 sdb1,手动执行 lsblk 看一下此时的 sdb1 存在不存在

#!/usr/bin/env bash

#格式化并挂载数据盘到/data目录
#disk_name只能写如:sdb,sdc,vdb,vdc,即不能带路径斜线
disk_name="sdb"
#定义磁盘要挂在到哪个目录,必须写完整路径
disk_mount_directory="/data"

for((i=0;i<=100;i++))
do
    echo "----------$i"
    #3、判断分区是否成功
    /usr/bin/lsblk | grep ${disk_name}1 > /dev/null 2>&1
    echo $?
    echo "----------$i"
done

测试了,单独执行这条命令没问题,lsblk |grep sdb1全部能抓得到,且返回值为0.正常。
不管是手工执行,还是这样批量执行都正常。就是按照最初的楼顶的那一堆脚本就偶尔会返回1。

我的意思是当出现返回值是 1 的时候,再手动执行 lsblk 看看

脚本里其实有你说的实现方式。

/usr/bin/lsblk | grep "${disk_name}1"
if [ $? -gt 0 ]; then
    echo "error: 分区不存在,请检查分区是否成功..."
    echo "    info-error: `lsblk | grep ${disk_name}1`"        <---------------这就是
    exit 1
else
    echo "    info-success: `lsblk | grep ${disk_name}1`"
fi

没用。手工执行lsblk |grep sdb1永远能得到正确结果。

可能是更新分区表需要一定时间,可以尝试在分区后做一下sleep等待几秒,再做分区结果验证

1 Like

正如你所说,我在这一行后面加了个sleep 3,就没有再出现问题了。
谢谢大佬帮忙解答疑惑 :hugs:

/usr/sbin/parted -s -a optimal /dev/${disk_name} mklabel gpt -- mkpart primary xfs 1 -1
sleep 3         <------更加这里