鸿 网 互 联 www.68idc.cn

当前位置 : 服务器租用 > 服务器相关 > linux > >

100个shell脚本【持续更新】推荐

来源:互联网 作者:佚名 时间:2018-03-08 10:56
本文用于记录学习和日常中使用shell写过的脚本 【脚本1】 打印等腰三角形、直角三角形、倒直角三角形、菱形 #!/bin/bash# 等腰三角形read -p "Please input the length: " nfor i in `seq 1 $n` for ((j=$n;j j--)) echo -n " " done for m in `seq 1 $i` ec

本文用于记录学习和日常中使用shell写过的脚本

【脚本1】
打印等腰三角形、直角三角形、倒直角三角形、菱形

#!/bin/bash
# 等腰三角形
read -p "Please input the length: " n
for i in `seq 1 $n`
 for ((j=$n;j j--))
 echo -n " "
 done
 for m in `seq 1 $i`
 echo -n "* "
 done
 echo 
# 倒直角三角形
read -p "Please input the length: " len
for i in `seq 1 $len`
 for j in `seq $i $len`
 echo -n "* "
 done
 echo
# 直角三角形
read -p "Please input the length: " len
for i in `seq 1 $len`
 for((j=1;j j++))
 echo -n "* "
 done
 echo
read -p "Please input the length: " n
for i in `seq 1 $n`
 for ((j=$n;j j--))
 echo -n " "
 done
 for m in `seq 1 $i`
 echo -n "* "
 done
 echo 
for i in `seq 1 $n`
 for((j=1;j j++))
 echo -n " "
 done
 for((k=$i;k =$len-1;k++))
 echo -n "* "
 done
 echo 
done

br

【脚本2】
根据以下要求截取出字符串中的字符:字符串 var=http://www.aaa.com/root/123.htm

1.取出www.aaa.com/root/123.htm

2.取出123.htm

3.取出http://www.aaa.com/root

4.取出http:

5.取出http://

6.取出www.aaa.com/root/123.htm

7.取出123

8.取出123.htm

#!/bin/bash
var="http://www.aaa.com/root/123.htm"
echo $var |awk -F '//' '{print $2}'
echo $var |awk -F '/' '{print $5}'
echo $var |grep -o 'http.*root'
echo $var |awk -F '/' '{print $1}'
echo $var |grep -o 'http://'
echo $var |grep -o 'www.*htm'
echo $var |grep -o '123'
echo $var |grep -o '123.htm'

br

【脚本3】
emm。。这个脚本是因为tomcat没有自带的能够给service开机启动的脚本,我就琢磨着自己写了一个简单的启动脚本,如下:

#!/bin/bash
# chkconfig:2345 64 36
# description: Tomcat start/stop/restart script.
### BEGIN INIT INFO
# Provides: tomcat
# Required-Start: 
# Should-Start: 
# Required-Stop: 
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start and stop Tomcat
# Description: Tomcat Service start restart stop script
### END INIT INFO
##Written by zero.##
JAVA_HOME=/usr/local/jdk1.8/
JAVA_BIN=/usr/local/jdk1.8/bin
JRE_HOME=/usr/local/jdk1.8/jre
PATH=$PATH:/usr/local/jdk1.8/bin:/usr/local/jdk1.8/jre/bin
CLASSPATH=/usr/local/jdk1.8/jre/lib:/usr/local/jdk1.8/lib:/usr/local/jdk1.8/jre/lib/charsets.jar
TOMCAT_BIN=/usr/local/tomcat/bin
RETVAL=0
prog="Tomcat"
start()
 echo "Starting $prog......"
 /bin/bash $TOMCAT_BIN/startup.sh
 RETVAL=$?
 return $RETVAL
stop()
 echo "Stopping $prog......"
 /bin/bash $TOMCAT_BIN/shutdown.sh
 RETVAL=$?
 return $RETVAL
restart(){
 echo "Restarting $prog......"
 stop
 start
case "$1" in
 start)
 start
 stop)
 stop
 restart)
 restart
 echo $"Usage: $0 {start|stop|restart}"
 RETVAL=1
exit $RETVAL

br

【脚本4】
linux系统的rm命令太危险,一不小心就会删除掉系统文件。 写一个shell脚本来替换系统的rm命令,要求当删除一个文件或者目录时,都要做一个备份,然后再删除。下面分两种情况,做练习:

假设有一个大的分区/data/,每次删除文件或者目录之前,都要先在/data/下面创建一个隐藏目录,以日期/时间命名,比如/data/.201703271012/,然后把所有删除的文件同步到该目录下面,可以使用rsync -R 把文件路径一同同步,示例:

