其他
10 个拿来就用的 Shell 脚本实例!
The following article is from 杰哥的IT之旅 Author JackTian
来自公众号:杰哥的IT之旅
脚本 1:该脚本用于读取Linux
系统/etc/passwd
文件中的所有/bin/bash
作为登录默认Shell
的用户列表,并提取每个用户的用户名。对于这些用户名进行检查,是否不等于root
和tidb
。如果用户名不等于root
和tidb
,则使用usermod
命令对该用户的默认Shell
修改为:/sbin/nologin
,它通常用于禁止用户远程登录系统。
#!/bin/bash
for user in $(cat /etc/passwd | grep /bin/bash | cut -d ":" -f 1)
do
if [ $user != "root" ] && [ $user != "tidb" ]; then
usermod -s /sbin/nologin $user
fi
done
md5_list
和md5_no_hash.txt
两个文件,然后循环读取md5_list
文件中每一行的哈希值,判断是否在md5_no_hash.txt
文件中存在。如果检查出哈希值在md5_no_hash.txt
中存在,则打印信息:MD5值 xxx 在 md5_no_hash.txt 中存在
。如果检查出哈希值在md5_no_hash.txt
中不存在,则打印信息:MD5值 xxx 在 md5_no_hash.txt 中不存在
。# 指定md5_list文件和md5_no_hash.txt文件的路径
md5_list_file="md5_list"
md5_no_hash_file="md5_no_hash.txt"
# 循环读取md5_list文件中的每一行
while IFS= read -r md5; do
# 检查md5是否在md5_no_hash.txt中
if grep -q "$md5" "$md5_no_hash_file"; then
echo "MD5值 $md5 在 $md5_no_hash_file 中存在"
else
echo "MD5值 $md5 在 $md5_no_hash_file 中不存在"
fi
done < "$md5_list_file"
IP
地址的文件,如该文件名为:mmyd
,然后对该文件里的每行IP
地址执行ping
操作,并检查丢包率。如果ping
的丢包率为:100%,则输出该IP
不可达的日志;如果ping
不存在丢包率,则输出该IP
可达的日志。# author:JackTian
# 获取当前系统时间
current_time=$(date +"%Y-%m-%d-%H:%M:%S")
# 获取开始时间戳
start_time=$(date +%s)
for i in `cat mmyd` # 这个是逐个读取该文件里的全部所列出的 IP 地址
do
ping=`ping -c 10 $i | grep loss | awk '{print $6}' | awk -F "%" '{print $1}'`
# 上面一行是对读出来的ip ping一次,看是否ping通。并取出loss的百分比的值 也就是丢包的值,看是否丢包
Packet_Loss_Rate=`ping -c 10 $i | grep loss | awk '{print $6}'`
if [ $ping -eq 100 ];then
# 比较一下,看丢包的值是不是100,如果是100就是全部丢包,那就是没ping通,那就显示 IP ping 失败了,如果不等于100的话,就ping通了,就显示 IP ping 成功了。
echo "$current_time 某某移动-活跃 IP 地址:$i ping 失败了,丢包率为:$Packet_Loss_Rate" >>/opt/jacktian/mmyd_ping.log
else
echo "$current_time 某某移动-活跃 IP 地址:$i ping 成功了!" >>/opt/jacktian/mmyd_ping.log
fi
done
# 获取结束时间戳
end_time=$(date +%s)
# 计算执行时间(秒)
execution_time_seconds=$((end_time - start_time))
# 将执行时间转换为分钟和秒
minutes=$((execution_time_seconds / 60))
seconds=$((execution_time_seconds % 60))
echo "执行完毕!该脚本执行时间共: $minutes 分钟 $seconds 秒"
Linux
系统中创建新用户,并为该用户设置密码、省份代码、目录权限以及vsftpd
服务的配置。read -p "user:" user
read -p "passd:" pass
read -p "province:" province
useradd $user -d /bigdata/sftp/province/$province/
#passwd $user
echo $pass | passwd --stdin $user
chown $user /bigdata/sftp/province/$province/ -R
chmod 750 /bigdata/sftp/province/$province/ -R
echo $user>>/etc/vsftpd/chroot_list
echo $user>>/etc/vsftpd/user_list
systemctl restart vsftpd.service
read -p "user:" user
:提示用户输入一个用户名,并将输入的值存储在变量user
中read -p "passd:" pass
:提示用户输入一个密码,并将输入的值存储在变量pass
中。注意:在输入密码时,不会显示任何字符read -p "province:" province
:提示用户输入一个省份代码,并将输入的值存储在变量province
中useradd $user -d /bigdata/sftp/province/$province/
:该命令将创建一个新用户,其用户名为之前输入的user
,其家目录为:/bigdata/sftp/province/$province/
echo $pass | passwd --stdin $user
:该命令会将之前输入的密码通过标准输入传给passwd
命令,为新创建的用户设置密码chown $user /bigdata/sftp/province/$province/ -R
:该命令将更改新创建用户成为/bigdata/sftp/province/$province/
目录及其子目录的所有者chmod 750 /bigdata/sftp/province/$province/ -R
:该命令会设置/bigdata/sftp/province/$province/
目录及其子目录的权限为:750
,也就是指:用户有读、写、执行的权限,而用户组只有读和执行的权限echo $user>>/etc/vsftpd/chroot_list
:该命令会将新创建的用户添加到vsftpd
服务的chroot
列表中。这表示当vsftpd
服务在运行时,该用户会被限制在其自己的目录中,不能访问系统的其他目录echo $user>>/etc/vsftpd/user_list
:该命令会将新创建的用户添加到vsftpd
服务的用户列表中。这表示当vsftpd
服务在运行时,这个用户可以登录并访问系统。systemctl restart vsftpd.service
:重启vsftpd
服务,使之前的所有配置生效
Linux
系统中创建新用户,并为该用户设置密码、省份代码、idcid、目录权限以及vsftpd
服务的配置。跟如上脚本 4 略有差异。read -p "user:" user
read -p "passd:" pass
read -p "province:" province
read -p "idcid:" idcid
mkdir -p /bigdata/sftp/province/$province/$idcid
useradd $user -d /bigdata/sftp/province/$province/$idcid
#passwd $user
echo $pass | passwd --stdin $user
chown $user /bigdata/sftp/province/$province/$idcid/ -R
chmod 750 /bigdata/sftp/province/$province/$idcid -R
echo $user>>/etc/vsftpd/chroot_list
echo $user>>/etc/vsftpd/user_list
systemctl restart vsftpd.service
du -sh 2023-10-*
命令,查询所有以2023-10-
开头目录的大小,并将结果输出到一个名为$province_code_file_size.txt
的文件中。执行for
循环,循环遍历所有子目录并查询每个子目录中的文件数量,然后将结果输出到一个名为$province_code_file_count.txt
的文件中。最后,脚本会返回到上级目录,以便对下一个省份编码下的文件大小及文件数量进行查询。所有的查询结果将保存在/opt/
目录下的以省份编码命名的文件中。# @Time : 2023/10/30
# @Author : jacktian
# @Desc : 这是一个适用于某台服务器循环查询特定省份、特定运营商、特定数据上报类型的文件大小及文件个数的脚本。
# 定义省份编码列表
provinces=("110000/dianxin/1024" "120000/liantong/1024" "130000/yidong/1024")
# 遍历省份编码列表
for province in "${provinces[@]}"; do
# 分割省份编码、运营商和数据上报类型
province_code=$(echo $province | cut -d'/' -f1)
operator=$(echo $province | cut -d'/' -f2)
category=$(echo $province | cut -d'/' -f3)
# 进入省份目录
cd /bigdata/sftp/province/$province_code/$operator/$category
# 执行du命令查询文件大小,并将结果输出到对应的省份编码txt文件
du -sh 2023-10-* >> /opt/"$province_code"_file_size.txt
# 执行for命令查询日期文件个数,并将结果输出到对应的省份编码txt文件
for date in $(ls -d */ | cut -d'/' -f1);
do
echo $date $(ls -1 $date | wc -l) >> /opt/"$province_code"_file_count.txt
done
# 返回上级目录
cd ..
done
# @Time : 2023/10/30
# @Author : jacktian
# @Desc : 这是一个适用于某台服务器循环查询特定省份、特定数据上报类型的文件大小及文件个数的脚本。
# 定义省份编码列表
provinces=("110000" "120000" "130000")
# 遍历省份编码列表
for province in "${provinces[@]}"; do
# 进入省份目录
cd /bigdata/sftp/province/$province/1024
# 执行du命令查询文件大小,并将结果输出到对应的省份编码txt文件
du -sh 2023-10-* >> /opt/"$province"_file_size.txt
# 执行for命令查询日期文件个数,并将结果输出到对应的省份编码txt文件
for date in $(ls -d */ | cut -d'/' -f1);
do
echo $date $(ls -1 $date | wc -l) >> /opt/"$province"_file_count.txt
done
# 返回上级目录
cd ..
done
# 获取当前日期
current_date=$(date +%Y-%m-%d)
# 第一条命令
directory_path="/bigdata/sftp/province/110000/yidong/1024/$current_date"
output_file="/opt/log_110000_yidong_$current_date.txt"
cd "$directory_path" && ls -l *.xml | awk '{print $8,$9}' | grep -v '^$' | awk -F '[/:]' '{hour=substr($1,1,2); if ((hour >= "00" && hour < "08") || (hour >= "10" && hour < "12") || (hour >= "14" && hour <= "24")) print}' >> "$output_file"
# 第二条命令
directory_path="/bigdata/sftp/province/120000/dianxin/1024/$current_date"
output_file="/opt/log_120000_dianxin_$current_date.txt"
cd "$directory_path" && ls -l *.xml | awk '{print $8,$9}' | grep -v '^$' | awk -F '[/:]' '{hour=substr($1,1,2); if ((hour >= "00" && hour < "08") || (hour >= "10" && hour < "12") || (hour >= "14" && hour <= "24")) print}' >> "$output_file"
# 第三条命令
directory_path="/bigdata/sftp/province/130000/liantong/1024/$current_date"
output_file="/opt/log_130000_liantong_$current_date.txt"
cd "$directory_path" && ls -l *.xml | awk '{print $8,$9}' | grep -v '^$' | awk -F '[/:]' '{hour=substr($1,1,2); if ((hour >= "00" && hour < "08") || (hour >= "10" && hour < "12") || (hour >= "14" && hour <= "24")) print}' >> "$output_file"
# 退出进程
exit
date
命令获取当前日期,格式为:YYYY-MM-DD
,并自定义current_date
变量。然后,自定义了一个目录路径directory_path
和输出文件output_file
。使用ls -l *.xml
列出所有以.xml
结尾的文件,通过awk '{print $8,$9}'
提取文件的修改时间和大小信息,grep -v '^$'
过滤掉空行,awk -F '[/:]' '{hour=substr($1,1,2); if ((hour >= "00" && hour < "08") || (hour >= "10" && hour < "12") || (hour >= "14" && hour <= "24")) print}'
筛选出每天的00:00-07:59、10:00-11:59、14:00-23:59
时间段内修改的文件,并输出它们的修改时间和大小信息,将结果追加到指定的输出文件中。脚本 9:该脚本主要用于监控系统资源使用情况,获取并记录了磁盘使用情况、CPU空闲情况、内存空闲情况和进程总数,并将这些打印信息输出到某个日志文件中。date=$(date +%Y-%m-%d-%H:%M:%S)
#1、打印磁盘使用情况
DISK_1=$(df -h | awk '{printf $NF} {printf "使用率:"} {print $5} '| grep appslog | grep -v 'Filesystem')
DISK_2=$(df -h | awk '{printf $NF} {printf "使用率:"} {print $5} '| grep bigdata | grep -v 'Filesystem')
DISK_3=$(df -h / | awk '{printf $NF} {printf "使用率:"} {print $5} '| grep / | grep -v 'Filesystem')
#2、打印 CPU 空闲情况
CPU=$(top -n 1 | grep Cpu | awk 'BEGIN {printf"CPU 空闲使用率:"} {print $8}')
#3、打印内存空闲情况
MEMORY=$(free -h | awk 'BEGIN {printf"内存空闲使用率:"} NR==2 {print $4}')
#4、打印进程总数
JINCHENG=$(ps aux | wc -l | awk 'BEGIN {printf"进程总数:"} {print $1}')
echo -e "\n $date\n\n $DISK_1\n\n $DISK_3\n\n $CPU\n\n $MEMORY\n\n $JINCHENG\n" >> /opt/jacktian/inspection.log
exit
done
date=$(date +%Y-%m-%d-%H:%M:%S)
:获取当前日期和时间,格式为:年-月-日-时:分:秒DISK_1、DISK_2、DISK_3
:该变量用于获取磁盘的使用情况。使用df -h
命令获取磁盘信息,然后使用awk
提取出使用率和文件系统名称。grep
用于筛选出特定名称的磁盘(如:appslog 和 bigdata)CPU
:该变量获取CPU
的空闲使用率。使用top -n 1
命令获取系统状态,然后使用grep
和awk
提取出CPU
的空闲使用率MEMORY
:该变量获取了内存的空闲使用率。使用free -h
命令获取内存信息,然后使用awk
提取出空闲内存的使用率JINCHENG
:该变量获取了系统的进程总数。使用ps aux
命令获取进程信息,然后使用wc -l
命令统计行数,即进程总数echo -e "\n $date\n\n $DISK_1\n\n $DISK_3\n\n $CPU\n\n $MEMORY\n\n $JINCHENG\n"
:这部分将上述所有的打印信息拼接在一起,并输出到日志文件中
# FTP IP 列表
FTP_IPS=("IP_1" "IP_2" "IP_3")
#企业微信机器人地址(需要根据实际机器人地址配置)
WEBHOOK_URL=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=XXX
#循环执行检测方法
while :
do
date=$(date +%Y-%m-%d-%H:%M:%S)
# 循环遍历 FTP IP 列表
for ip in "${FTP_IPS[@]}"
do
# 连接 FTP 服务器
ftp -n $ip <<EOF
# 退出 FTP 服务器
exit
EOF
# 检查上一条命令的退出状态码
if [ $? -ne 0 ];
then
# 如果退出状态码不为 0,则表示命令执行失败,发送异常的告警到企业微信机器人
curl --location --request POST ${WEBHOOK_URL} \
--header 'Content-Type: application/json' \
-d '{"msgtype": "markdown", "markdown": {"content": "'$date' FTP 访问异常:$ip"}}'
echo "$date FTP 访问异常:$ip" >>/opt/ftp_check/ftp_check.log
else
# 如果退出状态码为 0,则表示命令执行成功,不发送正常的告警到企业微信机器人
echo "$date FTP 访问正常:$ip" >>/opt/ftp_check/ftp_check.log
fi
done
exit
done
FTP_IPS
:该变量中包含了多个FTP
服务器的IP
地址WEBHOOK_URL
:该变量为企业微信机器人的地址,需要将 XXX 部分替换为实际的企业微信机器人的key
使用了 while
循环来定期执行检测。在每次循环中,将获取当前日期和时间,遍历FTP_IPS
列表。对于列表中的每个IP
地址,脚本会尝试连接到FTP
服务器如果连接命令 ftp -n $ip
执行失败,则退出状态码不为:0
,则表示FTP
访问异常。在这种情况下,脚本会发送一个异常告警到企业微信机器人,并将相关信息写入日志文件如果连接命令执行成功,退出状态码为: 0
,则表示FTP
访问正常,脚本将不发送告警信息,只是在日志中记录正常访问的信息
---END---