文章目录

  • 1.shell语法:Shell是用C语言编写的程序,它是用户使用Linux的桥梁,硬件>内核(os)>shell>文件系统
    • 1.1 变量:readonly定义只读变量,unset删除变量
    • 1.2 函数:shell脚本传递的参数中包含空格,应使用单引号或双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。if [ -n str1 ] 当字符串的长度大于0时为真(字符串非空)
    • 1.3 运算:算术、关系、布尔、逻辑、字符串、文件运算
    • 1.4 流程控制:if、for、while、case
  • 2.ssh_tool:sed -i 's/\r//g' 文件(删除从txt复制来代码的换行符)
  • 3.build_bmc:To go back to default recipes: devtool reset linux-aspeed , devtool reset u-boot
  • 4.环境变量:用bash调用脚本的时候会创建一个和自己一模一样的shell子进程执行这个外部命令。这个子进程中设置了自己的运行的环境变量,此时父进程的环境变量并没有改变。bash test.sh == ./test.sh。
  • 5.scp_image:不用管STRING1
  • 6.bmc_upgrade:断电重启才从主启,当前永远mtd4
  • 7.自动升级bmc:AC ON物理上电
  • 8.bmc_wtd:syscpld.c中wd_en和wd_kick节点对应寄存器,crontab,FUNCNAME
    • 8.1 AST2500/2600 WDT切换主备:BMC用WDT2作为主备切换的watchdog控制器
    • 8.2 BMC喂狗实现:sys/class/gpio/gpio1/value获取gpio1值
      • watch-dog.h
      • watch-dog.c
      • main.c
      • Makefile
      • run-watch-dog.sh
      • setup-watch-dog.sh
      • watch-dog_0.1.bb
  • 9.PECI(Platform Environment Control Interface):peci是 intel提供的私有协议,openbmc是由intel授权的,其他不授权是不能用,硬件上是一根线,不像i2c是2根线
    • 9.1 模式和命令介绍:peci1.1只支持CPU温度,2.0增加支持MSR相关寄存器,3.0增加支持读intel的PCI配置(根据intel的BDF【Bus/Device/Function】确定读pcie设备里的寄存器地址)
    • 9.2 通过peci读cpu温度:使用RdPkgconfig()命令(read page config),通过peci读到cpu的最大值(tjmax)和一个偏移量(Tcontrol)(距离当前设定的最大值还差多少值),这两个的差值作为cpu实际温度
    • 9.3 通过peci读cpu的DIMM温度:不涉及偏差多少,直接读实时温度,也是用RdPkgconfig()命令
    • 9.4 通过peci读MSR:不止msr还有pcie寄存器一些读法,lerrLoggingReg寄存器通过查cpu手册,发现是pcie寄存器。BDFO四个变量才能确定一个地址,带外方式用RdPCIConfigLocal()读PCIE寄存器
  • 10.fan/vol/curr/temp软连接:i2c_device_add 0 0x0d syscpld 相当于insmod syscpld.ko时走probe函数,/sys/bus/platform/devices/

1.shell语法:Shell是用C语言编写的程序,它是用户使用Linux的桥梁,硬件>内核(os)>shell>文件系统

1.1 变量:readonly定义只读变量,unset删除变量



如果字符串中有空格,必须需要使用引号(str=hello world会报错)。