#!/bin/bash
fileName=$1
now=`date +%Y%m%d%H%M`
read -p "Are you sure delete the file or directory $1? yes|no: " input
if [ $input == "yes" ] || [ $input == "y" ]
 mkdir /data/.$now
 rsync -aR $1/ /data/.$now/$1/
 /bin/rm -rf $1
elif [ $input == "no" ] || [ $input == "n" ]
 exit 0
 echo "Only input yes or no"
 exit
fi

br
2.复杂:

不知道哪个分区有剩余空间,在删除之前先计算要删除的文件或者目录大小,然后对比系统的磁盘空间,如果够则按照上面的规则创建隐藏目录,并备份,如果没有足够空间,要提醒用户没有足够的空间备份并提示是否放弃备份,如果用户输入yes,则直接删除文件或者目录,如果输入no,则提示未删除,然后退出脚本,示例:

#!/bin/bash
fileName=$1
now=`date +%Y%m%d%H%M`
f_size=`du -sk $1 |awk '{print $1}'`
disk_size=`LANG=en; df -k |grep -vi filesystem |awk '{print $4}' |sort -n |tail -n1`
big_filesystem=`LANG=en; df -k |grep -vi filesystem |sort -n -k4 |tail -n1 |awk '{print $NF}'`
if [ $f_size -lt $disk_size ]
 read -p "Are you sure delete the file or directory: $1 ? yes|no: " input
 if [ $input == "yes" ] || [ $input == "y" ]
 then
 mkdir -p $big_filesystem/.$now rsync -aR $1 $big_filesystem/.$now/ /bin/rm -rf $1
 elif [ $input == "no" ] || [ $input == "n" ]
 then
 exit 0
 else
 echo "Only input 'yes' or 'no'."
 echo "The disk size is not enough to backup the file: $1."
 read -p "Do you want to delete "$1"? yes|no: " input
 if [ $input == "yes" ] || [ $input == "y" ]
 then
 echo "It will delete "$1" after 5 seconds whitout backup."
 for i in `seq 1 5`; do echo -ne "."; sleep 1; done
 echo
 /bin/rm -rf $1
 elif [ $input == "no" ] || [ $input == "n" ]
 then
 echo "It will not delete $1."
 exit 0
 else
 echo "Only input 'yes' or 'no'."
fi

br

【脚本5】
编写shell脚本,要求输入一个数字,然后计算出从1到输入数字的和,要求,如果输入的数字小于1,则重新输入,直到输入正确的数字为止,示例:

#!/bin/bash
while :
 read -p "Please enter a positive integer: " n
 if [ $n -lt 1 ]
 then
 echo "It can't be less than 1"
 else
 break
num=1
for i in `seq 2 $n`
 num=$[$num+$i]
echo $num

br

【脚本6】
编写shell脚本,把/root/目录下的所有目录(只需要一级)拷贝到/tmp/目录下:

#!/bin/bash
cd /root/
list=(`ls`)
for i in ${list[@]}
 if [ -d $i ]
 then
 cp -r $i /tmp/
done

br

【脚本7】
编写shell脚本,批量建立用户user_00, user_01, ... user_100并且所有用户同属于users组:

#!/bin/bash
group=`cat /etc/group |grep -o users`
if [ $group == "users" ]
 for i in `seq 0 100`
 if [ $i -lt 10 ]
 then
 useradd -g users user_0$i
 else
 useradd -g users user_$i
 done
 echo "users group not found!"
 exit 1
fi

删除以上脚本批量添加的用户:

#!/bin/bash
for i in `seq 0 100`
 if [ $i -lt 10 ]
 then
 userdel -r user_0$i
 else
 userdel -r user_$i
done

br

【脚本8】
要求:请按照这样的日期格式(xxxx-xx-xx)每日生成一个文件,例如今天生成的文件为)2017-07-05.log, 并且把磁盘的使用情况写到到这个文件中,(不用考虑cron,仅仅写脚本即可)

#!/bin/bash
fileName=`date +%F`
c=`df -h`
echo "$c" /root/$fileName.log

br

【脚本9】
有一个日志文件,日志片段:如下:

112.111.12.248 – [25/Sep/2013:16:08:31 +0800]formula-x.haotui.com “/seccode.php?update=0.5593110133088248″ 200″http://formula-x.haotui.com/registerbbs.php” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;)”
61.147.76.51 – [25/Sep/2013:16:08:31 +0800]xyzdiy.5d6d.com “/attachment.php?aid=4554 k=9ce51e2c376bc861603c7689d97c04a1 t=1334564048 fid=9 sid=zgohwYoLZq2qPW233ZIRsJiUeu22XqE8f49jY9mouRSoE71″ 301″http://xyzdiy.×××thread-1435-1-23.html” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)”

