之前有个客户需要我们提供一个可以在系统下展示硬盘盘符对应实际服务器上物理槽位的脚本,一开始没有什么思路,后面摸索了下对于板载直连的服务器,pci下设备是固定的,那么机器正常启动过程中,对应的槽位和盘符也是固定的,不过这类需求只能适用于硬盘板载直连的机器了,如果是在raid卡下的硬盘,这个规律可能就不统一了。所以根据这个规律实现了脚本,一开始是想着槽位图上哪个位置有盘就显示出来,没有就显示X,实现效果如下图。后面客户表示不需要这样对应,只要能打印出来盘符和槽位的对应关系,槽位图显示完整的0-11就行,就重新改简单了
实现代码如下,实现了amd和intel机型的12LFF机器直通硬盘的槽位显示
#!/bin/bash
function CheckPlatform(){
if [[ `dmidecode | grep -i AMD` != "" ]];then
echo -e "This is an AMD server\n"
Platform="AMD"
elif [[ `dmidecode | grep -i intel` != "" ]];then
echo -e "This is an Intel server\n"
Platform="INTEL"
else
echo "This is not an AMD nor an Intel server\n"
fi
}
function CheckPresence()
{
if [[ `cat AHCIDisklist.log |awk '{print $2}'|grep ^$1$` != "" ]];then
if [ $1 == 9 ]; then
echo -e "$1 |"
elif [ $1 == 10 ] || [ $1 == 11 ];then
echo -e "$1 |"
elif [ $1 == 1 ] || [ $1 == 2 ];then
echo -e "| $1 \c"
else
echo -e "$1 \c"
fi
else
if [ $1 == 9 ] || [ $1 == 10 ] || [ $1 == 11 ];then
echo -e "X |"
elif [ $1 == 1 ] || [ $1 == 2 ];then
echo -e "| X \c"
else
echo -e "X \c"
fi
fi
}
function GetINTELSlot() {
for i in `grep -l Gbps /sys/class/ata_link/*/sata_spd`; do #循环,打印当前所有盘的link信息,该信息与slot位置有关
#截取link信息中盘的link num,当前intel平台是3-14(12个SATA盘),每个位置对应固定的link num;
linkLine=`basename ${i%/*} | sed 's/^....//' $1 `
#每个盘的host num是在link num数字上减一,即intel平台的host num是2-13;
hostNum=$[$linkLine-1]
if [ $hostNum -lt 6 ];then #如果host num小于6,是sSATA控制器(因为配置是4个sSATA+8个SATA盘,且顺序是从sSATA开始排序,因此sSATA的host num是2、3、4、5;SATA的是6-13)
slotNum=$[$linkLine -3] #slot号是从0开始排序的,所以0-3是sSATA,根据link num算就是3-6,因此需要减3
sdx=`ls -l /sys/class/block | grep -i host$hostNum/ |awk -F '/' '{print $NF}'|grep -Eo 'sd[a-z]'|uniq` #抓取该host num对应的盘符
model=`smartctl -i /dev/$sdx|grep "Device Model:"|awk -F: '{print $2}'|sed 's/ //g'`
# cat "${i%/*}"/device/dev*/ata_device/dev*/id | perl -nE 's/([0-9a-f]{2})/print chr hex $1/gie' | echo `strings` | awk '{print $1}' | xargs printf "%-5s | %-4s%-2s | %-11s:%-3s | %-14s:%-20s\n" sSATA slot "$slotNum" Disk_Volume "$sdx" Disk_SerialNum `strings` >> tmp_log.tmp 2>&1
SN=$(cat "${i%/*}"/device/dev*/ata_device/dev*/id | perl -nE 's/([0-9a-f]{2})/print chr hex $1/gie' | echo `strings` | awk '{print $1}')
# printf "%-15s %-10s %-10s %-s\n" sSATA $slotNum $sdx $SN >> tmp_log.tmp 2>&1
printf "%-15s %-10s %-10s %-20s %-s\n" sSATA $slotNum $sdx $SN $model >> tmp_log.tmp 2>&1
#抓取该link num对应的盘序列号,并依次打印控制器类型、slot号、盘序列号和盘符
elif [ $hostNum -ge 6 ];then #host num大于等于6的是SATA控制器
slotNum=$[$linkLine -3] #slot号是从4开始排序的,所以4-11是SATA,根据link num算就是7-14,因此也需要减3
sdx=`ls -l /sys/class/block | grep -i host$hostNum/ |awk -F '/' '{print $NF}'|grep -Eo 'sd[a-z]'|uniq` #抓取该host num对应的盘符
model=`smartctl -i /dev/$sdx|grep "Device Model:"|awk -F: '{print $2}'|sed 's/ //g'`
SN=$(cat "${i%/*}"/device/dev*/ata_device/dev*/id | perl -nE 's/([0-9a-f]{2})/print chr hex $1/gie' | echo `strings` | awk '{print $1}')
printf "%-15s %-10s %-10s %-20s %-s\n" SATA $slotNum $sdx $SN $model>> tmp_log.tmp 2>&1
#抓取该link num对应的盘序列号,并依次打印控制器类型、slot号、盘序列号和盘符
else
echo "No AHCI device"
fi
done
# Sort the disk according to the block device name
printf "%-15s %-10s %-10s %-20s %-s\n" Controller Slot Volume SerialNum Model
#判断是否存在AHCI device
if [ `cat tmp_log.tmp | wc -l` -eq 0 ]; then
echo "No AHCI devices in the system"
exit
fi
printf "%-15s %-10s %-10s %-20s %-s\n" Controller Slot Volume SerialNum Model> AHCIDisklist.log
cat tmp_log.tmp | sort -k 3 | tee -a AHCIDisklist.log
rm -rf tmp_log.tmp
echo -e "slot topo:\n"
echo " ------------- "
echo -e "| \c"
for i in 0 3 6 9 1 4 7 10 2 5 8 11
do
if [ $i == 1 ] || [ $i == 2 ];then
echo " ------------- "
fi
CheckPresence $i
done
echo " ------------- "
}
function GetAMDSlot(){
#print hdd info
for i in `grep -l Gbps /sys/class/ata_link/*/sata_spd`;do
H=`basename ${i%/*} | sed 's/^....//'`
m=$[$H-1]
echo $m >> num_temp.txt
done
for m in `sort -n num_temp.txt`;do
if [[ $m == 0 ]];then
sdx=`ls -l /sys/class/block/ | grep host0 | awk '{print $9}' | grep -Eo 'sd[a-z]'|uniq`
Sn=`smartctl /dev/$sdx -a | grep -i Serial | awk '{print $3}'`
mo=`smartctl -a /dev/$sdx | grep -i model | awk '{print $3,$4}'`
echo "Slot:M.2 DiskSerialNumber:$Sn Volume:$sdx Model:$mo" | tee -a AHCIDisklist.log
else
sdx=`ls -l /sys/class/block/ | grep host$m | awk '{print $9}' | grep -Eo 'sd[a-z]'|uniq`
Sn=`smartctl /dev/$sdx -a | grep -i Serial | awk '{print $3}'`
mo=`smartctl -a /dev/$sdx | grep -i model | awk '{print $3,$4}'`
echo "Slot:$(($m-4)) DiskSerialNumber:$Sn Volume:$sdx Model:$mo" | tee -a AHCIDisklist.log
fi
done
#print nvme info
E=`lsblk | grep -i nvme`
if [[ $E != "" ]];then
for i in `ls /sys/class/nvme`;do
Sn=`smartctl /dev/$i -a | grep -i Serial | awk '{print $3}'`
m=`ls -l /sys/class/nvme/ | grep -i $i | awk '{print $11}' | cut -c 44-45`
echo "Slot:Rear $(($(($(($m-1))/2))-13)) DiskSerialNumber:$Sn Volume:$i" | tee -a AHCIDisklist.log
done
else
:
fi
echo -e "\n"
echo -e "slot topo:\n"
echo " ------------- "
echo -e "| \c"
echo -e "0 \c"
echo -e "3 \c"
echo -e "6 \c"
echo -e "9 |"
echo " ------------- "
echo -e "| \c"
echo -e "1 \c"
echo -e "4 \c"
echo -e "7 \c"
echo -e "10 |"
echo " ------------- "
echo -e "| \c"
echo -e "2 \c"
echo -e "5 \c"
echo -e "8 \c"
echo -e "11 |"
echo " ------------- "
rm -rf num_temp.txt
}
echo -e "[The script is to check the AHCI disks in the Meituan Mercury System]"
echo -e "[List the AHCI device:(The log is in the "AHCIDisklist.log")]"
[ -f AHCIDisklist.log ] && rm -rf AHCIDisklist.log
Platform="UNKNOW"
CheckPlatform
if [[ $Platform == "AMD" ]];then
GetAMDSlot
elif [[ $Platform == "INTEL" ]];then
GetINTELSlot
else
:
fi