Shell常用脚本
[root@nginx ~]# sh /etc/scripts/process.sh
#!/bin/bash FILENAME=`basename $0 .sh` #获取脚本文件名称,不包含.sh后缀 FILEPATH=`dirname $0` echo "PID of this script: $$" #($$)查看当前脚本的进程ID echo "PPID of this script: $PPID" #($PPID)查看当前脚本父进程的进程ID echo "UID of this script: $UID" #($UID)查看用户的UID echo $$ >$FILEPATH/$FILENAME.pid # 保存脚本进程号到文件 echo "当前是第$LINENO行" #$LINENO获取当前行号 echo "文件名不包含.sh: $FILENAME" #脚本文件名 echo "文件路径: $FILEPATH" #脚本路径
[root@nginx ~]# sh /etc/scripts/datatime.sh
#!/bin/bash # 查看所有时区名称(tzselect:选择时区) # timedatectl list-timezones # 获取UTC时间 date -u '+%Y-%m-%dT%H:%M:%SZ' # 转换UTC时间格式为北京时间 date -d "2024-10-22T07:23:05Z" '+%Y-%m-%d %H:%M:%S' # 获取秒级时间戳 timestamp=$(date +%s) # 获取毫秒级时间戳 timestamp_ms=$(date +%s%3N) # 毫秒和秒转换 # timestamp=$((timestamp_ms / 1000)) # 获取utc时间戳 timestamp=$(date -u +%s) # 将时间戳转换为utc时间 date -u -d @"$timestamp" '+%Y-%m-%dT%H:%M:%SZ' # 将时间戳转换为北京时间 beijing_time=$(TZ='Asia/Shanghai' date -d @"$timestamp" '+%Y-%m-%d %H:%M:%S') echo $beijing_time
[root@web01 scripts]# cat ping.sh #并发执行ping(快速执行加{ }&)
#!/bin/bash for n in {1..254};do { ping -c 1 10.0.0.$n &>/dev/null if [ $? -eq 0 ];then echo "10.0.0.$n" >>/tmp/cunhuo.log else echo "10.0.0.$n" >>/tmp/dead.log fi }& done wait #wait等待前面的后台任务全部完成才往下执行 echo "hello world"
[root@web01 scripts]# cat iptables.sh #自动封IP
#!/bin/bash . /etc/init.d/functions if [ $UID -ne 0 ];then echo "Please use root run scription!!!!!" exit 10 fi while true do awk '{print $1}' /application/nginx/logs/access.log|sort -n -r|uniq -c >/tmp/ip.txt while read LINE do IP=${LINE#* } COUNT=${LINE%% *} ADD_IP=$(iptables -nL|egrep $IP|wc -l) IPTABLES(){ if [ "$COUNT" -gt 5 -a $ADD_IP -eq 0 ];then iptables -I INPUT -s $IP -j DROP action "$IP is dropped!!!!!!" /bin/true elif [ $COUNT -lt 5 ];then iptables -D INPUT -s $IP -j DROP 2>/dev/null fi } IPTABLES done </tmp/ip.txt sleep 60 done
[root@db02 3306]# cat fenku.sh # Mysql分库备份
#!/bin/bash port=3306 socket=/data/${port}/mysql.sock CmdPath="/application/mysql/bin" MysqlCmd="mysql -S $socket" MysqlDump="mysqldump -S $socket" DataPath=/data/backup [ -d $DataPath ] || mkdir $DataPath -p for dbname in `$CmdPath/$MysqlCmd -e "show databases;"|sed 1d|grep -v "_schema"` do $CmdPath/$MysqlDump -B --master-data=2 $dbname|gzip >$DataPath/${dbname}_$(date +%F).sql.gz done
[root@web01 scripts]# cat md5sum.sh
#!/bin/sh array=( 21029299 00205d1c a3da1677 1f6d12dd 890684b ) Path=/tmp/md5.txt funGetMd5() { > $Path for ((Num=0;Num<=32767;Num++)) do { Stat=$(echo $Num|md5sum) echo "$Stat $Num" >> $Path }& done } funFindMd5() { word=$(echo "${array[@]}"|sed -r 's# |\n#|#g') grep -E "$word" $Path } funcMain(){ funGetMd5 funFindMd5 } funcMain
[root@web01 scripts]# cat arr3.sh
#!/bin/sh . /etc/init.d/functions array=( http://blog.oldboyedu.com http://blog.etiantian.org http://oldboy.blog.51cto.com http://10.0.0.7 ) function wait(){ echo -n "Start Curl_check" for n in {1..3} do echo -n " ." sleep 1 if [ $i -eq 4 ];then echo -e "\t" action "Curl_check is start!!!!!!" /bin/true fi done } function check_url(){ wget -o /dev/null --spider -T 10 --tries=1 $1 if [ $? -eq 0 ];then action "$1 is ok" /bin/true else action "$1 is no" /bin/false fi } function main(){ wait for((i=0;i<${#array[*]};i++)) do check_url ${array[i]} sleep 1 done } main
[root@nginx ~]# cat func.sh $1
#!/bin/bash . /etc/init.d/functions function name() { if [ -z $1 ];then echo "Usg:sh $0 [ip/domain]" return 1 else ping -c 3 $1 >/dev/null if [ $? -eq 0 ];then echo "up" else echo "down" return 2 fi fi } result=$(name $1) #取函数的运行结果,以及向函数里传参 echo $? #取函数的return值 if [ "$result" == "down" ];then /sbin/ifdown eth1 >/dev/null action "eth1 is down" /bin/true elif [ "$result" == "up" ];then /sbin/ifup eth1 >/dev/null action "eth1 is up" /bin/true else echo $result fi
[root@nginx ~]# cat menu.sh #打印菜单脚本
#!/bin/sh clear echo -e "\n\n\t\t\tScripts admin menu" echo -e "\n\t\t++++++++++++++++++++++++++++\n" echo -e "\t\t1. Install Apche" echo -e "\t\t2. Install PHP" echo -e "\t\t3. Install Mysql" echo -e "\n\t\t++++++++++++++++++++++++++++" echo -en "\n\t\t Please enter Install option: " read -t 5 -n 1 NUM case $NUM in 1) echo -e "\n\nInstall Apple\n" ;; 2) echo -e "\n\nInstall PHP\n" ;; 3) echo -e "\n\nInstall Mysql\n" ;; *) echo -e "\n\n\tUsge: Enter 1|2|3\n" esac
[root@nginx ~]# cat captrue.sh #自动抓包脚本
#!/bin/bash n=1 while true;do tcpdumpid=`ps aux | grep tcpdump | awk '/^tcpdump/{print $2}'` curl 172.30.3.198:6011 &>/dev/null if [ $? -ne 0 ];then echo "$n `date +"%Y-%m-%d %T"` ---curl 172.30.3.198 false..." >>./status_error.log num=`ps aux | grep tcpdump| wc -l` if [ $num -eq 1 ];then tcpdump src host 172.30.4.152 and dst host 172.30.3.198 -w ./server_152.cap & fi else kill $tcpdumpid >/dev/null 2>&1 [ -f ./server_152.cap ] && mv ./server_152.cap ./server_$(date +%F-%T)_152.cap echo "$n `date +"%Y-%m-%d %T"` ---curl 172.30.3.198 ok..." >>./status.log fi ((n++)) sleep 2 done
[root@localhost ~]# cat clearlog.sh # 清理指定月份之前的日志
#!/bin/bash month=$(date +%m) if [ $month -gt 3 ];then let max_month=month-3 if [ $max_month -lt 10 ];then num=0$max_month else num=$max_month fi for m in `seq -s ' ' -w 1 $num`; do if [ -d $m ];then rm -rf $m echo $(date +%F" "%T) 清理$m月日志目录 >>/var/log/clean.log fi done fi
[root@localhost ~]# cat test.sh #打印99乘法表
#!/bin/bash for i in `seq 9` do for j in `seq $i` do [ $[i*j] -eq 6 ] || [ $[i*j] -eq 8 ] && [ $j -ne 1 ] && echo -n "$j*$i=$[i*j] " || echo -n "$j*$i=$[i*j] " done echo done
Shell并发脚本
#!/bin/bash # 最大并发数 max_jobs=3 # 计数器 count=0 run_task() { sleep "$1" echo "Task with sleep $1 seconds completed." } for i in {1..10}; do # 启动任务并放入后台 run_task $((RANDOM % 5 + 1)) & # 递增计数器 ((count++)) # 控制最大并发数 if [ "$count" -ge "$max_jobs" ]; then # 等待任一后台进程完成,有些shell版本不支持-n选项 wait -n # 递减计数器 ((count--)) fi done # 等待最后的后台进程完成 wait echo "All tasks are completed."
Shell逐行读取文件
# 方法一,指定换行符读取: #!/bin/bash IFS="\n" for LINE in `cat /etc/passwd` do echo $LINE done # 方法二,使用管道符将前面命令的输出传递给read处理: echo -e "line1 hello world\nline2 this test" | while read LINE;do echo "$LINE" && sleep 1;done # 以空格为分隔符,read将读取的第一部分赋值给变量VAR1,第二部分赋值给变量VAR2,第三部分赋值给变量VAR3 # -r 选项表示原样读取,不解析反斜杠,保持输入中的特殊字符的原始形式,不进行转义处理 echo -e "line1 hello world\nline2 this test" | while read -r VAR1 VAR2 VAR3;do echo "$VAR1--$VAR2--$VAR3";done # 方法三,用read读取文件重定向: # while read LINE;do echo $LINE && sleep 1;done < /etc/passwd #!/bin/bash while read LINE do echo $LINE && sleep 1 done < /etc/passwd
[root@localhost ~]# seq -s ' ' -w 1 05 #-s:指定分隔符,默认分割符为'\n',-w 1 05:从1到5 01 02 03 04 05 [root@localhost ~]# date +%Y/%m/%d" "%H:%M:%S 2023/05/17 10:20:47 [root@localhost ~]# date +%F" "%T 2023-05-17 10:20:38 [root@localhost ~]# useradd -M -U -s /sbin/nologin user1 #添加用户和组,组名同用户名;-M,不创建用户家目录 [root@localhost ~]# echo '123456' | passwd --stdin user1 #设置用户密码
检查k8s pod状态并将结果推送到Prometheus pushGateway
#!/bin/bash # 检查k8s pod状态并将结果推送到Prometheus pushGateway # kubectl get pod | awk 'NR>1{if($3=="Running"){printf "{\"module\":\"%s\",\"status\":\"正常\"} ",$1}else{printf "{\"module\":\"%s\",\"status\":\"异常\"} ",$1}}' jobName="K8S_Pod状态检查" instanceName="XXXXXX" pushGatewayAddress="http://x.x.x.x:30005/metrics/job/${jobName}/instance/${instanceName}" checkres=$(kubectl get pod -o wide | awk 'NR>1{if($3=="Running" || $3=="Completed"){printf "check_node_pod{pod=\"%s\",status=\""$3"\",nodename=\""$7"\"} 1\n",$1}else{printf "check_node_pod{pod=\"%s\",status=\""$3"\",nodename=\""$7"\"} 0\n",$1}}') cat <<EOF | curl --data-binary @- ${pushGatewayAddress} # TYPE check_node_pod gauge # HELP check_node_pod 1->success 0->failure $checkres EOF checkres=$(kubectl get pod -o wide | awk 'NR>1{split($1,arr,"-");if(length(arr)<3){res=arr[1]}else{res=arr[1]"-"arr[2]};if($3=="Running" || $3=="Completed"){printf "check_node_pod{pod=\"%s\",status=\""$3"\",nodename=\""$7"\"} 1\n",res}else if(res!="chrony" && $3!="Running"){printf "check_node_pod{pod=\"%s\",status=\""$3"\",nodename=\""$7"\"} 0\n",res}}') cat <<EOF | curl --data-binary @- ${pushGatewayAddress} # TYPE check_node_pod gauge # HELP check_node_pod 1->success 0->failure $checkres EOF
read -p 接提示语句
-t 3 超时设置(单位为秒)
-n 3 允许输入的最大字符串个数,大于3个直接退出
-s 隐藏输入的字符串
while循环的特长是执行守护进程,以及实现我们希望循环不退出持续执行的应用,擅长用于频率小于1分钟循环处理,其他的while循环几乎都可以被for循环取代
if语句、for语句最常用,其次while(守护进程),case(服务启动脚本)
sleep默认单位秒(s),usleep默认单位微秒(μs)
标准输入stdin,标准输出stdout和标准错误stderr,三个系统文件的文件描述符分别为0,1和2。所以2>&1的意思就是将标准错误也输出到标准输出当中
Ubuntu中编写脚本时报错 let: not found,原因为在Ubuntu中/bin/sh链接默认指向的是dash shell,dash是一个小巧的shell,而dash shell不支持++运算和let命令
解决办法:
1、直接指明使用bash shell
2、sudo dpkg-reconfigure dash 选择 "否", 表示用bash代替dash
参考链接:
https://blog.51cto.com/cuimk/1347743 # iptables交互脚本
https://segmentfault.com/a/1190000009745139 # shell分析日志文件
https://github.com/sqshq/sampler # Linux监控工具sampler
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术