要求: 统计出每个IP的访问量有多少?

awk '{print $1}' 1.log |sort -n |uniq -c |sort -n

解释:sort -n会按照数值而不是ASCII码来排序awk截取出来的IP。然后uniq命令用于报告或忽略文件中的重复行,加上-c选项后会在每列旁边显示该行重复出现的次数,在这一步就完成了统计。不过最后还得再让sort -n排序一下uniq -c统计出来的结果。

br

【脚本10】
写一个脚本计算一下linux系统所有进程占用内存大小的和。
代码:

#!/bin/bash
count=0
# 这个循环会遍历出每个进程占用的内存大小
for i in `ps aux |awk '{print $6}' |grep -v 'RSS'`
 # 将遍历出来的数字进行累加
 count=$[$count+$i]
# 就得到所有进程占用内存大小的和了
echo "$count/kb"

也可以使用awk 一条命令计算:

ps aux |grep -v 'RSS TTY' |awk '{sum=sum+$6};END{print sum}'

解释:grep -v是忽略 'RSS TTY' 所存在的那一行,后面的awk声明了一个变量sum,sum将前面命令列出来的数字进行累加,END之后就将累加后的sum打印出来,就得到所有进程占用内存大小的和了。

br

【脚本11】
设计一个简单的脚本,监控远程的一台机器(假设ip为123.23.11.21)的存活状态,当发现宕机时发一封邮件给你自己。

#!/bin/bash
ip="123.23.11.21"
email="[email protected]"
while 1
 ping -c10 $ip /dev/null 2 /dev/null
 if [ $? != "0" ]
 then
 # 调用一个用于发邮件的脚本
 python /usr/local/sbin/mail.py $email "$ip down" "$ip is down"
 sleep 30
done

mail.py 脚本代码:

#!/usr/bin/env python
#-*- coding: UTF-8 -*-
import os,sys
reload(sys)
sys.setdefaultencoding('utf8')
import getopt
import smtplib
from email.MIMEText import MIMEText
from email.MIMEMultipart import MIMEMultipart
from subprocess import *
def sendqqmail(username,password,mailfrom,mailto,subject,content):
 # 邮箱的服务地址
 gserver = 'smtp.qq.com'
 gport = 25
 try:
 msg = MIMEText(unicode(content).encode('utf-8'))
 msg['from'] = mailfrom
 msg['to'] = mailto
 msg['Reply-To'] = mailfrom
 msg['Subject'] = subject
 smtp = smtplib.SMTP(gserver, gport)
 smtp.set_debuglevel(0)
 smtp.ehlo()
 smtp.login(username,password)
 smtp.sendmail(mailfrom, mailto, msg.as_string())
 smtp.close()
 except Exception,err:
 print "Send mail failed. Error: %s" % err
def main():
 to=sys.argv[1]
 subject=sys.argv[2]
 content=sys.argv[3]
 #定义QQ邮箱的账号和密码,你需要修改成你自己的账号和密码
 sendqqmail('[email protected]','aaaaaaaaaa','[email protected]',to,subject,content)
if __name__ == "__main__":
 main()
#####脚本使用说明######
#1. 首先定义好脚本中的邮箱账号和密码
#2. 脚本执行命令为:python mail.py 目标邮箱 "邮件主题" "邮件内容"

br

【脚本12】
需求:

找到/123目录下所有后缀名为.txt的文件 批量修改.txt为.txt.bak 把所有.bak文件打包压缩为123.tar.gz 批量还原文件的名字,即把增加的.bak再删除

代码:

#!/bin/bash
now=`date +%F_%T`
mkdir /tmp/123_$now
for txt in `ls /123/*.txt`
 mv $txt $txt.bak
 for f in $txt
 cp $txt.bak /tmp/123_$now
 done
cd /tmp/
tar czf 123.tar.gz 123_$now/
for txt in `ls /123/*.txt.bak`
 name=`echo $txt |awk -F '.' '{OFS="."} {print $1,$2}'`
 mv $txt $name
done

br

【脚本13】
需求:
写一个脚本,判断本机的80端口(假如服务为httpd)是否开启着,如果开启着什么都不做,如果发现端口不存在,那么重启一下httpd服务,并发邮件通知你自己。脚本写好后,可以每一分钟执行一次,也可以写一个死循环的脚本,30s检测一次。
发邮件的脚本参考【脚本11】的示例代码。
代码:

