部分批处理小脚本

#技巧 #shell #Linux

控制字符

颠倒文字显示顺序 \&\#8238\;

这‮个 控制字符的作‮用就是让文字在显示时顺‮序‮颠‮倒

这个控制‮字符的作用就是让文字在显示时顺序‮颠倒


#sync #rsync

利用rsync同步远程内容到本机

#!/bin/bash

# 本机存储位置
local_path=/jpdata/fb/$1

# 如果本机存储位置不存在,则创建该目录并在创建后开始同步;否则直接开始同步
ls $local_path > /dev/null 2>&1
if [ $? -gt 0 ]; then
    echo "$local_path 目录不存在,尝试新建该目录"
    mkdir -p $local_path
    if [ $? -gt 0 ]; then
        echo "$local_path 创建失败,请手动创建该目录"
        exit
    else
        echo "目录创建成功,开始同步"
        rsync -rtva --password-file=/jpdata/rsync/rsync.password [email protected]::whftpfile/projects/$1 $local_path
    fi
else
    echo "开始同步"
    rsync -rtva --password-file=/jpdata/rsync/rsync.password [email protected]::whftpfile/projects/$1 $local_path
fi

# 显示同步目录下的结果,方便复制完整路径
find $local_path -maxdepth 3 -name "*.*"

linux下快速删除空行的几种操作

grep -v '^$' file

sed '/^$/d' file

监控指定任务的定时脚本

有时有些命令执行后所需时间比较长,放着容易忘,可以利用 crontab 和邮件功能做一个提醒。

以下定时任务为当 ps 命令过滤没检测到指定关键字时表示命令执行完成或中断,可以通过 [[Linux发送邮件]] 到指定用户邮箱,并注释当前定时任务,具体注释命令可以参考[[Linux命令/sed命令–处理编辑文本文件]]

# 指定注释行数来注释定时任务
* * * * * ps -aux | grep 'str' | grep -v grep || (sed -i "1 s/^/#/" /var/spool/cron/root; echo "邮件正文" | mail -s "邮件标题" [email protected] )

# 根据任务关键字过滤来注释定时任务
* * * * * ps -aux | grep 'str' | grep -v grep || (sed -i -e "/grep/ {s/^/#/}" /var/spool/cron/root; echo "邮件正文" | mail -s "邮件标题" [email protected] )

同步并提交到git

#! /bin/bash

# 需求:有新包要发布时,通过脚本 + 发布包的路径自动将要发布的包同步至git2,并自动解压提交到gi2对应的仓库
# 1.同步发布包至git2
# 2.解析出具体的项目名
# 3.解压发布包并同步至git2对应项目的本地仓库
# 4.进行git提交
# 使用示例:./fb.sh jiaoshoujia_pt/3.9.7_1/publish/20210928_2/java # fb.sh为本脚本名称,后面的路径为测试提供的发布包路径(要去掉路径前面的“/projects/”)

# 本机存储位置
LOCAL_PATH=/jpdata/fb/$1

if [ $1 = "" ];then
    echo "待同步的目录为空,请输入正确的同步路径"
    exit
fi    

# 开始从公司服务器同步待发布的包到华为云Git2服务器
# 如果本机存储位置不存在,则创建该目录并在创建后开始同步;否则直接开始同步
ls ${LOCAL_PATH} > /dev/null 2>&1
if [ $? -gt 0 ]; then
    echo "本地 ${LOCAL_PATH} 目录不存在,尝试新建该目录"
    mkdir -p ${LOCAL_PATH}
    if [ $? -gt 0 ]; then
        echo -e "\033[31m 本地 ${LOCAL_PATH} 创建失败,请手动创建该目录 \033[0m"
        exit
    else
        echo "#################################################################################"
        echo "目录创建成功,开始同步"
        rsync -rtva --password-file=/jpdata/rsync/rsync.password [email protected]::whftpfile/projects/$1 ${LOCAL_PATH}
        echo "#################################################################################"
    fi
else
    echo "#################################################################################"
    echo "开始同步"
    rsync -rtva --password-file=/jpdata/rsync/rsync.password [email protected]::whftpfile/projects/$1 ${LOCAL_PATH}
    echo "#################################################################################"
fi


# 显示同步目录下的结果,方便复制完整路径
FILE_LIST=$(find ${LOCAL_PATH} -maxdepth 3 -name "*.*")

# 临时目录
TEMP_DIR=/tmp/git2_temp

# git commit 时间信息
TIMES=$(date +%Y%m%d-%H%M%S)

if [ ${FILE_LIST} = "" ]; then
    echo -e "\033[31m 没有可更新的包,请检查同步的路径是否正确 \033[0m"
    exit
fi

echo -e "待发布的包已同步至Git2服务器,本次即将更新的包如下:\n${FILE_LIST}"
echo "#################################################################################"