获取字符串长度:echo ${#str}expr length “${str}”
截取字符串:echo ${str:1:4}:显示字符串第1到第4个字符。
echo ${str:4}:从左边第4个字符开始,一直到结束。
echo ${str:0-6:3}:从倒数第6个字符开始的3个字符。
echo ${str:0-6}:从倒数第6个字符开始,一直到结束。

file=/dir1/dir2/dir3/my.file.txt
${file#*/}:删掉第一个 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt     / 可换成 . 即#*.
${file##*/}:删掉最后一个 / 及其左边的字符串:my.file.txt${file%/*}:删掉最后一个 / 及其右边的字符串:/dir1/dir2/dir3
${file%%/*}:删掉第一个 / 及其右边的字符串:(空值)


#!/bin/bash
for i in `ifconfig | grep -o ^[a-z0-9.]*`
doname=$i echo $nameipaddr=$(ifconfig $i|sed -n 2p|awk '{ print $2 }'|tr -d 'addr:')  # -d删除echo http://$1:8080/api/slave -d '{"slave":"'$2${name}'","ip":"'${ipaddr}'"}'
done


如下截取 = 号左边即第一个。

"-d")shiftcase ${1} in"lc1" | "lc2" | "cmm" | "fb1" | "fb2");;*)usage;;esacdev=${1}led_devie=${dev%[^a-zA-Z]}  # lcif [ "$1" != "cmm" ];thenindex=${dev/*[a-zA-Z]/}   # 1fi;;

设置别名,printf,重定向,exit,until,shift,basename/dirname

不添加引号,转义将不被执行,如下转义。

command > /dev/null 2>&1不在屏幕上显示输出结果错误。/dev/null 是一个特殊文件,写入到它的内容都会被丢弃,从该文件读取内容,什么也读不到。


# a.sh
a()
{return 1
}
if ! a ; thenecho "111"
fi$ ./a.sh
111
# shift.sh
until [ $# -eq 0 ]
do
echo "第一个参数为: $1 参数个数为: $#"
shift
done$./shift.sh 1 2 3 4
第一个参数为: 1 参数个数为: 4
第一个参数为: 2 参数个数为: 3
第一个参数为: 3 参数个数为: 2
第一个参数为: 4 参数个数为: 1
# shift1.sh
sum=0
until [ $# -eq 0 ]
do
sum=`expr $sum + $1`
shift
done
echo "sum is: $sum"$./shift1.sh 10 20 15
结果显示:45
basename /usr/local/nginx/conf/nginx.conf
nginx.conf
basename -s .conf /usr/local/nginx/conf/nginx.conf
nginxdirname //
/
dirname /a/b/
/a
dirname a
.
dirname a/b
arealpath $path : 返回$path的绝对路径,路径不存在会报错,文件不存在不会报错

declare与let:let命令和双小括号 (( )) 的用法是类似的,它们都是用来对整数进行运算,不能对小数(浮点数)或字符串运算。


整型运算如上同如下。


test:用于检查某个条件是否成立,它可以进行数值、字符、文件三个方面的测试

1.2 函数:shell脚本传递的参数中包含空格,应使用单引号或双引号将该参数括起来,以便于脚本将这个参数作为整体来接收。if [ -n str1 ] 当字符串的长度大于0时为真(字符串非空)


1.3 运算:算术、关系、布尔、逻辑、字符串、文件运算

算术:

关系:


布尔:

逻辑:



文件测试运算:

1.4 流程控制:if、for、while、case

if:

for:

while:

until:

case:

break与continue:

2.ssh_tool:sed -i ‘s/\r//g’ 文件(删除从txt复制来代码的换行符)

#!/usr/bin/expect
# b文件,llength等是expect中专属的,和ftp那些命令一样
# obmc-server:~$ whereis expect
# expect: /usr/bin/expect /usr/share/man/man1/expect.1.gz
puts "$argv0"set arg_leng [llength $argv]
puts "$arg_leng" set argv_0   [lindex  $argv 0]
puts "$argv_0"# @obmc-server:~/test$ ./b w
# ./b
# 1
# w
#!/usr/bin/expect
# 如上一行必须加且必须在第一行
if { [llength $argv] < 1} {puts "Usage:"puts "$argv0 raspberr ttyUSBx <pi2 0>"  # ssh-tool.sh pi2 0puts "$argv0 raspberr <pi1> <pi2> <pi3>"  # ssh-tool.sh pi1puts "$argv0 project_name <hollywood> <s3ip-bmc> <s3ip-bsp>"    # ssh-tool.sh hollywood# puts "$argv0 raspberrNUM ttyUSBx [force]"     # ssh-tool.sh pi1 0 force# puts "force if other used tty will kill process,杀串口进程"exit 1
}set arg_leng [llength $argv  ]
set argv_0   [lindex  $argv 0]
set ttyUSBx  [lindex  $argv 1]
# set force    [lindex $argv 2]
set timeout 20
# set pi3_ip [exec sh -c {curl -s http://10.75.92.228:8080/api/help | python -m json.tool |grep -i "pi3" |cut -d '"' -f 4}]
set pi3_ip 10.75.159.104
set local_file ./tmp/deploy/images/obmc-cl/flash-obmc-cl
set passwderror 0#11111111111111111111111111111111111111111111111111111111111111111111111111
if { $argv_0 == "pi1" } {set passwd 123456spawn ssh pi@$pi1_ip
}
if { $argv_0 == "pi2" } {set passwd 123456spawn ssh pi@$pi2_ip
}
if { $argv_0 == "pi3" } {set passwd 123456spawn ssh pi@$pi3_ip
}
if { $argv_0 == "hollywood" } {set passwd 0penBmcspawn ssh-keygen -f "/home_a/yu/.ssh/known_hosts" -R $hollywood_ipspawn ssh root@$hollywood_ip
}
if { $argv_0 == "docker" } {set passwd 1spawn ssh cit@10.75.159.16expect {"*yes/no*" {send "yes\r"exp_continue}"*assword:*" {if { $passwderror == 1 } {puts "passwd is error"exit 2}set timeout 1000set passwderror 1send "$passwd\r"sleep 0.2send "sudo su\r"sleep 0.2send "$passwd\r"sleep 0.2send "docker exec -it 16d93b0d2026 bash\r"sleep 0.2send "zsh\r"sleep 0.2send "ls\r"sleep 0.2send "cd\r"interact}}
}#11111111111111111111111111111111111111111111111111111111111111111111111111
expect {"*yes/no*" {send "yes\r"exp_continue  # 该项被匹配后,还能继续匹配该expect判断语句内的其他项}"*assword:*" {if { $passwderror == 1 } {puts "passwd is error"exit 2}set timeout 1000set passwderror 1send "$passwd\r"if { $arg_leng == 1} {interact   # 执行完成后保持交互状态,把控制权交给控制台,这个时候便可以手动操作。# 如果没有该命令,命令完成后即退出。}if { $arg_leng == 2} {exp_continue  }}"*pi@raspberrypi*" {send " picocom -b 115200 /dev/ttyUSB$ttyUSBx\r"exp_continue}"*FATAL: cannot lock*" {# if { $force == "force" } {#     puts "you can kill process and try again"#     exit 1# }send " ps -ef |grep -i ttyUSB$ttyUSBx\r "interact}"*FATAL: cannot open*" {puts "!!!   ########################################   !!!"puts "!!!no ttyUSB$ttyUSBx"exit 1}"*Terminal ready*" {interact}
}

3.build_bmc:To go back to default recipes: devtool reset linux-aspeed , devtool reset u-boot

#!/bin/bash# downloads() {#     echo "buildpath: [$buildpath]"
#     build_exist=$(grep "DL_DIR" $buildpath/conf/local.conf)
#     echo "buildexist: [$build_exist]"
#     if [ ! -n "$build_exist" ]; then
#         echo "DL_DIR ?= \"/home_a/y/usr/local/downloads\"" >> "conf/local.conf"
#     fi
# }# buildplatform() {#     source openbmc-init-build-env meta-huaqin/meta-$1 build-$1
#     buildpath=$(pwd)
#     downloads
#     bitbake $1-image
#     rm -rf conf/local.conf
# }usage() {echo "Usage: build an openbmc image"echo "    $(basename $0) <platform>"echo "    $(basename $0) <platform> <feature>"echo "    $(basename $0) <platform> <clean>"echo "    $(basename $0) <platform> <clean> <feature>"echoecho "Examples:"echo "    $(basename $0) kestrel"echo "    $(basename $0) kestrel ipmid"echo "    $(basename $0) kestrel clean"echo "    $(basename $0) kestrel clean ipmid"
}
# if [ $# -eq 1 ]; then# buildplatform $1
if [ $# -eq 1 ]; thensource ./setup $1;echo "DL_DIR ?= \"/home_a/y/usr/local/downloads_ocp\"" >> "conf/local.conf"   # openbmc-hollywood-master/build/conf/local.conf 或 meta-huaqin/meta-xs9880-8c/conf/local.conf.samplebitbake  obmc-phosphor-image
elif [ $# -ge 2 ]; thencase $2 in"clean")source ./setup $1;echo "DL_DIR ?= \"/home_a/y/usr/local/downloads_ocp\"" >> "conf/local.conf"bitbake  obmc-phosphor-image -c cleanall obmc-phosphor-image;;"u-boot")# source openbmc-init-build-env meta-huaqin/meta-$1 build-$1 && buildpath=$(pwd); downloads; bitbake u-boot;;"linux-aspeed")# source openbmc-init-build-env meta-huaqin/meta-$1 build-$1 && buildpath=$(pwd); downloads; bitbake linux-aspeed;;*)source openbmc-init-build-env meta-huaqin/meta-$1 build-$1 && buildpath=$(pwd); downloads; bitbake $2;;esac
elseusage
fi
exit 0
# build目录下获取源码:devtool modify linux-aspeed ,devtool modify u-boot
# This will create local Linux package under /workspace/sources/linux-aspeed for development
chmod 777 /home_a/y/app/bin/(usr/local/bin/)build_bmc~$ vi .bash_profile
export PATH=/home_a/y/app/bin:$PATH~$ vi .bashrc
alias gr='grep -nr'

4.环境变量:用bash调用脚本的时候会创建一个和自己一模一样的shell子进程执行这个外部命令。这个子进程中设置了自己的运行的环境变量,此时父进程的环境变量并没有改变。bash test.sh == ./test.sh。

用source来执行脚本的时候,不会创建子进程,而是在父进程中直接执行,所以当需要程序修改当前shell本身的环境变量的时候,用source命令。source test.sh == . test.sh。如下记住ebe从大到小。

上面就是改变linux的env的三种方法,每个用户env都不一样,env中HOME为用户主目录。

export在命令行单独输入是临时的(export…,env可查到多出了刚export的,但用户登出再登录,env查看没有刚export的)。但在.bash_profile中都含有export,用户一登录就执行.bash_profile,所以env中含有这些环境变量,这样export可视为永久。

所有可执行程序都要PATH指定,如ls,pwd(也是可执行程序)不加./(./是在当前目录执行),因为在冒号分隔(冒号不是连接)的几个目录下找。sqlplus命令行命令在/oracle/bin中。


ls这个可执行程序就是在bin目录下,上面PATH已指定。如下若未改为英文显示:未找到命令(中文)。

如下必须在用户主目录/oracle,才能vi .bash_profile。


如下对所有用户有效。

/etc/profile 是文件(里面有不建议在这文件里修改的英文说明), /etc/profile.d/ 是目录(如下新建.sh文件创建全局环境变量)。

如下在sss.sh中写入下行。/etc/profile这个文件中有这么一段shell:for i in /etc/profile.d/*.sh;,会在每次启动时自动加载profile.d目录中每个配置。

不想要什么变量直接删除 /etc/profile.d/ 下对应的shell 脚本即可,当用户重新登录shell如下或source /etc/profile 时会触发。

5.scp_image:不用管STRING1

#!/usr/bin/expect if { [llength $argv] < 2} { puts "Usage:" puts "$argv0 <Image path> IP" puts "$argv0 <Image path> IP <path>" exit 1
}set timeout 20
set Local_File [lindex $argv 0]
set IP [lindex $argv 1]
set STRING 0
spawn ssh-keygen -f "/home_a/y/.ssh/known_hosts" -R $IPproc myscpfunc { STRING1 } {set passwd 0penBmcset passwderror 0 expect { "*assword:*" { if { $passwderror == 1 } { puts "passwd is error" exit 2 } set timeout 1000 set passwderror 1 send "$passwd\r" exp_continue } "yes/no" { send "yes\r" exp_continue } timeout { puts "connect is timeout" exit 3 }}
}if { [llength $argv] == 2} { if {[regexp -nocase "obmc-phosphor-image" $Local_File]} {spawn scp $Local_File root@$IP:/tmp/imagesmyscpfunc $STRINGspawn scp /home_a/y/bak/bmc_upgrade root@$IP:~/myscpfunc $STRING} else {spawn scp $Local_File /home_a/y/bak/bmc_upgrade root@$IP:~/myscpfunc $STRING}
}if { [llength $argv] == 3} { set path [lindex $argv 2]spawn scp $Local_File  root@$IP:$pathmyscpfunc $STRING
}

6.bmc_upgrade:断电重启才从主启,当前永远mtd4

if [ $# -lt 1 ];thenecho "Usage: `basename $0`+<1;2;all>"echo "1   : flash0"echo "2   : flash0ro"echo "all : flash0 & flash0ro"echo "ocp : update ocpbmc image"exit 255
fi
cat /proc/mtd |grep -i "flash0\""
cat /proc/mtd |grep -i "flash0ro"F0_string=$(cat /proc/mtd |grep -i flash0\" |cut -b 1-4)
F1_string=$(cat /proc/mtd |grep -i flash0ro |cut -b 1-4)
if [ "$F1_string" = "" ]; thenF1_string=$(cat /proc/mtd |grep -i flash1 |cut -b 1-4)
fiif [ $1 == "1" ]; thensource /usr/local/bin/openbmc-utils.shecho "Update /dev/$F0_string"flashcp  ./flash-* /dev/$F0_string
elif [ $1 == "2" ]; thensource /usr/local/bin/openbmc-utils.shecho "Update /dev/$F1_string"flashcp ./flash-* /dev/$F1_string
elif [ $1 == "all" ]; thensource /usr/local/bin/openbmc-utils.shecho "Update /dev/$F0_string & /dev/$F1_string"echo "First  : Update /dev/$F0_string"flashcp ./flash-* /dev/$F0_stringecho "Second : Update /dev/$F1_string"flashcp ./flash-* /dev/$F1_string
elif [ $1 == "ocp" ]; thenImage_ID=$(ls /tmp/images/)if [ ${#Image_ID} -eq 8 ];thenecho "IMAGE ID = ${Image_ID}"elseecho "IMAGE ID = ${Image_ID}"echo "Error-----multiple image"exit 255fiecho "busctl set-property xyz.openbmc_project.Software.BMC.Updater /xyz/openbmc_project/software/$Image_ID xyz.openbmc_project.Software.Activation RequestedActivation s xyz.openbmc_project.Software.Activation.RequestedActivations.Active"busctl set-property xyz.openbmc_project.Software.BMC.Updater /xyz/openbmc_project/software/$Image_ID xyz.openbmc_project.Software.Activation RequestedActivation s xyz.openbmc_project.Software.Activation.RequestedActivations.Activesleep 3echo "busctl get-property xyz.openbmc_project.Software.BMC.Updater /xyz/openbmc_project/software/$Image_ID xyz.openbmc_project.Software.Activation Activation" busctl get-property xyz.openbmc_project.Software.BMC.Updater /xyz/openbmc_project/software/$Image_ID xyz.openbmc_project.Software.Activation Activationsleep 1
fiif [ $? == "0" ];thenecho "Update Over"echo "reboot now !!!!"reboot
elseecho "Update fail !!!!"
fi

7.自动升级bmc:AC ON物理上电

#!/bin/sh
#shellcheck disable=SC1091
. /usr/local/bin/openbmc-utils.sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/binBMC_VERSION=/var/log/automatic_upgrade/version/bmc_version #主备版本都和这个比较,而不是主备互相比较
BMC_FW=/var/log/automatic_upgrade/fw/flash-xs9880-8c
BMC_WTD2_COUNT=/var/log/wtd_count
BMC_FW_UPDATE_COUNT=/var/log/bmc_update_count
FW_UPDATE_TIMES=8check_file_ok() {if [ ! -f "$BMC_WTD2_COUNT" ]; then   #这行if是:假如不存在文件echo 0 > $BMC_WTD2_COUNT   #创建文件并写0fiif [ ! -f "$BMC_FW_UPDATE_COUNT" ]; thenecho 0 > $BMC_FW_UPDATE_COUNTfiif [ ! -f "$BMC_VERSION" ] || [ ! -f "$BMC_FW" ]; thenecho "$BMC_VERSION or $BMC_FW file does not exist"exit 255fi
}check_fw_update_count() {bmc_fw_update_cont=$(cat "$BMC_FW_UPDATE_COUNT")if [ "$FW_UPDATE_TIMES" -lt "$bmc_fw_update_cont" ]; thenlogger -p user.err "$0 update bmc times exceeded"exit 255fi
}check_wtd2_count() {if [ "$wdt2_timeout_count" -eq 0 ]; thenecho 0 > $BMC_WTD2_COUNTfi
}#11111111111111111111111111111111111111111111111111111111111111111111111111111
update_bmc_fw() {if [ "$1" = "current" ]; thenflashcp $BMC_FW /dev/mtd4elif [ "$1" = "other" ]; thenflashcp $BMC_FW /dev/mtd9fi
}change_bmc_boot() {if [ "Master"x = "$bmc_boot"x ]; then bmc_boot_info.sh reset slaveelsebmc_boot_info.sh reset masterfi
}get_bmc_version() {if [ "$1" = "other" ]; thenbmc_version=$(version_dump --pingpong | awk -F ": " '{print $2}')elif [ "$1" = "current" ]; thenbmc_version=$(version_dump bmc | awk -F ": " '{print $2}')fiecho "$bmc_version"
}#1111111111111111111111111111111111111111111111111111111111111111111111111111111
update_bmc_fw_update_count() {index=$(cat "$BMC_FW_UPDATE_COUNT")index=$((index+1))echo $index > $BMC_FW_UPDATE_COUNT
}update_wdt2_timeout_count() {echo "$wdt2_timeout_count" > $BMC_WTD2_COUNT
}clean_bmc_fw_update_count() {echo 0 > $BMC_FW_UPDATE_COUNT
}#111111111111111111111111111111111111111111111111111111111111111111111111111111
main() {check_file_okbmc_boot_info=$(bmc_boot_info.sh)bmc_boot=$(echo $bmc_boot_info |awk -F " " '{print $10}')wdt2_timeout_count=$(echo $bmc_boot_info |awk -F " " '{print $4}')bmc_base_version=$(cat "$BMC_VERSION")bmc_wtd2_count=$(cat "$BMC_WTD2_COUNT")current_version=$(get_bmc_version current)other_version=$(get_bmc_version other)check_wtd2_countcheck_fw_update_countecho "$current_version" echo "$other_version"echo "$bmc_wtd2_count"echo "$wdt2_timeout_count"if [ "$bmc_wtd2_count"x = "$wdt2_timeout_count"x ]; then   # N(No) WTD没有增加if [ "$bmc_base_version"x = "$current_version"x ]; then   # 文件版本和当前版本一致if [ "$bmc_base_version"x = "$other_version"x ]; then   # 文件版本和对面版本一致echo "all same"clean_bmc_fw_update_countelse    # 文件版本和当前版本一致,但不和对面版本一致 【只有非当前版本一致】echo "only other not same"update_bmc_fw_update_countupdate_bmc_fw otherfielse  # 文件版本和当前版本不一致if [ "$bmc_base_version"x = "$other_version"x ]; then  # 【只有当前BMC版本不一致】echo "only current not same"change_bmc_bootelse   # 【两块BMC版本都不一致】echo "all not same"update_bmc_fw_update_countupdate_bmc_fw otherchange_bmc_bootfifielse #Y WTD增加了update_wdt2_timeout_countif [ "$bmc_base_version"x = "$current_version"x ]; then  #【当前BMC版本一致】echo "current same"update_bmc_fw_update_countupdate_bmc_fw otherelse  # 【当前BMC版本不一致】echo "current not same"update_bmc_fw_update_countupdate_bmc_fw otherchange_bmc_bootfifi
}
main

8.bmc_wtd:syscpld.c中wd_en和wd_kick节点对应寄存器,crontab,FUNCNAME

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/binWATCHDOG_LOG="/tmp/watchdog.log"usage(){program=$(basename "$0")echo "Usage:"echo "$program <operation>"echo "  <operation>  : start stop kick query restart"echo "Examples:"echo "  $program start"echo ""
}kick()
{ret=$(head -1  /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenecho "0x7c" > /sys/bus/i2c/devices/0-000d/wd_kickelseusageexitfiret=$(date)echo "$ret ${FUNCNAME[0]}" >> $WATCHDOG_LOG
}enable()
{ret=$(head -1  /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" != "0x1" ];thenecho "0x1" > /sys/bus/i2c/devices/0-000d/wd_enelseusageexitfiret=$(date)echo "$ret ${FUNCNAME[0]}" > $WATCHDOG_LOG
}disable()
{ret=$(head -1  /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenecho "0x0" > /sys/bus/i2c/devices/0-000d/wd_enecho "0x7c" > /sys/bus/i2c/devices/0-000d/wd_kickelseusageexitfiret=$(date)echo "$ret ${FUNCNAME[0]}" >> $WATCHDOG_LOG
}check_parameter()
{if [ $# -ne 1 ];thenusageexitficase ${1} in"start" | "stop" | "kick" |"query" |"restart");;*)      #除上面的其他的usageexit;;esac
}check_parameter "$@"case ${1} in"start")ret=$(head -1  /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenusageexitfienablekick;;"stop")disableexit;;"kick")kickexit;;"restart")ret=$(head -1  /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenusageexitfienablekickexit;;"query")ret=$(head -1  /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenecho "ENABLE"elseecho "DISABLE"fiexit;;
esacwhile true
doret=$(head -1  /sys/bus/i2c/devices/0-000d/wd_en)if [ "$ret" = "0x1" ];thenkickfisleep 30
done
root@bmc-oob:~# ps | grep wd588 root      2904 S    runsv /etc/sv/wd591 root      3036 S    {wd} /bin/bash /usr/local/bin/wd start779 root      3036 S    grep wd
root@bmc-oob:~# wd query
ENABLE
root@bmc-oob:~# wd stop
root@bmc-oob:~# wd query
DISABLE
root@bmc-oob:~# wd restart
root@bmc-oob:~# wd kick
root@bmc-oob:~# wd query
ENABLE
init()
{ret=$(ps |grep crond|grep -v grep)if [ "x$ret" = "x" ];thenecho "No found crond process"exitfiif [ ! -d /crontabs ];thenmkdir /crontabstouch /crontabs/rootficrontab -c /etc/cron/crontabs/ /etc/cron/crontabs/rootcp /var/log/watchdog.sh /usr/local/bin/watchdog.sh
}add_task()
{echo "* * * * * /usr/local/bin/watchdog.sh kick" >> /etc/cron/crontabs/rootecho "* * * * * date >> /var/log/date.log" >> /etc/cron/crontabs/root
}del_task()
{sed -i "/\* \* \* \* \* \/usr\/local\/bin\/watchdog.sh kick/d" /etc/cron/crontabs/root
}

8.1 AST2500/2600 WDT切换主备:BMC用WDT2作为主备切换的watchdog控制器

# 检查当前BMC是在主还是备启动的检查函数boot_source实现如下:
check_boot_source()
{# Please refer to reg WDT1/WDT2 Control Register definition to# understand this code block, WDT1 is on page 646 of ast2500v16.pdf# and WDT2 is on page 649 of ast2500v16.pdf# get watch dog1 timeout status registerwdt1=$(devmem 0x1e785010)# get watch dog2 timeout status registerwdt2=$(devmem 0x1e785030)wdt1_timeout_cnt=$(( ((wdt1 & 0xff00) >> 8) ))  #取出前8位,自动转为十进制wdt2_timeout_cnt=$(( ((wdt2 & 0xff00) >> 8) ))wdt1_boot_code_source=$(( ((wdt1 & 0x2) >> 1) )) #取出第1位(不是第0)wdt2_boot_code_source=$(( ((wdt2 & 0x2) >> 1) ))boot_code_source=0# Check both WDT1 and WDT2 to indicate the boot sourceif [ $wdt1_timeout_cnt -ge 1 ] && [ $wdt1_boot_code_source -eq 1 ]; thenboot_code_source=1elif [ $wdt2_timeout_cnt -ge 1 ] && [ $wdt2_boot_code_source -eq 1 ]; thenboot_code_source=1fiecho $boot_code_source
}bmc_boot_info() {# get watch dog1 timeout status registerwdt1=$(devmem 0x1e785010)# get watch dog2 timeout status registerwdt2=$(devmem 0x1e785030)wdt1_timeout_cnt=$(( ((wdt1 & 0xff00) >> 8) ))wdt2_timeout_cnt=$(( ((wdt2 & 0xff00) >> 8) ))boot_code_source=$(check_boot_source)boot_source="Master Flash"if [ $((boot_code_source)) -eq 1 ]; thenboot_source="Slave Flash"fiecho "WDT1 Timeout Count: " $wdt1_timeout_cntecho "WDT2 Timeout Count: " $wdt2_timeout_cntecho "Current BMC Boot Code Source: $boot_source"
}bmc_boot_from() {# Please refer to reg WDT1/WDT2 Control Register definition to# understand this code block, WDT1 is on page 646 of ast2500v16.pdf# and WDT2 is on page 649 of ast2500v16.pdf# Enable watchdog reset_system_after_timeout bit and WDT_enable_signal bit.# Refer to ast2500v16.pdf page 650th.boot_source=0x00000013boot_code_source=$(check_boot_source)if [ "$1" = "master" ]; thenif [ $((boot_code_source)) -eq 0 ]; thenecho "Current boot source is master, no need to switch."return 0fi# Set bit_7 to 0 : Use default boot code whenever WDT reset.boot_source=0x00000033elif [ "$1" = "slave" ]; thenif [ $((boot_code_source)) -eq 1 ]; thenecho "Current boot source is slave, no need to switch."return 0fi# No matter BMC boot from any one of master and slave.# Set bit_7 to 1 : Use second boot code whenever WDT reset.# And the sencond boot code stands for the other boot source.boot_source=0x000000b3fiecho "BMC will switch to $1 after 10 seconds..."/usr/local/bin/watch-dog stop# Clear WDT1 counter and boot code source statusdevmem 0x1e785014 w 0x77# Clear WDT2 counter and boot code source statusdevmem 0x1e785034 w 0x77# Set WDT time out 10s, 0x00989680 = 10,000,000 usdevmem 0x1e785024 32 0x00989680# WDT magic number to restart WDT counter to decrease.devmem 0x1e785028 32 0x4755devmem 0x1e78502c 32 $boot_source
}


如下ac后,bmc处于主。


如下切换spi:设置2ch寄存器为0x93,换到另一个flash,reboot后从备起。





8.2 BMC喂狗实现:sys/class/gpio/gpio1/value获取gpio1值

bmc喂狗gpio硬件管脚:


bmc监听gpio中断硬件管脚:





导出GPIO:echo $gpio_num > /sys/class/gpio/exporteg: echo 1 > /sys/class/gpio/export执行完以上命令后,如果该gpio接口存在且未被占用则会出现如下目录:/sys/class/gpio/gpio1设置方向:gpio的方向分为两类:in和outin:表示该gpio用于输入。(如该gpio连接一个按钮)out:表示该gpio用于输出。(如该gpio连接一个led灯)指定为in模式的命令:echo in > /sys/class/gpio/gpio1/direction指定为out模式的命令如下:echo out > /sys/class/gpio/gpio1/direction //默认value为0echo low > /sys/class/gpio/gpio1/direction //指定方向为out且value为0echo high > /sys/class/gpio/gpio1/direction //指定方向为out且value为1设置高低:只用当方向为out模式时才能指定gpio接口的电压的高低。这个很容易理解,因为如果是in模式的话,它的电平高低取决于所连接外设的电平高低,我们只能读取它的值,不能更改它的值echo 1 > /sys/class/gpio/gpio1/value //指定gpio1为高电平echo 0 > /sys/class/gpio/gpio1/value //指定gpio1为低电平


watch-dog.h

#ifndef SENSOR_MON__h
#define SENSOR_MON__h#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
#include <time.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <dirent.h>
#include <stdarg.h>
#include <syslog.h>
#include <openbmc/libgpio.h>
#include <fcntl.h>
#include <stdbool.h>
#include <poll.h>
#include <ctype.h>
#include <assert.h>
#include <libgen.h>
#include <linux/limits.h>//#define GPIO_KICK_NUM    885
//#define GPIO_KICK_NAME   "GPIOL5"
#define WDT_MASK_PATH "/sys/bus/i2c/devices/82-000d/bmc_wdt_mask"
#define GPIO_KICK_SHADOW "BMC_CPLD_GPIO69_WDO"typedef enum {WD_FUNC_START,  //0WD_FUNC_STOP,WD_FUNC_KICK,WD_FUNC_UNKNOWN,
} wd_func;typedef enum {MASK_ENABLE = 1,MASK_DISABLE = 0,
} wd_mask;// 如下LOG替换syslog , syslog像printf定义在<syslog.h>, 打印在/var/log/message
#define LOG(mode,format, ...)   syslog(mode, format, __VA_ARGS__)int bmc_wd_set(wd_mask value);
void feed_dog_func();#endif

watch-dog.c

#include "watch-dog.h"int bmc_wd_set(wd_mask value){   // bmc设置cpld寄存器控制wtd芯片(是外置芯片,不是bmc芯片内置的)开关FILE* pFile = fopen(WDT_MASK_PATH, "w");char regvalue[4]= {0};int ret = 0;if(value == MASK_DISABLE){ // 0sprintf(regvalue,"0x0");}else if(value == MASK_ENABLE){sprintf(regvalue,"0x1");}ret = fwrite(regvalue, sizeof(regvalue) , 1, pFile );  //ret为次数即fwrite中的1if(ret==1){fflush(pFile);ret = 0;}else{ret = -1;}fclose(pFile);return ret;
}void feed_dog_func()   // bmc通过gpio的0.5s高低电平来喂狗
{int ret = 0;struct timespec n_sleep;n_sleep.tv_sec = 0; //secondes, integer part sleep duration    // 整数n_sleep.tv_nsec = 5e8L; //nanoseconds, decimal part sleep duration   // 小数  0.5s(上行整数0,这行小数5)gpio_desc_t* desc = gpio_open_by_shadow(GPIO_KICK_SHADOW);  // libgpio-ctrl.so中的接口if (!desc) {syslog(LOG_INFO ,"gpio_open_by_shadow fail\n");return ;}ret = gpio_set_direction(desc, GPIO_DIRECTION_OUT);if (ret == -1){syslog(LOG_ERR ,"gpio_change_direction err \n");gpio_close(desc);return ;}ret = gpio_set_edge(desc, GPIO_EDGE_NONE);if (ret == -1){syslog(LOG_ERR ,"gpio_change_edge err \n");gpio_close(desc);return ;}
//BMC启动时,喂狗(硬件gpio管脚,每隔500ms翻转一次高低电平),并关闭中断MASK如下:
//cmm cpld 0X71 地址 bit0 是中断MASK (为1时MASK使能即看门狗关闭;为0时MASK失效即看门狗打开)
//i2cset -f -y 82 0xd 0x71 0xfe 做成bmc_wdt_mask节点ret=bmc_wd_set(MASK_DISABLE);  // 0开wtdif(ret == 0){syslog(LOG_INFO ,"bmc_wd_set OK\n");}else{syslog(LOG_ERR ,"bmc_wd_set Fail\n");gpio_close(desc);return;}while(1){gpio_set_value(desc,GPIO_VALUE_HIGH);nanosleep(&n_sleep, NULL);  // 0.5s 高电平gpio_set_value(desc,GPIO_VALUE_LOW);nanosleep(&n_sleep, NULL);   // 0.5s 低电平}gpio_close(desc);return ;
}

main.c

#include "watch-dog.h"int func_start()
{int ret = 0;ret=bmc_wd_set(MASK_DISABLE);  //mask和disable都是否定if(ret == 0){syslog(LOG_INFO ,"func_start OK\n");}else{syslog(LOG_ERR ,"func_start Fail\n");return -1;}return 0;
}int func_stop()
{int ret = 0;ret=bmc_wd_set(MASK_ENABLE);if(ret == 0){syslog(LOG_INFO ,"func_stop OK\n");}else{syslog(LOG_ERR ,"func_stop Fail\n");return -1;}return 0;
}void usage(void)
{fprintf(stderr, "usage: watch-dog <start/stop/kick> \n");exit (1);
}int func_kick()
{int rc,ret,pid_file;int pid_value;char piddata[12];char file_path[60];pthread_t tid_feed;ret = snprintf(file_path, sizeof(file_path), "/var/run/watch_dog.pid");  // /var/run/a 也可以,记录当前进程pid号if ((ret < 0) || (ret >= sizeof(file_path))) {syslog(LOG_ERR ,"watch_dog:too long for lockfile\n");return -1;}pid_file = open(file_path, O_CREAT | O_RDWR, 0666);if (pid_file < 0) {syslog(LOG_ERR ,"watch_dog: failed to acquire lock\n");exit(1);}else{pid_value=getpid();snprintf(piddata, sizeof(piddata), "%d\n", pid_value);ret=write(pid_file, piddata, sizeof(piddata));  //先open再writeif(ret < 0) {syslog(LOG_ERR ,"watch_dog: write pid err\n");}}rc = flock(pid_file, LOCK_EX | LOCK_NB); // Linux文件锁flock: 检测进程是否已经存在if(rc){if(EWOULDBLOCK == errno){syslog(LOG_ERR ,"Another watch_dog instance is running...\n");exit(1);}}syslog(LOG_INFO ,"watch_dog: daemon started\n");pthread_create(&tid_feed,NULL,(void *)feed_dog_func,NULL);  //一个pthread_create只创建一个线程pthread_join(tid_feed,NULL);if (pid_file >= 0) {unlink(file_path);  //#include<unistd.h> , unlink删除文件}syslog(LOG_INFO ,"watch_dog: daemon end\n");return 0;
}wd_func wd_func_judge(char * desc)
{if (!strcmp(desc, "start")){   // strcmp相同返回0,if(1)执行,shell中if(0)执行return WD_FUNC_START;}else if (!strcmp(desc, "stop")){return WD_FUNC_STOP;}else if (!strcmp(desc, "kick")){return WD_FUNC_KICK;}return WD_FUNC_UNKNOWN;
}int main(int argc, char* argv[])
{wd_func wd_func_sel = WD_FUNC_UNKNOWN;if (argc != 2) {usage();}wd_func_sel = wd_func_judge(argv[1]);if ( wd_func_sel == WD_FUNC_UNKNOWN ){usage();}switch (wd_func_sel){case WD_FUNC_START :func_start();break;case WD_FUNC_STOP :func_stop();break;case WD_FUNC_KICK :func_kick();break;default :break;}return 0;
}

Makefile

#
all: watch-dog
SRC = $(wildcard ./*.c)
CFLAGS += -Wall -Werror -D _XOPEN_SOURCE -pthread -lm -std=c99watch-dog: $(SRC)$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS).PHONY: cleanclean:rm -rf *.o watch-dog

run-watch-dog.sh

exec /usr/local/bin/watch-dog kick

setup-watch-dog.sh

WDTFUNC=/usr/local/bin/watch-dog
# /etc/init.d/setup-watch-dog.sh: start and stop the watch-dog
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin:/usr/local/bin"
case "$1" instart)echo -n "Starting watch dog kick daemon..."runsv /etc/sv/watch-dog > /dev/null 2>&1 &  # runsv找/etc/sv/watch-dog/run文件运行echo "done.";;stop)echo -n "Stopping watch dog daemon..."$WDTFUNC stop > /dev/null 2>&1 &echo "done.";;*)echo "Usage: /etc/init.d/setup-watch-dog.sh {start|stop}"exit 1;;
esac
exit 0

watch-dog_0.1.bb

SUMMARY = "watch dog Daemon"
DESCRIPTION = "Daemon for watch dog"
SECTION = "base"
PR = "r1"
LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://COPYING;md5=eb723b61539feef013de476e68b5c50a"
SRC_URI = "file://COPYING \file://main.c \file://watch-dog.c \file://watch-dog.h \file://Makefile \file://setup-watch-dog.sh \file://run-watch-dog.sh \"
S = "${WORKDIR}"
binfiles = "watch-dog \"
pkgdir = "watch-dog"
LDFLAGS = "-lgpio-ctrl"
DEPENDS += "libgpio-ctrl update-rc.d-native"
RDEPENDS_${PN} += "libgpio-ctrl bash"install_sysv() {install -d ${D}${sysconfdir}/init.dinstall -d ${D}${sysconfdir}/rcS.dinstall -d ${D}${sysconfdir}/svinstall -d ${D}${sysconfdir}/sv/watch-doginstall -d ${D}${sysconfdir}/watch-doginstall -m 755 setup-watch-dog.sh ${D}${sysconfdir}/init.d/setup-watch-dog.shinstall -m 755 run-watch-dog.sh ${D}${sysconfdir}/sv/watch-dog/run  #将run-watch-dog.sh复制到/etc/sv/watch-dog/run文件里update-rc.d -r ${D} setup-watch-dog.sh defaults 93 5  #defaults :开机自动执行setup-watch-dog.sh start ,reboot自动执行setup-watch-dog.sh stop
}do_install() {dst="${D}/usr/local/fbpackages/${pkgdir}"bin="${D}/usr/local/bin"install -d $dstinstall -d $binfor f in ${binfiles}; doinstall -m 755 $f ${dst}/$fln -snf ../fbpackages/${pkgdir}/$f ${bin}/$fdoneinstall_sysv
}FBPACKAGEDIR = "${prefix}/local/fbpackages"
FILES_${PN} = "${FBPACKAGEDIR}/watch-dog ${prefix}/local/bin ${sysconfdir}"

9.PECI(Platform Environment Control Interface):peci是 intel提供的私有协议,openbmc是由intel授权的,其他不授权是不能用,硬件上是一根线,不像i2c是2根线

9.1 模式和命令介绍:peci1.1只支持CPU温度,2.0增加支持MSR相关寄存器,3.0增加支持读intel的PCI配置(根据intel的BDF【Bus/Device/Function】确定读pcie设备里的寄存器地址)


1.PCH模式:需要先访问ME地址挂在smlink上,如下-b就是挂的bus号(i2c即smlink的bus号),-t是挂的地址,一般都是0x2c(设备地址)。BMC通过IPMI给ME发一个raw date命令,ME再发pcie命令到cpu。实际是ME不停给cpu发一些peci命令来获取它需要的数据,它把这些数据做一个缓存在自己内部,bmc向它访问数据的话,me会直接把缓存的数据回到bmc上,如下raw 6 1 是读ME的版本号。

2.PECI模式:obmc上有一个peci-util命令,通过这命令直接访问到cpu内部,peci-util虽是二进制命令,但是底层调用libpeci库(https://github.com/openbmc/libpeci.git),通过libpeci访问 /dev/peci-0节点进行IO操作即那根数据线发peci指令。Openbmc中使能PECI需要同时修改kernel.cfg和image.bb文件:在image.bb中IMAGE_INSTALL 变量中追加”peci-util-v2”来安装peci-util二进制文件即命令,在kernel.cfg中打开三行CONFIG_PECI相关宏来使能PECI驱动即生成 /dev/peci-0,如下图:

如下peci3.0支持的方式,如下10个命令也不是所有cpu平台都支持,具体还要看cpu手册,因为cpu平台功能划分比较细,不是所有平台都支持所有功能,前5个全平台支持。

9.2 通过peci读cpu温度:使用RdPkgconfig()命令(read page config),通过peci读到cpu的最大值(tjmax)和一个偏移量(Tcontrol)(距离当前设定的最大值还差多少值),这两个的差值作为cpu实际温度


如上LSB和MSB反一下。

9.3 通过peci读cpu的DIMM温度:不涉及偏差多少,直接读实时温度,也是用RdPkgconfig()命令

9.4 通过peci读MSR:不止msr还有pcie寄存器一些读法,lerrLoggingReg寄存器通过查cpu手册,发现是pcie寄存器。BDFO四个变量才能确定一个地址,带外方式用RdPCIConfigLocal()读PCIE寄存器



如下第一列0-15个物理核(intel最多支持),项目是0-4个物理核相当于5个cpu,现在项目只读物理核。读出如下0x0400寄存器值,具体解析bios做。读取期间不让cpld使cpu复位重启。cpu中所有msr寄存器(model specific register)是x86中监测CPU方面的寄存器,MSR使用RdIAMSR()命令。

# dumplwt.sh
. /usr/local/bin/openbmc-utils.sh
renice -20 -p $$ >/dev/null 2>&1do_msr_deal()
{echo
echo CPU MSR DUMP:
echo ==============
echo
echo "MCA_ERR_SRC_LOG"
peci-util 0x30 0x05 0x05 0xA1 0x00 0x00 0x05 0x00
echo
echo "IerrLoggingReg"
peci-util 0x30 0x05 0x05 0xE1 0x00 0xA4 0x50 0x18
echo
echo "MCerrLoggingReg"
peci-util 0x30 0x05 0x05 0xE1 0x00 0xA8 0x50 0x18
echo
echo "********************************************************"
echo "*                    MC index 00                       *"
echo "********************************************************"
echo " IA32_MC0_CTL, ProcessorID from 0 to 4 "  # 0x0400
peci-util 0x30 0x05 0x09 0xB1 0x00 0x00 0x00 0x04  # 倒数第三个是ProcessorID 如上一行, 即5个cpu
peci-util 0x30 0x05 0x09 0xB1 0x00 0x01 0x00 0x04
peci-util 0x30 0x05 0x09 0xB1 0x00 0x02 0x00 0x04
peci-util 0x30 0x05 0x09 0xB1 0x00 0x03 0x00 0x04
peci-util 0x30 0x05 0x09 0xB1 0x00 0x04 0x00 0x04 echo " IA32_MC0_CTL2, ProcessorID from 0 to 4 " # 0x0280
peci-util 0x30 0x05 0x09 0xB1 0x00 0x00 0x80 0x02
peci-util 0x30 0x05 0x09 0xB1 0x00 0x01 0x80 0x02
peci-util 0x30 0x05 0x09 0xB1 0x00 0x02 0x80 0x02
peci-util 0x30 0x05 0x09 0xB1 0x00 0x03 0x80 0x02
peci-util 0x30 0x05 0x09 0xB1 0x00 0x04 0x80 0x02 do_peci_select 7 #peci通道提前手动选择,在openbmc-utils.sh里source了一些borad.sh一些共用的脚本接口
do_msr_deal
do_peci_select 8
do_msr_deal
# 如下0x400是MC0起始地址,0x404是MC1起始地址
IA32_MCi_CTL=(0x400 0x404 0x408 0x40c 0x410 0x414 0x418 0x41c 0x420 0x424 0x428)mce_log(){modprobe msrmcelog --daemon  # 手动启动mcelog。查看mcelog日志:vim /var/log/mcelogi=${#IA32_MCi_CTL[@]}echo "read IA32_MCi_CTL register begin ${IA32_MCi_CTL[*]}"for ((cpu=0;cpu<8;cpu++));doecho "cpu $cpu read IA32_MCi_CTL register"for ((row=0;row<i;row++));dordmsr -p   $cpu  ${IA32_MCi_CTL[row]}   -xdonedoneecho "read IA32_MCi_CTL register end"
}
mce_log

10.fan/vol/curr/temp软连接:i2c_device_add 0 0x0d syscpld 相当于insmod syscpld.ko时走probe函数,/sys/bus/platform/devices/

# 5517 bus6 开片选:i2cset  -y -f 6 0x70 0x00 0x4
# if [ -f /sys/bus/i2c/devices/48-0058/mfr_id ];then ln -snf /sys/bus/i2c/devices/48-0058/mfr_id /sys_switch/psu/psu1/model_name;fi# pwm:0%(cpld的0即0x0), 50%(cpld的127即0x7f), 100%(cpld的255即0xff)#!/bin/bash
rm -rf /sys_switch
for((i=1;i<=5;i++));
domkdir -p -m 777 /sys_switch/fan/fan$icd /sys_switch/fan/fan$imkdir motor1 motor2
donefor((i=1;i<=5;i++));
doi2c_device_delete $((32+i)) 0x51 fanmodule#上行执行后: /sys/bus/i2c/devices# ls 没有33-0051,注意上行是0x51i2c_device_add $((32+i)) 0x51 fanmodule# root@bmc-oob:/sys/bus/i2c/devices/33-0051# ls# driver           modalias         part_number      subsystem# harware_version  model_name       power            uevent# hwmon            name             serial_numberln -s ${FCBCPLD_SYSFS_DIR}/fan_number /sys_switch/fan/numberln -s /sys/bus/i2c/devices/$((32+i))-0051/part_number /sys_switch/fan/fan$i/part_numberln -s /sys/bus/i2c/devices/$((32+i))-0051/serial_number /sys_switch/fan/fan$i/serial_numberln -s /sys/bus/i2c/devices/$((32+i))-0051/model_name /sys_switch/fan/fan$i/model_nameln -s /sys/bus/i2c/devices/$((32+i))-0051/harware_version /sys_switch/fan/fan$i/harware_versionln -s ${FCBCPLD_SYSFS_DIR}/fan${i}_pwm_ctrl /sys_switch/fan/fan$i/motor1/ratioln -s ${FCBCPLD_SYSFS_DIR}/fan${i}_pwm_ctrl /sys_switch/fan/fan$i/motor2/ratioln -s ${FCBCPLD_SYSFS_DIR}/fan${i}_airflow /sys_switch/fan/fan$i/motor1/directionln -s ${FCBCPLD_SYSFS_DIR}/fan${i}_airflow /sys_switch/fan/fan$i/motor2/directionln -s ${FCBCPLD_SYSFS_DIR}/fan${i}_present /sys_switch/fan/fan$i/statusln -s ${FCBCPLD_SYSFS_DIR}/fan${i}_led_status /sys_switch/fan/fan$i/led_statusln -s ${FCBCPLD_SYSFS_DIR}/motor_number /sys_switch/fan/fan$i/motor_numberln -s ${FCBCPLD_SYSFS_DIR}/fan${i}_input /sys_switch/fan/fan$i/motor1/speedln -s ${FCBCPLD_SYSFS_DIR}/fan${i}0_input /sys_switch/fan/fan$i/motor2/speedln -s ${FCBCPLD_SYSFS_DIR}/speed_tolerance /sys_switch/fan/fan$i/motor1/speed_toleranceln -s ${FCBCPLD_SYSFS_DIR}/speed_tolerance /sys_switch/fan/fan$i/motor2/speed_toleranceln -s ${FCBCPLD_SYSFS_DIR}/speed_target /sys_switch/fan/fan$i/motor1/speed_targetln -s ${FCBCPLD_SYSFS_DIR}/speed_target /sys_switch/fan/fan$i/motor2/speed_targetln -s ${FCBCPLD_SYSFS_DIR}/fan${i}_max /sys_switch/fan/fan$i/motor1/speed_maxln -s ${FCBCPLD_SYSFS_DIR}/fan${i}0_max /sys_switch/fan/fan$i/motor2/speed_maxln -s ${FCBCPLD_SYSFS_DIR}/fan${i}_min /sys_switch/fan/fan$i/motor1/speed_minln -s ${FCBCPLD_SYSFS_DIR}/fan${i}0_min /sys_switch/fan/fan$i/motor2/speed_min
done########################################################vol begain
for((a=1;a<=36;a++));
domkdir -p -m 777 /sys_switch/vol_sensor/vol$a
donefor((i=1;i<=36;i++));
dotouch /sys_switch/vol_sensor/vol$i/rangeecho NA > /sys_switch/vol_sensor/vol$i/rangetouch /sys_switch/vol_sensor/vol$i/nominal_valueecho NA > /sys_switch/vol_sensor/vol$i/nominal_value
donefor((b=1;b<=2;b++));
doln -s $(find /sys/bus/i2c/devices/17-0064/hwmon -name "hwmon*" | tail -n 1)/in${b}_label /sys_switch/vol_sensor/vol$b/aliasln -s $(find /sys/bus/i2c/devices/17-0064/hwmon -name "hwmon*" | tail -n 1)/in${b}_label /sys_switch/vol_sensor/vol$b/typeln -s $(find /sys/bus/i2c/devices/17-0064/hwmon -name "hwmon*" | tail -n 1)/in${b}_crit /sys_switch/vol_sensor/vol$b/maxln -s $(find /sys/bus/i2c/devices/17-0064/hwmon -name "hwmon*" | tail -n 1)/in${b}_lcrit /sys_switch/vol_sensor/vol$b/min
donefor((c=3;c<=4;c++));
doln -s $(find /sys/bus/i2c/devices/17-0066/hwmon -name "hwmon*" | tail -n 1)/in$((c-2))_label /sys_switch/vol_sensor/vol$c/aliasln -s $(find /sys/bus/i2c/devices/17-0066/hwmon -name "hwmon*" | tail -n 1)/in$((c-2))_label /sys_switch/vol_sensor/vol$c/typeln -s $(find /sys/bus/i2c/devices/17-0066/hwmon -name "hwmon*" | tail -n 1)/in$((c-2))_crit /sys_switch/vol_sensor/vol$c/maxln -s $(find /sys/bus/i2c/devices/17-0066/hwmon -name "hwmon*" | tail -n 1)/in$((c-2))_lcrit /sys_switch/vol_sensor/vol$c/min
doneln -s /sys/bus/i2c/devices/25-0068/modalias /sys_switch/vol_sensor/vol5/alias
ln -s /sys/bus/i2c/devices/25-0068/name /sys_switch/vol_sensor/vol5/type
ln -s /sys/bus/i2c/devices/25-0068/in1_crit /sys_switch/vol_sensor/vol5/max
ln -s /sys/bus/i2c/devices/25-0068/in1_lcrit /sys_switch/vol_sensor/vol5/minfor((d=6;d<=7;d++));
doln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/in$((d-3))_label /sys_switch/vol_sensor/vol$d/aliasln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/in$((d-3))_label /sys_switch/vol_sensor/vol$d/typeln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/in$((d-3))_crit /sys_switch/vol_sensor/vol$d/maxln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/in$((d-3))_lcrit /sys_switch/vol_sensor/vol$d/min
donefor((e=8;e<=9;e++));
doln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/in$((e-7))_label /sys_switch/vol_sensor/vol$e/aliasln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/in$((e-7))_label /sys_switch/vol_sensor/vol$e/typeln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/in$((e-7))_crit /sys_switch/vol_sensor/vol$e/maxln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/in$((e-7))_lcrit /sys_switch/vol_sensor/vol$e/min
donefor((f=10;f<=17;f++));
doln -s /sys/bus/i2c/devices/24-002b/modalias /sys_switch/vol_sensor/vol$f/aliasln -s /sys/bus/i2c/devices/24-002b/name /sys_switch/vol_sensor/vol$f/typetouch /sys_switch/vol_sensor/vol$f/maxecho NA > /sys_switch/vol_sensor/vol$f/maxtouch /sys_switch/vol_sensor/vol$f/minecho NA > /sys_switch/vol_sensor/vol$f/min
donefor((g=18;g<=23;g++));
doln -s /sys/bus/i2c/devices/20-0049/modalias /sys_switch/vol_sensor/vol$g/aliasln -s /sys/bus/i2c/devices/20-0049/name /sys_switch/vol_sensor/vol$g/typetouch /sys_switch/vol_sensor/vol$g/maxecho NA > /sys_switch/vol_sensor/vol$g/maxtouch /sys_switch/vol_sensor/vol$g/minecho NA > /sys_switch/vol_sensor/vol$g/min
donefor((h=24;h<=30;h++));
doln -s /sys/bus/i2c/devices/26-0048/modalias /sys_switch/vol_sensor/vol$h/aliasln -s /sys/bus/i2c/devices/26-0048/name /sys_switch/vol_sensor/vol$h/typetouch /sys_switch/vol_sensor/vol$h/maxecho NA > /sys_switch/vol_sensor/vol$h/maxtouch /sys_switch/vol_sensor/vol$h/minecho NA > /sys_switch/vol_sensor/vol$h/min
doneln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/in4_label /sys_switch/vol_sensor/vol31/alias
ln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/in4_label /sys_switch/vol_sensor/vol31/type
ln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/in4_crit /sys_switch/vol_sensor/vol31/max
ln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/in4_lcrit /sys_switch/vol_sensor/vol31/minfor((i=32;i<=36;i++));
doln -s /sys/bus/i2c/devices/26-0049/modalias /sys_switch/vol_sensor/vol$i/aliasln -s /sys/bus/i2c/devices/26-0049/name /sys_switch/vol_sensor/vol$i/typetouch /sys_switch/vol_sensor/vol$i/maxecho NA > /sys_switch/vol_sensor/vol$i/maxtouch /sys_switch/vol_sensor/vol$i/minecho NA > /sys_switch/vol_sensor/vol$i/min
done#########################################################curr begain
for((j=1;j<=9;j++));
domkdir -p -m 777 /sys_switch/curr_sensor/curr$jtouch /sys_switch/curr_sensor/curr$j/minecho 0 > /sys_switch/curr_sensor/curr$j/min
donefor((k=1;k<=2;k++));
doln -s $(find /sys/bus/i2c/devices/17-0064/hwmon -name "hwmon*" | tail -n 1)/curr${k}_label /sys_switch/curr_sensor/curr$k/aliasln -s $(find /sys/bus/i2c/devices/17-0064/hwmon -name "hwmon*" | tail -n 1)/curr${k}_label /sys_switch/curr_sensor/curr$k/typeln -s $(find /sys/bus/i2c/devices/17-0064/hwmon -name "hwmon*" | tail -n 1)/curr${k}_crit /sys_switch/curr_sensor/curr$k/maxln -s $(find /sys/bus/i2c/devices/17-0064/hwmon -name "hwmon*" | tail -n 1)/curr${k}_input /sys_switch/curr_sensor/curr$k/value
donefor((l=3;l<=4;l++));
doln -s $(find /sys/bus/i2c/devices/17-0066/hwmon -name "hwmon*" | tail -n 1)/curr$((l-2))_label /sys_switch/curr_sensor/curr${l}/aliasln -s $(find /sys/bus/i2c/devices/17-0066/hwmon -name "hwmon*" | tail -n 1)/curr$((l-2))_label /sys_switch/curr_sensor/curr${l}/typeln -s $(find /sys/bus/i2c/devices/17-0066/hwmon -name "hwmon*" | tail -n 1)/curr$((l-2))_crit /sys_switch/curr_sensor/curr${l}/maxln -s $(find /sys/bus/i2c/devices/17-0066/hwmon -name "hwmon*" | tail -n 1)/curr$((l-2))_input /sys_switch/curr_sensor/curr${l}/value
doneln -s /sys/bus/i2c/devices/25-0068/modalias /sys_switch/curr_sensor/curr5/alias
ln -s /sys/bus/i2c/devices/25-0068/name /sys_switch/curr_sensor/curr5/type
ln -s /sys/bus/i2c/devices/25-0068/curr1_crit /sys_switch/curr_sensor/curr5/max
# ln -s /sys/bus/i2c/devices/25-0068/curr1_lcrit /sys_switch/curr_sensor/curr5/min
ln -s /sys/bus/i2c/devices/25-0068/curr1_input /sys_switch/curr_sensor/curr5/valuefor((m=6;m<=7;m++));
doln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/curr$((m-3))_label /sys_switch/curr_sensor/curr${m}/aliasln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/curr$((m-3))_label /sys_switch/curr_sensor/curr${m}/typeln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/curr$((m-3))_crit /sys_switch/curr_sensor/curr${m}/maxln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/curr$((m-3))_input /sys_switch/curr_sensor/curr${m}/value
donefor((n=8;n<=9;n++));
doln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/curr$((n-7))_label /sys_switch/curr_sensor/curr${n}/aliasln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/curr$((n-7))_label /sys_switch/curr_sensor/curr${n}/typeln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/curr$((n-7))_max /sys_switch/curr_sensor/curr${n}/maxln -s $(find /sys/bus/i2c/devices/24-002b/hwmon -name "hwmon*" | tail -n 1)/curr$((n-7))_input /sys_switch/curr_sensor/curr${n}/value
done#########################################################temp begain
for((i=1;i<=14;i++));
domkdir -p -m 777 /sys_switch/temp_sensor/temp$i
donetouch /sys_switch/temp_sensor/temp1/alias
echo NA > /sys_switch/temp_sensor/temp1/alias
touch /sys_switch/temp_sensor/temp1/type
echo NA > /sys_switch/temp_sensor/temp1/type
touch /sys_switch/temp_sensor/temp1/max
echo NA > /sys_switch/temp_sensor/temp1/max
touch /sys_switch/temp_sensor/temp1/min
echo NA > /sys_switch/temp_sensor/temp1/min
touch /sys_switch/temp_sensor/temp1/value
echo NA > /sys_switch/temp_sensor/temp1/valueln -s $(find /sys/bus/i2c/devices/i2c-42/42-0048/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp2/alias
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-0048/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp2/type
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-0048/hwmon -name "hwmon*" | tail -n 1)/temp1_max /sys_switch/temp_sensor/temp2/max
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-0048/hwmon -name "hwmon*" | tail -n 1)/temp1_max_hyst /sys_switch/temp_sensor/temp2/min
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-0048/hwmon -name "hwmon*" | tail -n 1)/temp1_input /sys_switch/temp_sensor/temp2/valuetouch /sys_switch/temp_sensor/temp3/alias
echo NA > /sys_switch/temp_sensor/temp3/alias
touch /sys_switch/temp_sensor/temp3/type
echo NA > /sys_switch/temp_sensor/temp3/type
touch /sys_switch/temp_sensor/temp3/max
echo NA > /sys_switch/temp_sensor/temp3/max
touch /sys_switch/temp_sensor/temp3/min
echo NA > /sys_switch/temp_sensor/temp3/min
touch /sys_switch/temp_sensor/temp3/value
echo NA > /sys_switch/temp_sensor/temp3/valueln -s $(find /sys/bus/i2c/devices/i2c-39/39-0048/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp4/alias
ln -s $(find /sys/bus/i2c/devices/i2c-39/39-0048/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp4/type
ln -s $(find /sys/bus/i2c/devices/i2c-39/39-0048/hwmon -name "hwmon*" | tail -n 1)/temp1_max /sys_switch/temp_sensor/temp4/max
ln -s $(find /sys/bus/i2c/devices/i2c-39/39-0048/hwmon -name "hwmon*" | tail -n 1)/temp1_max_hyst /sys_switch/temp_sensor/temp4/min
ln -s $(find /sys/bus/i2c/devices/i2c-39/39-0048/hwmon -name "hwmon*" | tail -n 1)/temp1_input /sys_switch/temp_sensor/temp4/valueln -s $(find /sys/bus/i2c/devices/i2c-39/39-0049/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp5/alias
ln -s $(find /sys/bus/i2c/devices/i2c-39/39-0049/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp5/type
ln -s $(find /sys/bus/i2c/devices/i2c-39/39-0049/hwmon -name "hwmon*" | tail -n 1)/temp1_max /sys_switch/temp_sensor/temp5/max
ln -s $(find /sys/bus/i2c/devices/i2c-39/39-0049/hwmon -name "hwmon*" | tail -n 1)/temp1_max_hyst /sys_switch/temp_sensor/temp5/min
ln -s $(find /sys/bus/i2c/devices/i2c-39/39-0049/hwmon -name "hwmon*" | tail -n 1)/temp1_input /sys_switch/temp_sensor/temp5/valueln -s $(find /sys/bus/i2c/devices/i2c-40/40-004e/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp6/alias
ln -s $(find /sys/bus/i2c/devices/i2c-40/40-004e/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp6/type
ln -s $(find /sys/bus/i2c/devices/i2c-40/40-004e/hwmon -name "hwmon*" | tail -n 1)/temp1_max /sys_switch/temp_sensor/temp6/max
ln -s $(find /sys/bus/i2c/devices/i2c-40/40-004e/hwmon -name "hwmon*" | tail -n 1)/temp1_max_hyst /sys_switch/temp_sensor/temp6/min
ln -s $(find /sys/bus/i2c/devices/i2c-40/40-004e/hwmon -name "hwmon*" | tail -n 1)/temp1_input /sys_switch/temp_sensor/temp6/valueln -s $(find /sys/bus/i2c/devices/i2c-40/40-004f/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp7/alias
ln -s $(find /sys/bus/i2c/devices/i2c-40/40-004f/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp7/type
ln -s $(find /sys/bus/i2c/devices/i2c-40/40-004f/hwmon -name "hwmon*" | tail -n 1)/temp1_max /sys_switch/temp_sensor/temp7/max
ln -s $(find /sys/bus/i2c/devices/i2c-40/40-004f/hwmon -name "hwmon*" | tail -n 1)/temp1_max_hyst /sys_switch/temp_sensor/temp7/min
ln -s $(find /sys/bus/i2c/devices/i2c-40/40-004f/hwmon -name "hwmon*" | tail -n 1)/temp1_input /sys_switch/temp_sensor/temp7/valueln -s $(find /sys/bus/i2c/devices/i2c-41/41-0049/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp8/alias
ln -s $(find /sys/bus/i2c/devices/i2c-41/41-0049/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp8/type
ln -s $(find /sys/bus/i2c/devices/i2c-41/41-0049/hwmon -name "hwmon*" | tail -n 1)/temp1_max /sys_switch/temp_sensor/temp8/max
ln -s $(find /sys/bus/i2c/devices/i2c-41/41-0049/hwmon -name "hwmon*" | tail -n 1)/temp1_max_hyst /sys_switch/temp_sensor/temp8/min
ln -s $(find /sys/bus/i2c/devices/i2c-41/41-0049/hwmon -name "hwmon*" | tail -n 1)/temp1_input /sys_switch/temp_sensor/temp8/valueln -s $(find /sys/bus/i2c/devices/i2c-41/41-0048/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp9/alias
ln -s $(find /sys/bus/i2c/devices/i2c-41/41-0048/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp9/type
ln -s $(find /sys/bus/i2c/devices/i2c-41/41-0048/hwmon -name "hwmon*" | tail -n 1)/temp1_max /sys_switch/temp_sensor/temp9/max
ln -s $(find /sys/bus/i2c/devices/i2c-41/41-0048/hwmon -name "hwmon*" | tail -n 1)/temp1_max_hyst /sys_switch/temp_sensor/temp9/min
ln -s $(find /sys/bus/i2c/devices/i2c-41/41-0048/hwmon -name "hwmon*" | tail -n 1)/temp1_input /sys_switch/temp_sensor/temp9/valueln -s $(find /sys/bus/i2c/devices/i2c-42/42-0048/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp10/alias
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-0048/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp10/type
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-0048/hwmon -name "hwmon*" | tail -n 1)/temp1_max /sys_switch/temp_sensor/temp10/max
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-0048/hwmon -name "hwmon*" | tail -n 1)/temp1_max_hyst /sys_switch/temp_sensor/temp10/min
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-0048/hwmon -name "hwmon*" | tail -n 1)/temp1_input /sys_switch/temp_sensor/temp10/valueln -s $(find /sys/bus/i2c/devices/i2c-42/42-0049/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp11/alias
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-0049/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp11/type
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-0049/hwmon -name "hwmon*" | tail -n 1)/temp1_max /sys_switch/temp_sensor/temp11/max
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-0049/hwmon -name "hwmon*" | tail -n 1)/temp1_max_hyst /sys_switch/temp_sensor/temp11/min
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-0049/hwmon -name "hwmon*" | tail -n 1)/temp1_input /sys_switch/temp_sensor/temp11/valueln -s $(find /sys/bus/i2c/devices/i2c-42/42-004a/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp12/alias
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-004a/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp12/type
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-004a/hwmon -name "hwmon*" | tail -n 1)/temp1_max /sys_switch/temp_sensor/temp12/max
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-004a/hwmon -name "hwmon*" | tail -n 1)/temp1_max_hyst /sys_switch/temp_sensor/temp12/min
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-004a/hwmon -name "hwmon*" | tail -n 1)/temp1_input /sys_switch/temp_sensor/temp12/valueln -s $(find /sys/bus/i2c/devices/i2c-42/42-004b/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp13/alias
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-004b/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp13/type
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-004b/hwmon -name "hwmon*" | tail -n 1)/temp1_max /sys_switch/temp_sensor/temp13/max
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-004b/hwmon -name "hwmon*" | tail -n 1)/temp1_max_hyst /sys_switch/temp_sensor/temp13/min
ln -s $(find /sys/bus/i2c/devices/i2c-42/42-004b/hwmon -name "hwmon*" | tail -n 1)/temp1_input /sys_switch/temp_sensor/temp13/valueln -s $(find /sys/bus/i2c/devices/i2c-8/8-004a/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp14/alias
ln -s $(find /sys/bus/i2c/devices/i2c-8/8-004a/hwmon -name "hwmon*" | tail -n 1)/name /sys_switch/temp_sensor/temp14/type
ln -s $(find /sys/bus/i2c/devices/i2c-8/8-004a/hwmon -name "hwmon*" | tail -n 1)/temp1_max /sys_switch/temp_sensor/temp14/max
ln -s $(find /sys/bus/i2c/devices/i2c-8/8-004a/hwmon -name "hwmon*" | tail -n 1)/temp1_max_hyst /sys_switch/temp_sensor/temp14/min
ln -s $(find /sys/bus/i2c/devices/i2c-8/8-004a/hwmon -name "hwmon*" | tail -n 1)/temp1_input /sys_switch/temp_sensor/temp14/value

【Note4】shell语法,ssh/build/scp/upgrade,环境变量,自动升级bmc,bmc_wtd,peci,软连接相关推荐

  1. shell编程(三) : [Linux基础] Linux 环境变量

    接上一篇文章Linux shell编程(二): Linux shell基础 2.3 Linux环境变量 bash shell用一个叫作环境变量(environment variable)的特性来存储有 ...

  2. shell执行脚本的方法及环境变量

    执行脚本的方法 (1)bash ./filename.sh(产生子进程,再运行,使用当前指定的bash shell去运行) (2)./filename.sh(产生子进程,再运行,使用脚本里面指定的sh ...

  3. linux 带环境变量 远程执行,SSH远程执行命令环境变量问题

    SSH命令格式 usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec] [-D [bind_address: ...

  4. jenkins执行shell脚本,找不到环境变量

    2019独角兽企业重金招聘Python工程师标准>>> 问题如摘要描述:问题原因分析参考 jenkins找不到环境变量 解决方案:在需要执行的脚本前加上 /bin/bash -l   ...

  5. MAC IOS ssh 连接下修改环境变量

    根路径: suningdeMac-mini:/ suning$ ls Applications System bin etc net tmp Library Users cores home priv ...

  6. webpack vue 环境变量_webpack升级指南

    导语:前端开发的同学基本上都知道,webpack现在已经是主流的前端项目构建工具,从1版本到现在的4版本(以下简称webpack4),webpack进行了多次优化,目的是让前端构建的门槛更低,操作更简 ...

  7. tomcat升级_「shell脚本」懒人运维之自动升级tomcat应用(war包)

    准备: 提前修改war包里的相关配置,并上传到服务器: 根据要自动升级的tomcat应用修改或添加脚本相关内容: tomcat启动脚本如是自己写的,要统一格式命名,如:xxx.xxxTomcat 等: ...

  8. linux环境变量自动配置,Linux进入系统时自动配置 环境变量的要领

    用Exp ort命令能够 配置 环境变量,但是假如 每回进入系统之后都要重新配置 一遍环境变量就很烦人.Linux给大众 提供了自动配置 环境变量的要领 ,那就是修改 .bashrc 文件. 通常 说 ...

  9. 本地tomcat启动war包_「shell脚本」懒人运维之自动升级tomcat应用(war包)

    准备: 提前修改war包里的相关配置,并上传到服务器: 根据要自动升级的tomcat应用修改或添加脚本相关内容: tomcat启动脚本如是自己写的,要统一格式命名,如:xxx.xxxTomcat 等: ...

最新文章

  1. python分类流程_文本分类指南:你真的要错过 Python 吗?
  2. 【哲学】不可知论是什么?agnosticism
  3. 使用PIE/PIF值判断DVD刻录机的刻录品质
  4. jaxb int convert to integer
  5. vue积累——另一种走马灯
  6. ajax获得excel文件流在前端打开_主流前端技术讲解,面试必考!
  7. 视频增强之“动态范围扩展”HDR技术漫谈
  8. std c++ 获取运行时间封装
  9. 谈推荐场景下的对比学习
  10. 携程ELK日志分析平台深耕之路
  11. 如何使用Java代码获取Android移动终端Mac地址
  12. linux shell写日志,Linux shell编程之文件内容写入和日志记录
  13. css中margin属性的探究
  14. mysql从备份,mysql 主从同步范例-从同步备份步骤
  15. 127.0.0.1 zxt.php_windows 10 下docker布置nginx+php环境,用宿主WEB目录负载均衡
  16. Intel(R) Matrix Storage Manager 介绍
  17. android 应用升级,系统做了什么?
  18. HONOR Magicbook 进不了系统
  19. js 打印去掉页眉页脚页码_javascript 打印时去掉页眉页脚
  20. 如何防止别人偷窥我给宝贝儿娜娜的信

热门文章

  1. 使用原生JavaScript改变DOM元素面试题
  2. 电商后台设计:品类管理
  3. 第059篇:高分二号遥感影像预处理流程(ENVI5.3.1平台+ENVI App Store中最新的中国国产卫星支持工具)
  4. xposed 框架学习
  5. win7系统打开截图工具显示“截图工具当前未在计算机上运行” 如何解决
  6. 【ArcGIS风暴】CASS建立标准分幅图框并在ArcGIS中DOM批量分幅案例教程
  7. FPGA简单全加器设计
  8. unity3D 下雨效果实现
  9. 计算机作业微波炉工作的原理,微波炉工作电路原理图及功能图解
  10. 我的毕业四年总结及对未来的期许!