分享嵌入式中几个实用的shell脚本!

Posted 嵌入式大杂烩

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分享嵌入式中几个实用的shell脚本!相关的知识,希望对你有一定的参考价值。

工作中,为了解决一些问题或者自动处理一些繁琐的操作,我常常会写一些脚本。

每次写脚本也花了不少时间,这里记录一下几个工作中用到的脚本,之后再用到的时候找起来容易些~

推荐文章:Hello系列 | Shell编程必备简明基础知识

1、一键配置脚本

#! /bin/bash
#####################################################################
# 脚本功能:一键配置脚本
#####################################################################

echo "################################# 解压、拷贝文件 #################################"

# 解压安装文件
tar xf robot_install_files.tar
echo "tar xf robot_install_files.tar"

SRC_INSTALL_FILE_PATH=./robot_install_files
ROBOT_USR_PATH=/data

# mqtt
mv $SRC_INSTALL_FILE_PATH/mqtt $ROBOT_USR_PATH
echo "mv $SRC_INSTALL_FILE_PATH/mqtt $ROBOT_USR_PATH"

# rsync
mv $SRC_INSTALL_FILE_PATH/rsync /usr/bin
echo "mv $SRC_INSTALL_FILE_PATH/rsync /usr/bin"

# bin
SRC_BIN_DIR=$SRC_INSTALL_FILE_PATH/bin
DEST_BIN_DIR=/data/bin
if [ -d $DEST_BIN_DIR ]; then
    echo "$DEST_BIN_DIR exit, cp config"
    cp $SRC_BIN_DIR/* $DEST_BIN_DIR
else
    echo "$DEST_BIN_DIR not exit, mv config"
    mv $SRC_BIN_DIR $ROBOT_USR_PATH
fi

# cfg
SRC_CFG_DIR=$SRC_INSTALL_FILE_PATH/cfg
DEST_CFG_DIR=/data/cfg
if [ -d $DEST_CFG_DIR ]; then
    echo "$DEST_CFG_DIR exit, cp config"
    cp $SRC_CFG_DIR/* $DEST_CFG_DIR
else
    echo "$DEST_CFG_DIR not exit, mv config"
    mv $SRC_CFG_DIR $ROBOT_USR_PATH
fi

# lib
SRC_LIB_DIR=$SRC_INSTALL_FILE_PATH/lib
DEST_LIB_DIR=/data/lib
if [ -d $DEST_LIB_DIR ]; then
    echo "$DEST_LIB_DIR exit, cp config"
    cp $SRC_LIB_DIR/* $DEST_LIB_DIR
else
    echo "$DEST_LIB_DIR not exit, mv config"
    mv $SRC_LIB_DIR $ROBOT_USR_PATH
fi

chmod 777 $ROBOT_USR_PATH/bin/*

echo "################################# thttpd配置 #################################"
CURRENT_DIR=$PWD
WEB_PAGE_SRC_DIR=$SRC_INSTALL_FILE_PATH/webpage
cp $CURRENT_DIR/mqtt/lib/libmos* /lib/
mkdir -p /etc/thttpd
chmod 755 /etc/thttpd
touch /etc/thttpd/thttpd.log
chmod 666 /etc/thttpd/thttpd.log
touch /etc/thttpd/thttpd.pid
chmod 666 /etc/thttpd/thttpd.pid
mkdir -p /etc/thttpd/html
chmod 755 /etc/thttpd/html
mkdir -p /etc/thttpd/html/cgi-bin
chmod 755 /etc/thttpd/html/cgi-bin
cp $WEB_PAGE_SRC_DIR/thttpd.conf /etc
chmod 777 /etc/thttpd.conf
cp $WEB_PAGE_SRC_DIR/index.html /etc/thttpd/html
chmod 644 /etc/thttpd/html/index.html
cp -r $WEB_PAGE_SRC_DIR/jquery /etc/thttpd/html
chmod 777 /etc/thttpd/html/jquery
chmod 666 /etc/thttpd/html/jquery/*
cp $WEB_PAGE_SRC_DIR/thttpd /bin
chmod 777 /bin/thttpd
cp $WEB_PAGE_SRC_DIR/MowerHTML.cgi /etc/thttpd/html/cgi-bin
chmod 755 /etc/thttpd/html/cgi-bin/MowerHTML.cgi

echo "################################# 配置环境变量 #################################"
echo "$CURRENT_DIR"
if [ -d $ROBOT_USR_PATH/mqtt ]; then
    echo "export LD_LIBRARY_PATH=$CURRENT_DIR/mqtt/lib/:/data/lib:$LD_LIBRARY_PATH" >> /etc/profile
    echo "export PATH=$CURRENT_DIR/mqtt/bin/:$CURRENT_DIR/mqtt/sbin:$PATH" >> /etc/profile
    echo "user root" >> $CURRENT_DIR/mqtt/etc/mosquitto/mosquitto.conf
    echo "mosquitto -d -c $CURRENT_DIR/mqtt/etc/mosquitto/mosquitto.conf" >> /etc/profile
    echo "cd /data/bin/" >> /etc/profile
    echo "pwd" >> /etc/profile
    source /etc/profile
else
    echo "mqtt not exit"
fi

echo "############################### 删除解压文件 ###############################"
rm -rf /data/robot_install_files
echo "rm -rf robot_install_files"

每次装新机器都需要安装一些文件、进行一些必要配置,把这些繁琐的工作交给脚本。

2、log并自动合并

#!/bin/bash

#####################################################################
# 脚本功能:一键获取log并自动合并
#####################################################################

# 机器IP
ROBOT_IP=172.13.10.36

# PC端存log的路径
PC_SAVE_LOG_PATH=.
APP_LOG_TMP_PATH=$PC_SAVE_LOG_PATH/app_tmp_dir

# 合成的文件
APP_MERGE_LOG_FILE=$PC_SAVE_LOG_PATH/app_log_$(date +%m%d_%H%M)

# 机器log路径(不可修改!)
ROBOT_APP_LOG_PATH=/data/bin/app_log

echo "################################# 合成APP LOG文件 #################################"
# 创建app log临时文件夹
if [ -d $APP_LOG_TMP_PATH ]; then
    echo "rm -rf $APP_LOG_TMP_PATH"
    rm -rf $APP_LOG_TMP_PATH
fi
echo "create app_tmp_dir"
mkdir -p $APP_LOG_TMP_PATH

# 拉取app log文件
echo "pull robot $ROBOT_APP_LOG_PATH"
sshpass -p 1 rsync -avz --progress root@$ROBOT_IP:$ROBOT_APP_LOG_PATH/*.log $APP_LOG_TMP_PATH

# 获取LOG文件最后一次修改的时间戳
APP_LOG_FILE_LIST=($(ls $APP_LOG_TMP_PATH/*.log))
for i in "$!APP_LOG_FILE_LIST[@]";
do
    APP_LOG_FILE="$APP_LOG_TMP_PATH/$i.log"
    # echo $APP_LOG_FILE
    # echo "i = "$i
    APP_LOG_FILE_TIME_ARR[$i]=$(stat -c %Y $APP_LOG_FILE)
    APP_LOG_FILE_DATE_ARR[$i]=$(date '+%Y-%m-%d %H:%M:%S' -d @$APP_LOG_FILE_TIME_ARR[$i])
    echo $APP_LOG_FILE $APP_LOG_FILE_DATE_ARR[$i] $APP_LOG_FILE_TIME_ARR[$i]
    APP_LOG_FILE_TIME_SORT_ARR[$i]=$APP_LOG_FILE_TIME_ARR[$i]
    # echo $APP_LOG_FILE_TIME_SORT_ARR[$i]
done

# 时间戳从小到大排序
for((i = 0; i < $#APP_LOG_FILE_TIME_SORT_ARR[@]; i++))

   for((j = 0; j < $#APP_LOG_FILE_TIME_SORT_ARR[@] - 1; j++))
   
     if [[ $APP_LOG_FILE_TIME_SORT_ARR[j] -gt $APP_LOG_FILE_TIME_SORT_ARR[j+1] ]]; then
          tmp=$APP_LOG_FILE_TIME_SORT_ARR[j]
          APP_LOG_FILE_TIME_SORT_ARR[j]=$APP_LOG_FILE_TIME_SORT_ARR[j+1]
          APP_LOG_FILE_TIME_SORT_ARR[j+1]=$tmp
      fi
    

echo "app log timestamp after sort"
echo $APP_LOG_FILE_TIME_SORT_ARR[@]

# 记录时间戳从小到大的文件
for((sort_index = 0; sort_index < $#APP_LOG_FILE_TIME_SORT_ARR[@]; sort_index++))

    for((ori_index = 0; ori_index < $#APP_LOG_FILE_TIME_ARR[@]; ori_index++))
    
        # echo $ori_index
        if [ $APP_LOG_FILE_TIME_SORT_ARR[$sort_index] = $APP_LOG_FILE_TIME_ARR[$ori_index] ]; then
            APP_LOG_INDEX_ARR[$sort_index]=$ori_index
        fi
    

echo "APP_LOG_INDEX_ARR=$APP_LOG_INDEX_ARR[@] len=$#APP_LOG_INDEX_ARR[@]"

# 总app log文件合成
if [ $#APP_LOG_INDEX_ARR[@] -le 0 ]; then
    echo "app log merge error!!"
else
    touch $APP_MERGE_LOG_FILE
    for i in $!APP_LOG_INDEX_ARR[@];
    do
        $(cat $APP_LOG_TMP_PATH/$APP_LOG_INDEX_ARR[$i].log >> $APP_MERGE_LOG_FILE 2>&1)
    done
    echo "merge app_log success!! file_name: $APP_MERGE_LOG_FILE"
fi

# 删除app log临时文件
echo "clean tmp app log file"
rm -rf $APP_LOG_TMP_PATH

机器上的app的log循环存储若干份,要看完整log需要自己从机器上拷贝各log文件,并进行合并。

其中,有用到一个rsync远程同步工具,可参考往期文章:本地与远程设备之间如何有效地进行文件同步?

3、一键更新程序

#! /bin/bash
#####################################################################
# 脚本功能:一键更新程序
#####################################################################

# 1、使用wifi更新,输入命令:./push_all_pros.sh wifi
# 2、使用adb更新,输入命令:./push_all_pros.sh adb

# 机器IP
ROBOT_IP=172.13.10.36

# 源路径(PC路径)
AI_SO_LIB_SRC_PATH=./AI/data/lib
AI_CONFIG_SRC_PATH=./AI/data/config
AI_MODEL_SRC_PATH=./AI/data/model
AI_EXE_FILE_SRC_PATH=./AI/data/bin
APP_EXE_FILE_SRC_PATH=./app

# 目标路径(机器路径)
AI_SO_LIB_TARTET_PATH=/data/lib
AI_CONFIG_TARGET_PATH=/data/config
AI_MODEL_TARGET_PATH=/data/model
AI_EXE_FILE_TARGET_PATH=/data/bin
APP_EXE_FILE_TARGET_PATH=/data/bin

# 程序名称
AI_EXE_NAME=ai
APP_EXE_NAME=app

# adb传输
if [ $1 = "adb" ]; then
 # 更新AI lib files
 echo "========== AI_SO_FILE =========="
 SO_LIST=($(ls $AI_SO_LIB_SRC_PATH/*.so))
 for i in "$!SO_LIST[@]";
 do
     SO_NAME=$SO_LIST[$i]
     echo "push $SO_NAME $AI_SO_LIB_TARTET_PATH ..."
     adb push $SO_NAME $AI_SO_LIB_TARTET_PATH
 done
 echo -e "\\n"
 # 更新AI cfg files
 echo "========== AI_INI_FILE =========="
 INI_LIST=($(ls $AI_CONFIG_SRC_PATH/*.ini))
 for i in "$!INI_LIST[@]"
 do
  INI_NAME=$INI_LIST[$i]
  echo "push $INI_NAME $AI_CONFIG_TARGET_PATH ..."
  adb push $INI_NAME $AI_CONFIG_TARGET_PATH
 done
 echo -e "\\n"
 # 更新AI model files
 echo "========== AI_MODLE_FILE =========="
 MODEL_LIST=($(ls $AI_MODEL_SRC_PATH/*.rknn))
 for i in "$!MODEL_LIST[@]"
 do
  MODEL_NAME=$MODEL_LIST[$i]
  echo "push $MODEL_NAME $AI_MODEL_SRC_PATH ..."
  adb push $MODEL_NAME $AI_MODEL_TARGET_PATH
 done
 echo -e "\\n"
 # 更新AI pro
 echo "========== AI_EXE_FILE =========="
 echo "push $AI_EXE_FILE_SRC_PATH/$AI_EXE_NAME $AI_EXE_FILE_TARGET_PATH ..."
 adb push $AI_EXE_FILE_SRC_PATH/$AI_EXE_NAME $AI_EXE_FILE_TARGET_PATH
 echo -e "\\n"
 # 更新app pro
 echo "========== APP_EXE_FILE =========="
 echo "push $APP_EXE_FILE_SRC_PATH/$APP_EXE_NAME $APP_EXE_FILE_TARGET_PATH ..."
 adb push $APP_EXE_FILE_SRC_PATH/$APP_EXE_NAME $APP_EXE_FILE_TARGET_PATH
# wifi传输
elif [ $1 = "wifi" ]; then
 echo "========== AI_EXE_FILE =========="
 echo "push $AI_EXE_FILE_SRC_PATH/$AI_EXE_NAME $AI_EXE_FILE_TARGET_PATH ..."
 sshpass -p 1 scp $AI_SO_LIB_SRC_PATH/*.so root@$ROBOT_IP:$AI_SO_LIB_TARTET_PATH
 sshpass -p 1 scp $AI_CONFIG_SRC_PATH/*.ini root@$ROBOT_IP:$AI_CONFIG_TARGET_PATH
 sshpass -p 1 scp $AI_MODEL_SRC_PATH/*.rknn root@$ROBOT_IP:$AI_MODEL_TARGET_PATH
 sshpass -p 1 scp $AI_EXE_FILE_SRC_PATH/$AI_EXE_NAME root@$ROBOT_IP:$AI_EXE_FILE_TARGET_PATH
 echo "========== APP_EXE_FILE =========="
 echo "push $APP_EXE_FILE_SRC_PATH/$APP_EXE_NAME $APP_EXE_FILE_TARGET_PATH ..."
 sshpass -p 1 scp $APP_EXE_FILE_SRC_PATH/$APP_EXE_NAME root@$ROBOT_IP:$APP_EXE_FILE_TARGET_PATH
 echo -e "push all pro end!"
fi

每次发布版本,都需要更新好多文件,一个一个传有些繁琐,故写了一个一键更新脚本。可使用无线更新,也可以使用有线更新。

4、一键运行程序

#!/bin/bash

#####################################################################
# 脚本功能:一键运行所有程序
#####################################################################

# 脚本log名称
APP_SCRIPT_RUN_LOG=app_script_log

# 每次启动都先把脚本的log给删掉
if [ -f $APP_SCRIPT_RUN_LOG ]; then
 rm -f $APP_SCRIPT_RUN_LOG
fi

# 输入命令
if [ $# != 2 ] ; then 
 echo "Usage: $0 app_pro ai_pro"
 exit 1; 
fi 

# 程序路径
PROGRAM_PATH=/data/bin

# 程序名称
APP_EXE_NAME=$PROGRAM_PATH/$1
AI_EXE_NAME=$PROGRAM_PATH/$2

# 运行程序之前先清除log等数据
delete_script=delete_data.sh
if [ -f $delete_script ]; then
 echo "delete data..."
 source $delete_script
else
 echo "$delete_script not exit!!!"
fi

# 启动http服务
thttpd -D -C /etc/thttpd.conf &

# 后台运行程序
nohup $APP_EXE_NAME &
app_run_result=$(ps -ef | grep -w $APP_EXE_NAME | grep -v grep | wc -l)
if [ $app_run_result -eq 1 ]; then
 echo "app_run_result = $app_run_result, $APP_EXE_NAME run success!!" >> $APP_SCRIPT_RUN_LOG
else
 echo "app_run_result = $app_run_result, $APP_EXE_NAME run error!!" >> $APP_SCRIPT_RUN_LOG
fi

nohup $AI_EXE_NAME &
ai_run_result=$(ps -ef | grep -w $AI_EXE_NAME | grep -v grep | wc -l)
if [ $ai_run_result -eq 1 ]; then
 echo "ai_run_result = $ai_run_result, $AI_EXE_NAME run success!!" >> $APP_SCRIPT_RUN_LOG
else
 echo "ai_run_result = $ai_run_result, $AI_EXE_NAME run error!!" >> $APP_SCRIPT_RUN_LOG
fi

# 程序重复运行了,杀死所有进程,重新执行脚本
if [ $app_run_result -gt 1 -o $ai_run_result -gt 1 ]; then
 killall_script=killall_pro.sh
 if [ -f $killall_script ]; then
  echo "kill all app pros..."
  source $killall_script
 else
  echo "$killall_script not exit!!!"
 fi
 sleep 1
 source run_all_pros.sh
fi

平时开发过程中,有时候会挂着几个终端运行几个程序,有时候也需要一键后台运行所有程序。上面脚本可一键运行所有程序于后台,稍作修改可设置成开机自启动。

开机自启动相关内容可查看往期文章:干货 | 浅析程序开机自启动

5、一键杀死进程

#!/bin/bash

#####################################################################
# 脚本功能:一键杀死进程
#####################################################################

RELEASE_APP_NAME=app
RELEASE_AI_NAME=ai

release_app_run_result=$(ps -ef | grep $RELEASE_APP_NAME | grep -v grep | wc -l)
if [ $release_app_run_result -gt 0 ]; then
    killall -9 $RELEASE_APP_NAME*
 echo "kill $RELEASE_APP_NAME* success!!"
fi

release_ai_run_result=$(ps -ef | grep $RELEASE_AI_NAME | grep -v grep | wc -l)
if [ $release_ai_run_result -gt 0 ]; then
    killall -9 $RELEASE_AI_NAME*
 echo "kill $RELEASE_AI_NAME* success!!"
fi

http_run_result=$(ps -ef | grep -w thttpd | grep -v grep | wc -l)
if [ $http_run_result -gt 0 ]; then
    killall -9 thttpd
 echo "kill thttpd success!!"
fi

于上面的一键运行脚本相对应,一键杀死所有进程。

以上就是本次的分享~

温馨提示

由于微信公众号近期改变了推送规则,如果您想经常看到我们的文章,可以在每次阅读后,在页面下方点一个「赞」或「在看」,这样每次推送的文章才会第一时间出现在您的订阅列表里。

往期推荐:

Hello系列 | cmake简明基础知识

嵌入式周报 | 第 3 期

嵌入式周报 | 第 2 期

嵌入式周报 | 第 1 期

分享一个轻量级跨平台构建工具!

分享一个程序员必备的知识库系统!

Hello系列 | Shell编程必备简明基础知识

在公众号聊天界面回复1024,可获取嵌入式资源;回复 m ,可查看文章汇总。

点击阅读原文,查看更多分享。

以上是关于分享嵌入式中几个实用的shell脚本!的主要内容,如果未能解决你的问题,请参考以下文章

linux shell 脚本中几个特殊参数含义

R语言中几个小而实用的技巧

几例实用shell脚本分享

11 个非常实用的 Python 和 Shell 拿来就用脚本实例!

分享几个嵌入式 C 中的实用技巧

python中几个实用的文件操作