# 解析出具体的项目名和后缀
echo "开始解析出待发布包的项目名和压缩方式,解压后同步、提交至Git2的[GitLab](Git相关/GitLab%20安装记录.md)仓库"
echo "#################################################################################"

for PACKAGE_FULL_NAME in ${FILE_LIST}
do  
    ls ${TEMP_DIR} > /dev/null 2>&1
    if [ $? -gt 0 ]; then
        echo -e "临时目录 ${TEMP_DIR} 不存在,将创建该目录" && mkdir -p ${TEMP_DIR} || exit
    fi
    cd ${TEMP_DIR}
    
    # 过滤出包的后缀 gz zip war
    FITL_TYPE=$(echo ${PACKAGE_FULL_NAME} | awk -F '.' '{print $NF}')
    
    echo ${FITL_TYPE} ${PACKAGE_FULL_NAME}
    
    
    # 根据是否包含update来过滤出发布包中的项目名,因为更新包和全量包命名格式不一样,样本如下:
    # jp-jsjxz-web-1_fht_update_7100_7297_202111221051.tar.gz
    # jp-jsc-gw-core-1_update_20211122_01.zip
    # jp-thd-core-1.war
    if [[ ${PACKAGE_FULL_NAME} =~ "update" ]]; 
    then
        PROJECT_NAME=$(echo ${PACKAGE_FULL_NAME} | tr 'A-Z' 'a-z' | awk -F '/' '{print $NF}' | awk -F '_' '{print $1}')
    else
        PROJECT_NAME=$(echo ${PACKAGE_FULL_NAME} | tr 'A-Z' 'a-z' | awk -F '/' '{print $NF}' | awk -F '.' '{print $1}')
    fi
     
    # 根据不同的后缀包来进行不同的解压
    if [ ${FITL_TYPE} = 'gz' ]
    then 
        echo -e "开始解压 ${PROJECT_NAME} ,压缩方式为 ${FITL_TYPE}"
        tar -zxf ${PACKAGE_FULL_NAME} 

    elif [ ${FITL_TYPE} = 'zip' ]
    then 
        echo -e "开始解压 ${PROJECT_NAME} ,压缩方式为 ${FITL_TYPE}"
        unzip -q ${PACKAGE_FULL_NAME}
        
    elif [ ${FITL_TYPE} = 'war' ]
    then 
        echo -e "开始解压 ${PROJECT_NAME} ,压缩方式为 ${FITL_TYPE}"
        unzip -q ${PACKAGE_FULL_NAME} -d ${PROJECT_NAME}        
    fi

    rm -rf ./*.txt  # 删除打包中带的txt记录文件
    
    # 如果发布包中jp-开头的项目名不带数字则改成带数据版
    ls | grep "jp-" | grep [0-9] > /dev/null 2>&1 || mv $(ls | grep "jp-" | grep -v [0-9]) ${PROJECT_NAME}
    
    GIT_DIR=/jpdata/project/shengyijia/${PROJECT_NAME}        
    ls ${GIT_DIR}
    
    if [ $? -gt 0 ]; then
        echo -e "\033[31m ${GIT_DIR}不存在,请手动检出该项目至/jpdata/project/shengyijia/路径 \033[0m"
        cd ${TEMP_DIR} && rm -rf ./jp-* && echo 'clear temp dir'
        exit
    else
        echo "#################################################################################"
        echo -e "更新 ${PROJECT_NAME} 本地库至最新"
        cd ${GIT_DIR}
        
        while true
        do 
            git pull 
            if [ $? -eq 0 ]; then
                echo -e "${PROJECT_NAME} 本地库已更新完成"
                echo "#################################################################################"
                break;
            else
                echo -e "重新尝试更新 ${PROJECT_NAME} 本地库~~"
                sleep 3
            fi
        done
        
        echo "#################################################################################"
        echo -e "开始同步"
        echo "#################################################################################"
        
        
        # 复制解压后的内容到git2本地仓库目录进行合并、提交
        
        if [[ ${PACKAGE_FULL_NAME} =~ "update" ]]; then
            echo "update~~"
            rsync -av ${TEMP_DIR}/${PROJECT_NAME} ${GIT_DIR}/
        else
            echo "new deploy~~"
            rsync -a --delete ${TEMP_DIR}/${PROJECT_NAME} ${GIT_DIR}/
        fi
        
        echo "#################################################################################"
        echo "开始提交至Git2的GitLab仓库"
        echo "#################################################################################"
        
        # 以包名做为commit的描述信息
        git add . && git commit -m $(echo ${PACKAGE_FULL_NAME} | awk -F '/' '{print $NF}')
        # git push origin master && echo "update completed~"
        
        # 因为本地有多个仓库,提交代码切换不同仓库太快时有可能遇到HTTP 403问题,需要重试几次提交
        while true
        do 
            git push origin master
            if [ $? -eq 0 ]; then
                echo -e "\n \033[32m update completed~ \033[0m \n"
                break;
            else
                sleep 3
            fi
        done
        
        cd ${TEMP_DIR} && rm -rf ./jp-* && echo -e "\n 临时目录已清空~~ \n"
    fi

done
echo -e "\n本次更新的包全路径为:\n${FILE_LIST}\n"
echo -e "本次更新的包如下:"
echo -e "\033[32m"
echo -e "${FILE_LIST}" | awk -F '/' '{print $NF}'
echo -e "\033[0m"

Windows使用bat脚本显示本机IP

有时给人远程处理问题,需要让对方提供IP信息,对小白用户来说查IP要一步步指导,比较慢,可以将以下内容保存为.bat文件,然后执行,就会在弹出的命令行窗口显示当前的IPv4地址了。

@echo off
echo "Your Computer IP Address is:"
ipconfig | find "IPv4"
echo.
pause>nul
exit

网页内嵌PDF绕过下载限制

页面没有下载入口 打开浏览器开发者模式(F12),切换到Network,选项“fetch/XHR”,刷新页面后在新标签页打开Type为“fetch”的链接


[[vim]]快速删除一对括号

例如有如下内容,要删除整个Zstack{}的内容

Vstack{

	Zstack{
    
    	print("我竟然在互联网搜不到这个问题的解决方案“)
        
    	}
    
}

使用vim打开文件,在命令模式下,将光标移到要要删除的括号位置,输入da{,即可删除光标位置{}的所有内容。

删除小括号da(


Shell获取字符串的长度

# echo
a="abcd"
echo ${#a}

# awk后面的引号要用英文单引号
echo $a | awk '{print length($0)}'

# wc命令有两个参数可以实现
echo $a | wc -L
echo -n $a | wc -c

[[远程备份同步导入脚本]]


Shell生成UUID

cat /proc/sys/kernel/random/uuid

查找Linux/MacOS系统下的相同文件

利用相同文件的hash值相同来进行查找对比

#! /bin/bash

file_type="\(sh\|jpeg\|jpg\|png\|pdf\|psd\|doc\|docx\|xls\|xlsx\|ppt\|pptx\|mp4\|mov\|gz\|zip\|rar\|dmg\|avi\|wmv\|mpeg\|m4v\|asf\|flv\|f4v\|rmvb\gp\|vob\)"

# 对所有符合条件的文件计算hash值并记录到指定文件中
sha224sum $(find / -type f -regex ".*.${file_type}") >> hash_info.txt

# 对hash值相同的文件进行过滤并将相同的文件写入指定文件中
{
    for dup in  $(awk -F ' ' '{print $1}' hash_info.txt | sort -n |uniq -d)
    do grep ${dup} hash_info.txt
    echo "------------------------------------------"
    done
} >> dup_file.txt
rm -rf hash_info.txt

分析慢日志中是否有符合要监控的对应库慢SQL

#! /bin/bash

logfile="db-pro-slow.log-$(date +%Y%m%d)"
yestday=$(date +%F -d '-1 day')

scp [email protected]:/jpdata/data/mysql/${logfile} /tmp/

SendSussesMail () 
{
  echo "生产环境MySQL 慢查询日志见附件 $1 " | mail -s "${yestday} 生产环境慢日志" -a /tmp/${yestday}_slow_sql.tar.gz [email protected]
  find /tmp/output* /tmp/*.txt /tmp/*.gz /tmp/db-pro-slow.log-* -exec rm -rf {} \;
}

SendFailedMail ()
{
  echo "没有匹配库的慢日志,退出脚本" | mail -s "生产环境没有慢日志" [email protected]
  find /tmp/output* /tmp/*.txt /tmp/db-pro-slow.log-* -exec rm -rf {} \;
}


if [ -f /tmp/${logfile} ];then
  # cp /jpdata/data/mysql/${logfile} /tmp/
  
  cd /tmp/ || exit 1

  # 目前只需要mml_syj和mml_jsj两个库的慢日志先判断要分析的库是否有慢日志,如果没有则直接退出
  if ! grep -E '^use mml_syj|^use mml_jsj' ${logfile} > /dev/null 2>&1 ; then SendFailedMail ; exit 1; fi

  # 先创建一个空文件,用来写第一个
  echo > temp

  csplit -s -f output ${logfile} '/^use /' '{*}'
  for file in output*; do
    cat ${file} >> temp
    mv temp ${file}
    tail -n 3 ${file} > temp
    sed -i '$d' ${file}
  done
  
  # 用换行符\n做为for的分隔符
  IFS=$'\n'
  for keys in $(grep "use " ${logfile} | sort | uniq )
  do
    dbname=$(echo ${keys} | awk '{print $2}' | tr -d ';')
    
    for file in output*; do
      if grep -q "${keys}" ${file}; then
        # echo -e "写入 ${file} 日志到 ${dbname}.txt"
        cat ${file} >> $dbname.txt

        # 删除已经写入的文件,避免重复搜索
        rm -rf ${file}
      fi
    done

  done

  # 清除临时的IFS值
  unset IFS

  # 目前只分析需要mml_syj和mml_jsj两个库的慢日志

  files_with_keyword=""

  Abc ()
  {
    if [ -f "$1" ];then
      # if (grep "FROM" $1 | grep -v 'core_logs' > /dev/null 2>&1 );then
      if (grep "FROM" $1 | grep -v -E "core_logs|DELETE" > /dev/null 2>&1 );then
        files_with_keyword+="$1 "
      fi
    fi
  }

  # 目前只分析需要mml_syj和mml_jsj两个库的慢日志
  # 判断这两个库的慢日志中除了core_logs查询以外有没有其它的查询
  for a in `ls *.txt | grep -E 'mml_syj|mml_jsj'`; do
    Abc $a
  done

  if [ ! -z ${files_with_keyword} ];then
    tar czf ${yestday}_slow_sql.tar.gz ${files_with_keyword} && SendSussesMail ${yestday}_slow_sql.tar.gz 
  else
    echo "没有多的sql"
    SendFailedMail
  fi
  
else
    SendFailedMail
    exit 1
fi

从全库备份的sql中切割出每个库的部分内容

使用csplit 指定'/^USE /'做为关键字来进行分割,分割后的文件以db开头,依次增加数字编号

csplit -s -f db bak_20230614030001.sql '/^USE /' '{*}'

查看每个文件的第一行,判断文件中是哪个库的所有数据

for a in `ls db*`; do head -n 1 $a ; echo $a " --"; done

分割指定库的所有表

使用csplit 指定'/^DROP TABLE IF EXISTS /'做为关键字来进行分割,分割后的文件以table开头,依次增加数字编号

csplit -s -f table db19 '/^DROP TABLE IF EXISTS /' '{*}'

查看每个文件的第一行,判断文件中是哪个表的所有数据

for a in `ls table*`; do head -n 1 $a ; echo $a " --"; done

通过死循环反复执行指定脚本,直到正常执行完成后退出

有时候会有一些脚本或者命令因为不确定的原因会报错导致退出,又不想每镒退出后手动重新执行,可以通过以while循环命令来实现自动重试,直至成功为止

while true; do python3 type.py; if [ $? -ne 0 ]; then sleep 30; else break; fi ; done

修改Obsidian中默认的文件、图片引用格式为MarkDown通用格式

#!/bin/bash

# 定义替换图像格式的函数
replace_image_format() {
    file="$1"

    # 定义目标格式的正则表达式(包含"media/Images"的情况)
    pattern_with_path='!\[\[media/Images/([^]]+)\]\]'

    # 定义目标格式的正则表达式(不包含"media/Images"的情况)
    pattern_without_path='!\[\[([^]]+)\]\]'

    # 读取文件内容
    content=$(cat "$file")

    # 检查文件内容是否包含"media/Images",并根据情况替换图像格式
    if [[ "$content" == *"media/Images"* ]]; then
        new_content=$(echo "$content" | sed -E "s#$pattern_with_path#![](../../../media/Images/\\1)#g")
    else
        new_content=$(echo "$content" | sed -E "s#$pattern_without_path#![](../../../media/Images/\\1)#g")
    fi

    # 处理文件名中的宽度内容(如果有),并移除竖线
    new_content=$(echo "$new_content" | sed -E 's/\|([0-9]+)//g')

    # 将修改后的内容写回文件
    echo "$new_content" > "$file"
}

# 要处理的目录
target_directory="/root/fix_md"

# 查找目标目录及其子目录下的所有.md文件,并执行替换图像格式操作
find "$target_directory" -type f -name "*.md" | while read -r file; do
    replace_image_format "$file"
done

批量创建用户、加组、生成密钥并给访问指定主机的权限


groudadd dev

#! /bin/bash
for a in user1 user2; do
    useradd $a
    usermod -aG dev $a
    sudo -H -u $a bash -c 'ssh-keygen -q -N "" -t rsa -m PEM -f ~/.ssh/id_rsa'
    sudo -H -u $a bash -c "cat ~/.ssh/id_rsa.pub > ~/.ssh/authorized_keys"
    sudo -H -u $a bash -c 'ssh-copy-id -i ~/.ssh/id_rsa [email protected]'
    sudo -H -u $a bash -c 'cp ~/.ssh/id_rsa /tmp/tag_$(whoami)_id_rsa'
done
chmod 777 /tmp/*id_rsa

最后更新于