#!/bin/bash
email="[email protected]"
if netstat -lntp |grep ':80' |grep 'httpd'
 echo "80 port no problem"
 exit
 /usr/local/apache2.4/bin/apachectl restart
 python mail.py $email "check_80port" "The 80 port is down."
 n=`ps aux |grep httpd|grep -cv grep`
 if [ $n -eq 0 ]
 then
 /usr/local/apache2/bin/apachectl start 2 /tmp/apache_start.err
 if [ -s /tmp/apache_start.err ]
 then
 python mail.py $mail 'apache_start_error' `cat /tmp/apache_start.err`
fi

【脚本14】
需求:

设计一个shell脚本来备份数据库,首先在本地服务器上保存一份数据,然后再远程拷贝一份,本地保存一周的数据,远程保存一个月。

假定,我们知道mysql root账号的密码,要备份的库为discuz,本地备份目录为/bak/mysql, 远程服务器ip为192.168.123.30,远程提供了一个rsync服务,备份的地址是 192.168.123.30::backup . 写完脚本后,需要加入到cron中,每天凌晨3点执行。
脚本代码:

#!/bin/bash
PATH=$PATHi:/usr/local/mysql/bin
week=`date +%w`
today=`date +d`
passwd="123456"
backdir="/data/mysql"
r_backupIP="192.168.123.30::backup"
exec 1 /var/log/mysqlbak.log 2 /var/log/mysqlbak.log
echo "mysql backup begin at `date +%F %T`."
# 本地备份
mysqldump -uroot -p$passwd --default-character-set=utf8 discuz $backdir/$week.sql
# 同步备份到远程机器
rsync -az $backdir/$week.sql $r_backupIP/$today.sql
echo "mysql backup end at `date +%F %T`."

然后加入cron
0 3 * * * /bin/bash /usr/local/sbin/mysqlbak.sh

【脚本15】
服务器上跑的是LNMP环境,近期总是有502现象。502为网站访问的状态码,200正常,502错误是nginx最为普通的错误状态码。由于502只是暂时的,并且只要一重启php-fpm服务则502消失,但不重启的话,则会一直持续很长时间。所以有必要写一个监控脚本,监控访问日志的状态码,一旦发生502,则自动重启一下php-fpm。

我们设定:

access_log /data/log/access.log 脚本死循环,每10s检测一次(假设每10s钟的日志条数为300左右) 重启php-fpm的方法是 /etc/init.d/php-fpm restart

脚本代码:

#!/bin/bash
access_log="/data/log/access.log"
while :
 # 因为10秒大概产生300条日志记录
 tail -n300 $access_log /tmp/log
 # 拿出log中包含502的日志行数
 n_502=`grep -c "502" /tmp/log`
 # 如果行数大于10
 if [ $n_502 -ge $N ]
 then
 # 就记录一下系统状态
 top -bn1 /tmp/`date +%H%M%S`-top.log
 vmstat 1 5 /tmp/`date +%H%M%S`-vm.log
 # 然后才重启服务,并把错误信息重定向
 /etc/init.d/php-fpm restart 2 /dev/null
 # 重启php-fpm服务后,应先暂缓1分钟,而后继续每隔10s检测一次
 sleep(60)
 sleep(10)
done

【脚本16】
将memcached里的数据导出到文件中,然后再导入memcached里却发现数据过期了,这是因为导出的数据是带有一个时间戳的,这个时间戳就是该条数据过期的时间点,如果当前时间已经超过该时间戳,那么是导入不进去的。不过可以修改文件中的时间戳来保证导入时数据的有效期。可以写一个简单的脚本批量替换这些文件中的时间戳:

#!/bin/bash
hour=`date -d "+1 hour" +%s` # 一个小时之后的时间戳
data_time=`cat data.txt |grep add |awk '{print $4}' |sort -n |uniq`
for i in $data_time
 sed -i "s/$i/$hour/g" `grep $i -rl /root/data.txt`
done

【脚本17】
docker每次关闭都会连带着将运行中的容器关闭,所以每次启动docker后都需要逐个去启动容器,很麻烦,由于是实验用的虚拟机不是线上的机器,所以就直接写了一个很简单的循环来启动容器:

#!/bin/bash
/usr/bin/systemctl start docker
for i in `docker ps -a |grep 'Exited' |awk '{print $1}'`
 /usr/bin/docker start $i
done
网友评论
<