Shell脚本技巧与实例

admin
2025-10-27 / 0 评论 / 3 阅读 / 正在检测是否收录...

66d3bd82a1ca1.png



Shell教程:http://c.biancheng.net/view/743.html

shell脚本检查web:

https://www.shellcheck.net 需要翻墙

===================================

判断目录并创建


if [ ! -d "/data/" ];then
mkdir /data
else
echo "文件夹已经存在"
fi

==================================

找出日志并删除


time find /root/test -type f -name *.log -exec rm -f {} \;
time find /root/test -type f -name *.log -exec rm -f {} \;


找出5天前的日志然后删除:

cat > /etc/cron.weekly/clear_log.sh << EOF
#!/usr/bin/env bash 
location="/opt/dmeeting/dm-project/logs"
find \$location -mtime +5 -type f -name *.log.gz -exec rm -f {} \;
EOF

chmod +x /etc/cron.weekly/clear_log.sh

当在cat EOF内写脚本有用$时 需要转移符\


找出某个目录下所有log文件并清空
for i in find /www/wwwlogs/pm2 -name "*.log"; do cat /dev/null >$i; done

找出文件并删除
find . -mtime +5 -name '*.exe' -type f -print -exec rm -rf {} \;
"." 表示从当前目录开始递归查找
print 打印出文件名

================================

获取日期:


获取今天时期:
date +%Y%m%ddate +%F 或 $(date +%y%m%d)
注意:date后面有空格

命令输出结果如下:

  1. [root@centi-C sh]# date +%Y%m%d
  2. 20120727
  3. [root@centi-C sh]# date +%F
  4. 2012-07-27
  5. [root@centi-C sh]# date +%y%m%d
  6. 120727

================================

数据库备份:


#!/bin/bash
DATE=$(date +%Y%m%d-%H:%M)
DES=/config/database-backup
MYSQL_U="root"
MYSQL_P="xxxxx"
MYSQL_H="127.0.0.1"
if [ ! -d "$DES" ];then
mkdir -p "$DES"
fi
/usr/bin/mysqldump -u$MYSQL_U -p$MYSQL_P -h $MYSQL_H --all-databases>"$DES/${DATE}.sql"
find $DES -name "*.sql" -mtime +7 -exec rm -rf {} \;

然后写个计划任务调用:
crontab -l
0 /2 /bin/bash /config/back_cloudstack_mariadb.sh >/dev/null 2>&1

=============================

脚本检查mysql运行状态


#!/usr/bin/env bash
port=$(netstat -nlt|grep -c 3306)
process=$(ps -ef |grep mysql|grep -v grep |wc -l)
if [ "$port" -eq 1 ] && [ "$process" -eq 2 ]
then
 echo "MySQL is running"
else
 pkill mysql
 systemctl start mysql
fi

或者

#!/bin/bash
mysql -uroot -p123456 -e "select version();" &>/dev/null
if [ $? -ne 0 ]
then
 /etc/init.d/mysqld start
else
 echo "MySQL is running"
fi

=============================

写一个脚本,ping本网段,把能通的IP和不通IP各输出一个文本


#!/bin/bash
ip="192.168.119."
for i in {1..254}
do
ping -c 2 $ip$i |grep -q "ttl=" && echo "$ip$i" >> yes.txt ||echo "$ip$i" >> no.txt &
done 
#!/bin/bash
for i in `ls ./*.tar.gz`
do
tar -zxvf $i >/dev/null
done

=============================

获取当前服务器ip地址:


Server_IP=`ip addr | grep 'state UP' -A2 | grep inet | egrep -v '(127.0.0.1|inet6|docker)' | awk '{print $2}' | tr -d "addr:" | head -n 1 | cut -d / -f1`

或者

/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"

===================================

for循环执行实例


#!/bin/bash
for ((i = 19051; i <= 19100; i++))
do 
 echo "bsp -p $i -P `openssl rand -base64 6` -s 100 -a -A -j"
done 

===================================

批量免密shell脚本


免密脚本,涉及2个文件,batchSendKey.sh是脚本逻辑,hostlist.txt是要同步密钥的主机列表(也可以提前设置环境变量 打印出来 或者 传入参数如$1)

#!/bin/bash
if [ ! -f ~/.ssh/id_rsa ];then
 ssh-keygen -t rsa
else
 echo "id_rsa has created ..."
fi

while read line
 do
 user="root"
 ip=`echo $line | cut -d " " -f 1`
 passwd="root用户登录密码"
 expect <
 set timeout 10
 spawn ssh-copy-id -i /root/.ssh/id_rsa.pub $user@$ip
 expect {
 "yes/no" { send "yes\n";exp_continue }
 "password" { send "$passwd\n" }
 }
 expect "password" { send "$passwd\n" }
EOF
 done < hostlist.txt

