日常开发中,需要完成一些运维工作,需要编写Shell脚本提升自动化能力,提高效率。
1、文件批量重命名
案例描述:将指定目录下的所有.txt
文件扩展名改为.yml
。
#!/bin/bash
# 批量重命名文件扩展名
directory=$1
for file in $directory/*.txt; do
mv "$file" "${file%.txt}.yml"
done
echo "当前目录下所有.txt文件已重命名为.yml"
使用方式:
./rename_files.sh /renamepath/to/directory
2、备份数据库
案例描述:每天凌晨自动备份MySQL数据库到指定目录。
#!/bin/bash
# 自动备份MySQL数据库
backup_dir="/backup/data/mysql"
db_user="root"
db_password="password"
db_name="mydatabase"
date_str=$(date +%Y%m%d%H%M%S)
backup_file="$backup_dir/$db_name-$date_str.sql"
mysqldump -u$db_user -p$db_password $db_name > $backup_file
echo "当前数据库$db_name已备份到$backup_file"
使用方式:
在crontab -e中添加:0 0 * * * /path/to/backup_db.sh
3、查找并删除大文件
案例描述:查找并删除指定目录下大于100MB的文件。
#!/bin/bash
# 查找并删除大文件
directory=$1size_threshold=$((100 * 1024 * 1024))
# 100MB in bytes
find $directory -type f -size +$size_threshold -exec rm -f {} \;
echo "已删除$directory目录下所有大于100MB的文件"
使用方法:
./delete_large_files.sh /path/to/directory
4、清理临时文件
案例描述:每天清理指定目录下的临时文件。
#!/bin/bash
# 清理临时文件
temp_dir="/tmp"
# 删除超过7天的临时文件
find $temp_dir -type f -mtime +7 -exec rm -f {} \;
echo "已清理$temp_dir目录下超过7天的临时文件"
使用方式:
在crontab -e中添加:0 0 * * * /path/to/cleanup_temp.sh
5、发送系统状态报告
案例描述:每天发送系统状态报告(如CPU、内存使用情况)到管理员邮箱。
#!/bin/bash
# 发送系统状态报告
email="service@example.com"
report=$(free -m && df -h && uptime && vmstat 1 5 | tail -n 15)
echo "$report" | mail -s "系统状态报告" $email
使用方式:
在crontab -e中添加:0 12 * * * /path/to/send_system_report.sh(假设每天上午12点发送)
6、检查磁盘空间并发送邮件
案例描述:当磁盘空间低于某个阈值时,发送邮件警告。
#!/bin/bash
# 检查磁盘空间并发送邮件
# 阈值百分比
threshold=80
email="service@example.com"
used=$(df / | grep / | awk '{ print $5}' | sed 's/%//g')
if [ $used -ge $threshold ]; then
echo "磁盘空间警告:已使用 $used%" | mail -s "磁盘空间警告" $email
fi
使用方式:
check_disk_threshold.sh
7、检测 MySQL 服务是否存活
案例描述:检查MySQL服务是否存活
#!/bin/bash
# 检测 MySQL 服务是否存活
# host 为你需要检测的 MySQL 主机的 IP 地址,user 为 MySQL 账户名,passwd 为密码
# 这些信息需要根据实际情况修改后方可使用
host=XXX
user=XXX
passwd=XXX
mysqladmin -h '$host' -u '$user' -p'$passwd' ping &>/dev/null
if [ $? -eq 0 ]
then
echo "MySQL is UP"
else
echo "MySQL is down"
fi
8、Nginx访问日志自动按天(周、月)切割
#!/bin/bash
#nginx日志目录
LOG_DIR=/www/server/nginx/logs
#获取到上一天的时间
YESTERDAY_TIME=$(date -d "yesterday" +%F)
#归档日志取时间
LOG_MONTH_DIR=$LOG_DIR/$(date +"%Y-%m")
#归档日志的名称
LOG_FILE_LIST="access.log"
for LOG_FILE in $LOG_FILE_LIST; do
[ ! -d $LOG_MONTH_DIR ] && mkdir -p $LOG_MONTH_DIR
mv $LOG_DIR/$LOG_FILE $LOG_MONTH_DIR/${LOG_FILE}_${YESTERDAY_TIME}
done
kill -USR1 $(cat $LOG_DIR/nginx.pid)
9、监控MySQL主从同步状态是否异常脚本
#!/bin/bash
HOST=XX
USER=XX
PASSWD=XX
IO_SQL_STATUS=$(mysql -h$HOST -u$USER -p$PASSWD -e 'show slave status\G'
2>/dev/null |awk '/Slave_.*_Running:/{print $1$2}')
for i in $IO_SQL_STATUS; do
THREAD_STATUS_NAME=${i%:*}
THREAD_STATUS=${i#*:}
if [ "$THREAD_STATUS" != "Yes" ]; then
echo "Error: MySQL Master-Slave $THREAD_STATUS_NAME status is
$THREAD_STATUS!" |mail -s "Master-Slave Staus" xxx@163.com
fi
done
10、监控特定进程是否存在
#!/bin/bash
# 监控特定进程是否存在的脚本
process_name="nginx" # 要监控的进程名
while true; do
if pgrep -x "$process_name" > /dev/null; then
echo "$process_name is running."
else
echo "$process_name is not running. Starting $process_name..."
# 假设nginx的启动命令是service nginx start
service $process_name start
fi
sleep 60 # 每60秒检查一次
done
11:限制特定用户进程数量
#!/bin/bash
# 监控并重启崩溃服务的脚本
service_name="httpd" # 要监控的服务名
while true; do
if service $service_name status > /dev/null 2>&1; then
echo "$service_name is running."
else
echo "$service_name has crashed. Restarting..."
# 重启服务
service $service_name restart
fi
sleep 60 # 每60秒检查一次
done
一、文件比较运算符
1. e filename 如果 filename存在,则为真 如: [ -e /var/log/syslog ]
2. -d filename 如果 filename为目录,则为真 如: [ -d /tmp/mydir ]
3. -f filename 如果 filename为常规文件,则为真 如: [ -f /usr/bin/grep ]
4. -L filename 如果 filename为符号链接,则为真 如: [ -L /usr/bin/grep ]
5. -r filename 如果 filename可读,则为真 如: [ -r /var/log/syslog ]
6. -w filename 如果 filename可写,则为真 如: [ -w /var/mytmp.txt ]
7. -x filename 如果 filename可执行,则为真 如: [ -L /usr/bin/grep ]
8. filename1-nt filename2 如果 filename1比 filename2新,则为真 如: [
/tmp/install/etc/services -nt /etc/services ]
9. filename1-ot filename2 如果 filename1比 filename2旧,则为真 如: [
/boot/bzImage -ot arch/i386/boot/bzImage ]二、字符串比较运算符
1. -z string 如果 string长度为零,则为真 如: [ -z "$myvar" ]
2. -n string 如果 string长度非零,则为真 如: [ -n "$myvar" ]
3. string1= string2 如果 string1与 string2相同,则为真 如: ["$myvar" = "one two three"]
4. string1!= string2 如果 string1与 string2不同,则为真 如: ["$myvar" != "one two three"]三、算术比较运算符
1. num1-eq num2 等于 如: [ 3 -eq $mynum ]
2. num1-ne num2 不等于 如: [ 3 -ne $mynum ]
3. num1-lt num2 小于 如: [ 3 -lt $mynum ]
4. num1-le num2 小于或等于 如:[ 3 -le $mynum ]
5. num1-gt num2 大于 如:[ 3 -gt $mynum ]
6. num1-ge num2 大于或等于 如: [ 3 -ge $mynum ]
如何在Shell脚本中输出日志信息
1、方法1:使用echo命令打印日志
echo "This is a log message"
2、方法2:使用变量和echo命令打印日志
log_message="This is a log message"
echo $log_message
3、方式3:将日志输出到文件中
log_message="This is a log message"
log_file="log.txt"
echo $log_message >> $log_file
样例如下:
function loginfo() { echo "[ INFO $(date '+%Y-%m-%d %H:%M:%S')] [ $1 ]" }
loginfo "Step1: aligning sequence data" sleep 5 # 等待5秒,避免两次loginfo的时间一样
loginfo "Step2: calling variants"
# 示例输出: # [ INFO 2024-11-08 19:22:15] [ Step1: aligning sequence data ] # [ INFO 2024-11-08 19:22:20] [ Step2: calling variants ]
RPM包常用
使用 rpm -qi
过滤安装日期
rpm -qi kernel | grep "Install Date"
# 输出示例:Install Date: Sun 10 Jul 2022 01:46:04 PM CST
基础安装命令格式
sudo rpm -ivh package_name.rpm # 标准安装命令
-i:表示安装操作(install)14
-v:显示详细安装过程(verbose)14
-h:以 # 符号显示进度条(hash marks)45
关键选项
--test:
rpm -ivh --test package.rpm
--nodeps:
忽略依赖强制安装(可能导致软件无法运行
rpm -ivh --nodeps package.rpm
--force:
强制覆盖安装(即使已存在相同版本
rpm -ivh --force package.rpm
--replacepkgs:
重新安装已存在的包(修复文件丢失或损坏
典型安装场景如下:
标准安装:
sudo rpm -ivh httpd-2.4.6.rpm
输出进度条和详细日志
强制重装损坏包
sudo rpm -ivh --replacepkgs httpd-2.4.6.rpm
忽略依赖安装(紧急调试)
sudo rpm -ivh --nodeps mysql.rpm
卸载流程如下:
️基础卸载命令:
rpm -e <软件包名> # 包名需完整(不含版本号和扩展名)
sudo rpm -e firefox-115.10.0-1.el7.x86_64
核心选项如下:
--test(模拟卸载):
检查依赖冲突但不实际删除,用于安全预检:
rpm -e --test package_name
--nodeps(忽略依赖):
强制卸载,无视其他软件包的依赖关系(高危操作):
rpm -e --nodeps corrupted_package # 仅限紧急修复
--force(强制覆盖):
通常与 --nodeps 联用,应对极端情况(如包损坏无法正常卸载):
rpm -e --force --nodeps package_name
推荐卸载流程:
查询精准包名:
rpm -qa | grep httpd # 输出示例:httpd-2.4.6-97.el7.x86_64
模拟卸载测试:
sudo rpm -e --test httpd-2.4.6-97.el7.x86_64
正式卸载:
sudo rpm -e httpd-2.4.6-97.el7.x86_64
反查文件所属包:
卸载前可通过文件路径定位包名:
rpm -qf /usr/bin/firefox # 输出:firefox-115.10.0-1.el7.x86_64
查看卸载详情:
添加 -v 参数显示详细过程:
sudo rpm -ev package_name
【附录Shell编程基础点】
1、Shell变量
1.1 用户自定义变量
变量名 描述 示例
USER_NAME 用户定义变量
USER_NAME="liyb"
FILE_PATH 用户定义变量
FILE_PATH="/home/user/file.txt"
1.2 环境变量
变量名 描述 示例 HOME 当前用户的家目录 echo $HOME PATH 系统可执行文件路径 echo $PATH USER 当前用户名 echo $USER SHELL 当前使用的shell程序 echo $SHELL PWD 当前工作目录 echo $PWD LANG 系统的语言和地区设置 echo $LANG HOSTNAME 当前主机名 echo $HOSTNAME
1.3 特殊变量
变量名 描述 示例 $0 脚本的名称 echo $0 — 输出脚本文件名 2... 脚本传递的参数 echo 2 — 输出第一个和第二个参数 $# 脚本传递的参数个数 echo $# — 输出参数个数 $@ 所有传递给脚本的参数(保留空格) echo "$@" — 输出所有参数 $* 所有传递给脚本的参数(作为一个字符串) echo "$*" — 输出所有参数(空格分隔) $? 上一个命令的退出状态码 echo $? $$ 当前脚本的进程 ID echo $$ $! 最近在后台运行的命令的进程 ID echo $!
1.4 数组变量
变量名 描述 示例 fruits 定义一个数组变量 fruits=("Apple" "Banana" "Cherry") ${fruits[0]} 访问数组中的第一个元素 echo ${fruits[0]} ${#fruits[@]} 获取数组的长度 echo ${#fruits[@]} ${fruits[@]} 打印数组中的所有元素 echo ${fruits[@]}
2、文件测试表达式
[ <表达式> ]
操作符 描述 示例 -e 检测文件是否存在 [ -e file ] -f 检测是否为普通文件 [ -f file ] -d 检测是否为目录 [ -d directory ] -L 检测是否为符号链接 [ -L link ] -r 检测文件是否可读 [ -r file ] -w 检测文件是否可写 [ -w file ] -x 检测文件是否可执行 [ -x file ] -s 检测文件是否非空 [ -s file ] -z 检测字符串是否为空 [ -z string ] -b 检测是否为块设备 [ -b file ]
操作符 描述 示例 -eq 等于 [ "b" ] -ne 不等于 [ "b" ] -lt 小于 [ "b" ] -le 小于或等于 [ "b" ] -gt 大于 [ "b" ] -ge 大于或等于 [ "b" ]