实现U盘升级的shell脚本

这个脚本是放到应用程序里去使用的,所以main函数里主要是三个功能:(1)杀死正在运行的应用进程(2)把新的应用程序覆盖旧的(3)重启应用程序。但实现着三个功能需要一些函数去辅助,以下先讲讲其中一些函数,再把完整的代码给大家。

目录

进程是否存在函数

比较文件函数

升级函数

杀死进程函数

完整代码

实现效果


进程是否存在函数

# 进程是否存在
# 参数:进程名字
# 返回值:RET_EP 1 存在,0不存在
ExistProcess ( )
{
	#echo "ps -ef | grep $1 | grep -v grep"
	CHECK=`ps -ef | grep $1 | grep -v grep`  #列出所有的进程信息、再从列出项中找到包含进程名字的、grep -v 排除掉包含grep的
	                                         #因为本条指令就是包含进程名的,但我们要查找的是进程本身
	if [ -z "$CHECK" ];then                  #检查变量$CHECK是否为空,-z测试字符串是否为空
		RET_EP=0
	else
		RET_EP=1
	fi
	#echo $CHECK
}

大家可以先挨着输入一下这些命令,就知道每条命令具体再处理什么。可以用echo打印到出口去看看,我这里是注释掉了。

比较文件函数

我们升级应用程序一定会有一个比较的过程,如果不一样则升级,一样就无需升级。