hostlist.txt示例如下:
192.168.0.1
192.168.0.2

====================================

shell 函数使用


function auto_ssh ()
{
while read line
 do
 user="root"
 ip=`echo $line | cut -d " " -f 1`
 passwd="Home7*9)"
 expect <
 set timeout 10
 spawn ssh-copy-id -i /root/.ssh/id_rsa.pub $user@$ip
 expect {
 "yes/no" { send "yes\n";exp_continue }
 "password" { send "$passwd\n" }
 }
 expect "password" { send "$passwd\n" }
EOF
 done < ` echo "$MASTER1\n$MASTER2\n$MASTER3\n$NODE1\n$NODE2\n$NODE3\n" >> hostlist.txt `
}

if [ "$(hostname)" = "$HOSTNAME_m1" ]; then
 [ ! -f /root/.ssh/id_rsa.pub ] && ssh-keygen -t rsa -p '' &>/dev/null
 auto_ssh # 直接引入函数
 else
 echo "非$HOSTNAME_M1不做免密配置"
fi

====================================

设置动态变量:


#!/bin/bash
if [ $(hostname) != 'localhost.localdomain' ]
 then
 agenthostname=$(hostname)
else
 agenthostname=$( ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:" )
fi
echo uuu=$agenthostname

===================================

简单For循环 curl do后面加{}& 表示多线程并行


for((i=1;i<=202;i++));do echo [$i] ; curl -v https://news.wh-djz.com/api/news/recommend/list ; done


for((i=1;i<=202;i++));do { echo [$i] ; curl -v https://news.wh-djz.com/api/news/recommend/list ; }& done

=================================

shell中for循环遍历目录下所有文件


for file in "$directory"/*;  do
或者
cd DIRNAME 
for file in `ls . ` ; do 

常用在for循环
[root@slave ~]# for i in {1..10};do echo $i;done
1-10
[root@slave ~]# for i in `seq -w -s ' ' 1 10`; do echo $i;done
01-10

如果for循环的结尾是变量
for i in `seq 1 $end`; do echo $i; done

如果for循环的开始和结尾都是变量
for i in `eval echo {$start..$end}`; do echo $i; done
扩展
for ((i=0;i<$end;i++)) do echo $i; done

=================================

判断一个变量的值在一个区间内


比如判断a是否在1~10范围内,if(a>=1 && a<=10)

while true;do
    #获取当前时间,格式是时分,例如当前是上午8:50,hh=850
    hh=`date '+%H%M'`
    #早上7.30--7.45 执行自动做早餐的任务
    if [ $hh -ge 730 -a $hh -le 745 ]
    then
        echo " Morning -- Automatic breakfast "
    #中午11.52--12.15 执行做饭任务
    elif [ $hh -ge 1152 -a $hh -le 1215 ]
    then
        echo " Lunch time -- Cook "
    #下午17:23--17.40 执行自动浇花任务
    elif [ $hh -ge 1723 -a $hh -le 1740 ]
    then
        echo "night -- Automatic watering"
    #不适合适的时间,不做什么
    else
        echo "$hh Not within time "
    fi
    sleep 5 #休息5s
    out_time=`date '+%Y-%m-%d-%H:%M'`  #格式:2019-04-24-21:26
    echo "$out_time"
done

-a 与&& 一样都是或与的意思


实例:

qy() {
           for i in `eval echo {$start_day..$end_day}`; do
           #echo $i
           sum_qy=$(cat /data/logs/prod-apisix/access.log.$last_month_year-$last_month-$i | grep api.napp.qiyitianbao.com | grep -oE '"http_x_forwarded_for":"[^"]+"' | cut -d ":" -f 2 | sort -u | grep -v 180.165.182.167 | wc -l) ;
           #echo $sum_qy
           total_sum_qy=$((total_sum_qy + sum_qy))
           done;
}

================================

用Shell脚本打印无序序列的示例:


生成随机数序列
numbers=(3 7 2 9 4 1 6 8 5)


打印序列
for num in "${numbers[@]}"
do

echo $num

done

==================================

利用ssh私钥批量登录服务器并且执行脚本:


#!/bin/bash
服务器列表,每行一个服务器地址
servers=("server1" "server2" "server3")
SSH私钥文件路径
private_key_path="/path/to/your/private/key.pem"
远程执行的脚本路径
remote_script_path="/path/to/kui.sh"

循环遍历服务器列表

for server in "${servers[@]}"; do
    echo "Connecting to $server..."
    使用ssh密钥进行登录并执行脚本
    ssh -i "$private_key_path" "$server" "bash -s" < "$remote_script_path"
    检查ssh命令的退出状态
    if [ $? -eq 0 ]; then
        echo "Script executed successfully on $server."
    else
        echo "Error executing script on $server."
    fi
done



0

评论 (0)

取消