业务系统一般单独挂一块数据盘存数据。拿到新盘后要格式化、分区、挂载、写 fstab,一两台机器手工做还行,节点一多就该交给脚本。下面这份脚本面向 CentOS,用 expect 做到全程免交互。
脚本的执行逻辑
流程分四段:先检查 expect 是否已装,没装就 yum 装上,并对 /etc/fstab 执行 chattr -i 解锁;然后用 lsblk 找尚未分区挂载的新盘(按 /sd 前缀匹配,awk 统计只出现一次的盘名);接着用 expect -c 驱动 fdisk,依次应答新建主分区、默认分区号、默认起始扇区、整个磁盘、wq 写入;最后 mkfs.xfs 格式化分区、写入 fstab、挂载到 /data,并重新 chattr +i 锁住 fstab。分区和格式化的交互提示词依赖系统语言,所以脚本按 LANG 分了 zh_CN 和 en_US 两个分支。
完整脚本
#!/usr/bin/env bash
#===============================================================================
#
# FILE: Disk_Initialize.sh
#
# USAGE: ./Disk_Initialize.sh
#
# DESCRIPTION: Linux CentOS Disk免交互格式化分区、挂载
#
# ORGANIZATION: DingQz dqzboy.com
# CREATED: 2021
#===============================================================================
# 安装软件
EXPECT=`yum list installed | grep -w expect`
if [ $? -eq 0 ];then
echo
echo
echo "--------------------------------------------------------------------------"
echo " Yum Install expect Skip..."
echo "--------------------------------------------------------------------------"
echo
echo
else
yum -y install expect
echo
echo
echo "--------------------------------------------------------------------------"
echo " Yum Install expect Done..."
echo "--------------------------------------------------------------------------"
echo
echo
fi
# 解锁文件
chattr -i /etc/fstab
OS_CN() {
# 注意修改磁盘名称前缀,例如这里的 /sd
Dsk=`lsblk -r --output NAME,MOUNTPOINT | awk -F / '/sd/ { dsk=substr($1,1,3);dsks[dsk]+=1 } END { for ( i in dsks ) { if (dsks[i]==1) print i } }'`
Disk="/dev/${Dsk}"
DiskP="${Disk}1"
if [ ! -z "${Dsk}" ];then
expect -c "
spawn fdisk ${Disk}
expect {
-re "(.*)三思(.*)(n*)(.*)获取帮助(.*)" { send "nr";exp_continue }
"default p" { send "r";exp_continue }
"分区号" { send "r";exp_continue }
"起始 扇区" { send "r";exp_continue }
"Last 扇区" { send "r";exp_continue }
"命令" { send "wqr";exp_continue }
}
"
else
echo
echo
echo "--------------------------------------------------------------------------"
echo " The new disk was not found. Exit..."
echo "--------------------------------------------------------------------------"
echo
exit 1
fi
}
OS_EN() {
Dsk=`lsblk -r --output NAME,MOUNTPOINT | awk -F / '/sd/ { dsk=substr($1,1,3);dsks[dsk]+=1 } END { for ( i in dsks ) { if (dsks[i]==1) print i } }'`
Disk="/dev/${Dsk}"
DiskP="${Disk}1"
if [ ! -z "${Dsk}" ];then
expect -c "
spawn fdisk ${Disk}
expect {
-re "(.*)careful(.*)(n*)(.*)help(.*)" { send "nr";exp_continue }
"default p" { send "r";exp_continue }
"Partition number" { send "r";exp_continue }
"First sector" { send "r";exp_continue }
"Last sector" {send "r";exp_continue }
"Command" { send "wqr";exp_continue }
}
"
else
echo
echo
echo "--------------------------------------------------------------------------"
echo " The new disk was not found. Exit..."
echo "--------------------------------------------------------------------------"
echo
exit 1
fi
}
Mkfs_Disk() {
sleep 3
# 格式化分区
Partitions=`blkid | awk -F ":" '{print $1}'| grep "${DiskP}"`
if [ $? -eq 0 ];then
echo
echo
echo "--------------------------------------------------------------------------"
echo " Formatted Done"
echo "--------------------------------------------------------------------------"
echo
echo
else
mkfs.xfs -f -n ftype=1 ${DiskP}
fi
if ! grep "${DiskP}" /etc/fstab; then
cat >> /etc/fstab <<EOF
${DiskP} /data xfs defaults 1 0
EOF
echo "--------------------------------------------------------------------------"
fi
# 创建挂载目录
mkdir -p /data
mount ${DiskP} /data
# 非ROOT用户不允许编辑以下文件
chattr +i /etc/fstab
}
# 判断系统语言
OS_LANG=`echo $LANG | awk -F "." '{print $1}'`
if [ "${OS_LANG}" == "en_US" ];then
OS_EN
Mkfs_Disk
elif [ "${OS_LANG}" == "zh_CN" ];then
OS_CN
Mkfs_Disk
else
echo "Sorry script does not support this system."
fi
expect 用到的几个指令
expect -c:在命令行上直接跟要执行的 expect 命令,命令要用引号包住,防止被 shell 拆散;spawn:启动一个进入交互模式的程序,后面跟要驱动的命令;expect:等待匹配输出,匹配成功就执行后面的动作;send:发送指定字符串,r相当于回车;exp_continue:匹配成功后继续下一轮匹配,用来串起整个交互过程。
使用前确认几件事
脚本只挑选没有分区、没有挂载点的 sd 前缀磁盘,识别到多块新盘时只取一块;挂载点写死在 /data,改路径要同时动 fstab 追加和 mount 两处;磁盘前缀 /sd 之外(如 vdb、nvme)需要改匹配式;fstab 被加过 +i 之后,后续手工编辑要先 chattr -i,否则改不动。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


















暂无评论内容