# 两个文件是否相同
# 参数1:文件1路径
# 参数2:文件2路径
# 返回值:RET_IS_SAME_FILE,1 相同  0 不相同
IsSameFile ( )
{
	LOG "==========in IsSameFile=========="
	LOG "param1 is $1"
	LOG "param2 is $2"
	if [[ $# -lt 2 ]];then                  #检查传递给函数的参数数量是否少于2个,$# ——添加到Shell的参数个数 -lt比较运算符小于,小于2说明给的参数不够
		RET_IS_SAME_FILE=0
	fi

	FILE_DATE1=`ls -e "$1" | cut -c30-69`   #列出参数1路径下应用程序的信息,截取第30到69的字符(代码大小,最后修改日期时间)
	FILE_DATE2=`ls -e "$2" | cut -c30-69`   #列出参数2路径下应用程序的信息,截取第30到69的字符(代码大小,最后修改日期时间)
	#DATE_DIFF=$((FILE_DATE1 - FILE_DATE2))
	LOG "$FILE_DATE1"
	LOG "$FILE_DATE2"

	if [[ "$FILE_DATE1" == "$FILE_DATE2" ]];then   #比较文件大小及最后修改时间,一样则返回1,不一样则返回0
		RET_IS_SAME_FILE=1
	else
		RET_IS_SAME_FILE=0
	fi
}

LOG是我们的一个日志函数,下面完整的代码里会有,我们这里是通过比较文件的修改时间,来判断需不需要升级的。

升级函数

其实升级,就是一个文件拷贝的过程。

# 更新文件
# 参数1 新文件路径
# 参数2 目标文件路径
# 返回值 RET_UPDATE: 0-更新失败  1-成功	2-无需更新
UpdateFile ( )
{
	IsSameFile $1 $2                                     #调用比较程序函数,一样则不需要更新
	#LOG "$1 $2 is same : $RET_IS_SAME_FILE"
	if [[ $RET_IS_SAME_FILE == 1 ]];then
		LOG "$1 文件一致,无需更新!"
		RET_UPDATE=2
	else                                                 #不一样则将参数一路径下的文件拷贝到参数二路径下文件
		cp -p "$1" "$2"
		if [[ $? == 0 ]];then                            #用来检查上一个命令执行的退出状态码是否为0
			LOG "更新文件, 成功: $2"
			RET_UPDATE=1
		else
			LOG "更新文件, 失败: $2"
			RET_UPDATE=0
		fi
	fi
}

杀死进程函数

# 杀死进程
# 参数 进程名字
KillProcess () {
echo $1
  Linux_new_id=`ps -ef | grep $1 | grep -v grep | awk '{print $1}'`
echo $Linux_new_id
 
for id in $Linux_new_id
do
    kill $id  
    echo "killed $id"  
done

}

在我们升级前需要先kill掉进程,所以这个函数就是实现,先找的这个进程本身,并将它杀死。

完整代码

完整代码里还包含了判断升级状态,和创建文件目录,打印日志到指定路径的小功能,更加完善。大家可以参考。大家如果测试时对路径做相应的修改就可以了。加入我们运行这hello1程序,在U盘里放入hello2,然后插入即可看到实现的效果。

#!/usr/bin/env bash

HARDDISK1_PATH='/opt'     #放应用程序和回滚版本应用程序(其实总共就是这两个目录)
HARDDISK12_PATH='/HardDisk12'   #放日志记录
# DRU_200C主控程序目录
PROGRAM_PATH='/opt'       #就是第一个目录,只不过给个定义
LOG_PATH='/HardDisk12/USB_log'  #日志的具体目录

PROGRAM_NAME='hello'            #程序名称




# 升级结果缓存
# 0 : 升级失败
# 1 : 升级成功
# 2 : 无需升级
TEMP_RET_UPDATE_DRU_200C_ZK=2      #初始升级状态为无需升级

# 功能:DRU_200C主控升级状态处理
# 输入参数:升级状态
# 注:
# 若升级成功,且当前总的升级状态不是“升级失败”,则更新为“升级成功”;
# 若升级失败,则更新总的升级状态为“升级失败”
# 否则,不处理
DRU_200CUpdateStatusHandler ()
{
	if [[ $1 == 1 ]];then                            # 若升级成功,且当前总的升级状态不是“升级失败”,则更新为“升级成功”;
	if [[ $TEMP_RET_UPDATE_DRU_200C_ZK != 0 ]];then
		TEMP_RET_UPDATE_DRU_200C_ZK=1
	fi
	elif [[ $1 == 0 ]];then                          # 若升级失败,则更新总的升级状态为“升级失败”
		TEMP_RET_UPDATE_DRU_200C_ZK=0
	fi
}

# 如果没有这两个目录就创建 HardDisk1 and HardDisk12 
if [[ ! -d "$HARDDISK1_PATH" ]];then
  mkdir "$HARDDISK1_PATH"
fi
if [[ ! -d "$HARDDISK12_PATH" ]];then
  mkdir "$HARDDISK12_PATH"
fi

# 如果没有就创建  myapp-log directory
if [[ ! -d "$LOG_PATH" ]];then
  mkdir "$LOG_PATH"
fi

#log函数,记录日志,保存在LOG_PATH='/HardDisk12/log_sys'里
LOG ( )
{
	LOG_DATE=`date '+%Y-%m-%d'`                                        #以日期命名log名称
	echo `date '+%Y-%m-%d %H:%M:%S'` $1 >> "$LOG_PATH/$LOG_DATE.txt"   #打印日期时间到日志里
	echo `date '+%Y-%m-%d %H:%M:%S'` $1                                #打印日期时间到终端
}

##########################################添加myapp版本号#################################################
                              LOG "myapp version: V2.0.0 20211102"
##########################################################################################################

# 进程是否存在
# 参数:进程名字
# 返回值:RET_EP 1 存在,0不存在
ExistProcess ( )
{
	#echo "ps -ef | grep $1 | grep -v grep"
	CHECK=`ps -ef | grep $1 | grep -v grep`  #列出所有的进程信息、再从列出项中找到包含进程名字的、grep -v 排除掉包含grep的
	                                         #因为本条指令就是包含进程名的,但我们要查找的是进程本身
	if [ -z "$CHECK" ];then                  #检查变量$CHECK是否为空,-z测试字符串是否为空
		RET_EP=0
	else
		RET_EP=1
	fi
	#echo $CHECK
}

# 两个文件是否相同
# 参数1:文件1路径
# 参数2:文件2路径
# 返回值:RET_IS_SAME_FILE,1 相同  0 不相同
IsSameFile ( )
{
	LOG "==========in IsSameFile=========="
	LOG "param1 is $1"
	LOG "param2 is $2"
	if [[ $# -lt 2 ]];then                  #检查传递给函数的参数数量是否少于2个,$# ——添加到Shell的参数个数 -lt比较运算符小于,小于2说明给的参数不够
		RET_IS_SAME_FILE=0
	fi

	FILE_DATE1=`ls -e "$1" | cut -c30-69`   #列出参数1路径下应用程序的信息,截取第30到69的字符(代码大小,最后修改日期时间)
	FILE_DATE2=`ls -e "$2" | cut -c30-69`   #列出参数2路径下应用程序的信息,截取第30到69的字符(代码大小,最后修改日期时间)
	#DATE_DIFF=$((FILE_DATE1 - FILE_DATE2))
	LOG "$FILE_DATE1"
	LOG "$FILE_DATE2"

	if [[ "$FILE_DATE1" == "$FILE_DATE2" ]];then   #比较文件大小及最后修改时间,一样则返回1,不一样则返回0
		RET_IS_SAME_FILE=1
	else
		RET_IS_SAME_FILE=0
	fi
}


# 更新文件
# 参数1 新文件路径
# 参数2 目标文件路径
# 返回值 RET_UPDATE: 0-更新失败  1-成功	2-无需更新
UpdateFile ( )
{
	IsSameFile $1 $2                                     #调用比较程序函数,一样则不需要更新
	#LOG "$1 $2 is same : $RET_IS_SAME_FILE"
	if [[ $RET_IS_SAME_FILE == 1 ]];then
		LOG "$1 文件一致,无需更新!"
		RET_UPDATE=2
	else                                                 #不一样则将参数一路径下的文件拷贝到参数二路径下文件
		cp -p "$1" "$2"
		if [[ $? == 0 ]];then                            #用来检查上一个命令执行的退出状态码是否为0
			LOG "更新文件, 成功: $2"
			RET_UPDATE=1
		else
			LOG "更新文件, 失败: $2"
			RET_UPDATE=0
		fi
	fi
}

# 杀死进程
# 参数 进程名字
KillProcess () {
echo $1
  Linux_new_id=`ps -ef | grep $1 | grep -v grep | awk '{print $1}'`
echo $Linux_new_id
 
for id in $Linux_new_id
do
    kill $id  
    echo "killed $id"  
done

}
	
main(){
		GREPRET=`grep 'sd[a-z][0-9]\? /media' /proc/mounts` #在/proc/mounts文件中查找挂载在/media目录下的块设备(通常代表U盘或硬盘分区),
															#sd[a-z][0-9]\?匹配如sda1、sdb等常见的块设备名称。
		UDISK_PATH=$(echo $GREPRET | { read UP1 UP2 UP3; echo $UP2; })
		echo $UDISK_PATH
		if [[ -e "$UDISK_PATH/$PROGRAM_NAME" ]];then
			IsSameFile "$UDISK_PATH/$PROGRAM_NAME" "$PROGRAM_PATH/$PROGRAM_NAME"
			if [ $RET_IS_SAME_FILE == 1 ];then
				LOG "DRU_200C_ZK Program need not update"
				exit 1
			else
				LOG "Check if the DRU_200C_ZK process exists?"
				ExistProcess "$PROGRAM_NAME"
				if [ $RET_EP == 1 ];then
					LOG "Check ok, quit DRU_200C_ZK program"
					KillProcess $PROGRAM_NAME
				fi
				UpdateFile "$UDISK_PATH/$PROGRAM_NAME" "$PROGRAM_PATH/$PROGRAM_NAME"
				DRU_200CUpdateStatusHandler $RET_UPDATE
				
				if [[ $TEMP_RET_UPDATE_DRU_200C_ZK == 1 ]];then
					LOG "Update DRU_200C_ZK Program, success"
					echo -e -n "\x00" > "$FILE_DOWNLOADS_VERSION"
					cd "$PROGRAM_PATH"
					"./$PROGRAM_NAME" & 					#非阻塞运行应用程序
					sleep 10s
					exit 1
				elif [[ $TEMP_RET_UPDATE_DRU_200C_ZK == 2 ]];then
					LOG "DRU_200C_ZK Program need not update"  #前面存在IsSameFile判断,实际上不存在该分支,只作为逻辑出口
					
				else
					LOG "Update DRU_200C_ZK Program, fail: copy fail"
					exit 0
				fi
			fi
		else
			LOG "DRU_200C_ZK upgrade program does not exist"
			exit 1
		fi

	
#	sleep 10s
}

main

实现效果

刚开始它会检测到版本不一样实现升级,当升级完后再次重启发现U盘里和运行的是一个版本后则无需升级了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值