赞
踩
概述
Shell是一种具备特殊功能的程序,它提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令,并把它送入内核去执行。内核是Linux系统的心脏,从开机自检就驻留在计算机的内存中,直到计算机关闭为止,而用户的应用程序存储在计算机的硬盘上,仅当需要时才被调入内存。Shell是一种应用程序,当用户登录Linux系统时,Shell就会被调入内存去执行。Shell独立于内核,它是连接内核和应用程序的桥梁,并由输入设备读取命令,再将其转为计算机可以理解的机械码,Linux内核才能执行该命令。
优势
Shell脚本语言的好处是简单、易学、易用,适合处理文件和目录之类的对象,以简单的方式快速完成某些复杂的事情通常是创建脚本的重要原则,脚本语言的特性可以总结为以下几个方面:
1. 语法和结构通常比较简单。
2. 学习和使用通常比较简单,
3. 通常以容易修改程序的“解释”作为运行方式,而不需要“编译。
4. 程序的开发产能优于运行效能。
Shell脚本语言是Linux/Unix系统上一种重要的脚本语言,在Linux/Unix领域应用极为广泛,熟练掌握Shell脚本语言是一个优秀的Linux/Unix开发者和系统管理员必经之路。利用Shell脚本语言可以简洁地实现复杂的操作,而且Shell脚本程序往往可以在不同版本的Linux/Unix系统上通用。
Shell脚本的文件名后缀通常是.sh (当然你也可以使用其他后缀或者没有后缀,.sh是为了规范)
程序编写格式:
#!/bin/bash
# 注释使用#号
代码示例:
使用vi编辑器编写shell脚本(a.sh不存在则会新建)
vi a.sh
进入vi编辑模式后编写执行代码
固定格式,记住就可以了
#!/bin/bash
执行的代码
echo Hello World
赋予权限并执行:
赋予可执行权限
chmod +x a.sh
执行(调用/bin/bash执行a.sh脚本)
./a.sh
sh a.sh
执行结果:
[root@python ~]# ./a.sh
Hello world
bash 语法检查
[root@python ~]# bash -x a.sh
+ echo Hello world
Hello world
变量不需要声明,初始化不需要指定类型
- 只能使用数字,字母和下划线,且不能以数字开头
- 变量名区分大小写
- 建议命令要通俗易懂
注意:变量赋值是通过等号(=)进行赋值,在变量、等号和值之间不能出现空格。
显示变量值使用echo命令(类似于java中的system.out) ,加上变量名,也可以使用{变量名}
变量的申明和使用:
[root@python ~]# num=10
[root@python ~]# echo $num
10
Shell变量有这几类:本地变量、环境变量、局部变量、位置变量、特殊变量。
- 只对当前shell进程有效的,对当前进程的子进程和其它shell进程无效。
- 定义:VAR_NAME=VALUE
- 变量引用:{VAR_NAME} 或者 VAR_NAME
- 取消变量:unset VAR_NAME
- 只能当前类使用,子类和其他类都无法使用。
在一个bash命令窗口下再使用bash,则变成了子进程,本地变量不会被这个子进程所访问
[root@python ~]# num=10
[root@python ~]# echo $num
10
[root@python ~]# bash
[root@python ~]# echo $unm
[root@python ~]#
自定义的环境变量对当前shell进程及其子shell进程有效,对其它的shell进程无效
定义:export VAR_NAME=VALUE
对所有shell进程都有效需要配置到配置文件中
[root@python ~]# vim /etc/profile
[root@python ~]# source /etc/profile
[root@python ~]# export name=xiaoming
[root@python ~]# echo $name
xiaoming
[root@python ~]# bash
[root@python ~]# echo $name
xiaoming
比如脚本中的参数:
Linux中变量$#,$@,$0,$1,$2,$*,$$,$?的含义?
$# 是传给脚本的参数个数
$0 是脚本本身的名字
$1 是传递给该shell脚本的第一个参数
$2 是传递给该shell脚本的第二个参数
$@ 是传给脚本的所有参数的列表
$* 是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个
$$ 是脚本运行的当前进程ID号Linux中变量$#,$@,$0,$1,$2,$*,$$,$?的含义
$? 是显示最后命令的退出状态,0表示没有错误,其他表示有错误
编写脚本:
[root@python ~]# cat variable.sh
#!/bin/sh
echo "number:$#"
echo "scname:$0"
echo "first :$1"
echo "second:$2"
echo "argume:$@"
echo "show parm list:$*"
echo "show process id:$$"
echo "show precomm stat: $?"
执行示例:
[root@python ~]# ./variable.sh
number:0
scname:./variable.sh
first :
second:
argume:
show parm list:
show process id:1445
show precomm stat: 0
Shell编程中有三类引号:单引号、双引号、反引号。
###1.’'单引号
不解析变量
[root@python ~]# echo '$name'
$name
###2.""双引号
会解析变量
[root@python ~]# echo "$name"
xiaoming
###3.``反引号
是执行并引用一个命令的执行结果,类似于$(…)
[root@python ~]# echo `$name`
bash: xiaoming: command not found
通过使用一个变量去遍历给定列表中的每个元素,在每次变量赋值时执行一次循环体,直至赋值完成所有元素退出循环
for ((i=0;i<10;i++))
do
...
Done
for i in 0 1 2 3 4 5 6 7 8 9
do
...
Done
示例
#!/bin/bash
day="sun mon tue wen fri sat "
for x in $day
do
echo "the day is : $x"
done
格式 3
for i in {0..9}
do
...
done
注意:for i in {0…9} 等于for i in {0…9…1} , 第三个参数为跨步
示例
#!/bin/bash
day="sun mon tue wen fri sat "
for x in $day
do
echo "the day is : $x"
done
适用于循环次数未知,或不便用for直接生成较大的列表时
while 测试条件
do
循环体
done
如果测试条件为“真”,则进入循环,测试条件为假,则退出循环。
[root@python ~]# cat while.sh
#!/bin/bash
num=0
while [ $num -lt 10 ]
do
echo $num
let num=$num+1
done
打印结果
[root@python ~]# sh while.sh
0
1
2
3
4
5
6
7
8
9
break命令是在处理过程中跳出循环的一种简单方法,可以使用break命令退出任何类型的循环,包括while循环和for循环
continue命令是一种提前停止循环内命令,而不完全终止循环的方法,这就需要在循环内设置shell不执行命令的条件
格式:
test EXPR
[ EXPR ]:注意中括号和表达式之间的空格
-gt:大于:
-lt:小于
-ge:大于等于
-le:小于等于
-eq:等于
-ne:不等于
例如[ $num1 -gt $num2 ]或者test $num1 -gt $num2
=:等于,例如判断变量是否为空 [ "$str" = "" ] 或者[ -z $str ]
!=:不等于
示例:
[root@python ~]# cat str.sh #!/bin/bash num1=4 num2=5 str1=Alice str2=Bob if [ $num1 -gt $num2 ] then echo num1 large than num2 else echo num1 lower than num2 fi if [ -z $str1 ] then echo str1 is empty else echo str is not empty fi
执行结果:
[root@python ~]# sh str.sh
num1 lower than num2
str is not empty
if 测试条件;then
选择分支
fi
#!/bin/bash
if [ $USER != root ];then
echo "erro:not root user,permission deny"
exit 127
fi
if 测试条件
then
选择分支1
else
选择分支2
fi
if 条件1; then
分支1
elif 条件2; then
分支2
elif 条件3; then
分支3
...
else
分支n
fi
示例:
#!/bin/bash
read -p "input a file name:" file_name
if [ -d $file_name ];then
echo "$file_name is a directory"
elif [ -f $file_name ];then
echo "$file_name is a file"
elif [ -c $file_name ];then
echo "$file_name is a devices"
else
echo "$file_name is unknown file"
fi7.**Case判断**
case 变量引用 in
PATTERN1)
分支1
;;
PATTERN2)
分支2
;;
...
*)
分支n
;;
esac
PATTERN :类同于文件名通配机制,但支持使用|表示或者
a|b:a或者b
*:匹配任意长度的任意字符
?:匹配任意单个字符
[a-z]:指定范围内的任意单个字符
[root@python ~]# cat case.sh #!/bin/bash num=10 case $num in 1) echo 1 ;; 2) echo 2 ;; 10) echo 10 ;; *) echo somethine else ;; esac
let varName=算术表达式
varName=$[算术表达式]
varName=$((算术表达式))
varName=`expr $num1 + $num2`
使用这种格式要注意两个数字和+号中间要有空格。
[root@centos7 ~]# num=2
[root@centos7 ~]# let num=$num+1
[root@centos7 ~]# echo $num
3
[root@centos7 ~]# num=2
[root@centos7 ~]# num=$[ $num+1 ]
[root@centos7 ~]# echo $num
3
[root@centos7 ~]# num=2
[root@centos7 ~]# num=$(($num+1))
[root@centos7 ~]# echo $num
3
[root@centos7 ~]# num=2
[root@centos7 ~]# num=`expr $num + 1`
[root@centos7 ~]# echo $num
3
需要用到shell中的逻辑操作符
-a 与
-o 或
! 非
如if [ 条件A -a 条件B ]
示例
[root@python ~]# cat num_1.sh
#!/bin/bash
num1=10
num2=20
num3=15
if [ $num1 -lt $num3 -a $num2 -gt $num3 ]
then
echo "num is between 10 and 20"
else
echo "something else"
fi
#####示例
#!/bin/bash
num1=10
num2=20
num3=15
if [ $num1 -ge $num3 -o $num2 -lt $num3 ]
then
echo "num is between 10 and 20"
else
echo "something else"
fi
function 函数名(){
...
}
引用自定义函数文件时,使用source func.sh
有利于代码的重用性
函数传递参数(args[1]代表Shell中的$1)
函数的返回值,只能是数字
[root@python ~]# cat func.sh
#!/bin/bash
function func(){
echo this is function
}
func
[root@python ~]# cat func2.sh
#!/bin/bash
source /root/func.sh
func
read命令接收标准输入(键盘)的输入,或者其他文件描述符的输入。得到输入后,read命令将数据放入一个标准变量中。
格式
read VAR_NAME
read如果后面不指定变量,那么read命令会将接收到的数据放置在环境变量REPLY中
#表示输入时的提示字符串:
read -p "Enter your name:" VAR_NAME
[root@python ~]# read -p "Enter you name:" name
Enter you name:
[root@python ~]# read -t 5 -p "Enter you name:" name
Enter you name:[root@python ~]#
# -t表示输入等待的时间
read -t 5 -p "enter your name:" VAR_NAME
[root@python ~]# read -s -p "Enter your password:" pass
Enter your password:
用来限定变量的属性
-r 只读
-i 整数:某些算术计算允许在被声明为整数的变量中完成,而不需要特别使用expr或let来完成。
-a 数组
示例:
[root@python ~]# num=10
[root@python ~]# declare -r num
[root@python ~]# num=20
bash: num: readonly variable
[root@python ~]#
[root@python ~]# num4=10
[root@python ~]# num4=$num4+1
[root@python ~]# echo $num4
10+1
[root@python ~]# declare -i num5
[root@python ~]# num5=10
[root@python ~]# num5=$num5+1
[root@python ~]# echo $num5
11
[root@python ~]# declare -a arr
[root@python ~]# arr=(1 2 3 4 5)
[root@python ~]# echo ${arr[*]}
1 2 3 4 5
${#VAR_NAME}
[root@python ~]# name=Alice
[root@python ~]# echo ${#name}
5
${variable:offset:length}或者${variable:offset}
[root@python ~]# name=Alice
[root@python ~]# echo ${name:0:3}
Ali
${variable: -length}:注意冒号后面有空格
[root@python ~]# name=Alice
[root@python ~]# echo ${name:2}
ice
小—>大:
${variable^^}
[root@python ~]# name=Alice
[root@python ~]# echo ${name^^}
ALICE
大—>小
${variable,,}
[root@python ~]# name=Alice
[root@python ~]# echo ${name,,}
alice
定义:declare -a:表示定义普通数组
特点
- 支持稀疏格式
- 仅支持一维数组
**数组赋值方式 **
- 一次对一个元素赋值a[0]=$RANDOM
- 一次对多个元素赋值a=(a b c d)
按索引进行赋值a=([0]=a [3]=b [1]=c)
使用read命令read -a ARRAY_NAME查看元素
${ARRAY[index]}:查看数组指定角标的元素
${ARRAY}:查看数组的第一个元素
${ARRAY[*]}或者${ARRAY[@]}:查看数组的所有元素
获取数组的长度
${#ARRAY[*]}
${#ARRAY[@]}
获取数组内元素的长度
${#ARRAY[0]}
注意:${#ARRAY[0]}表示获取数组中的第一个元素的长度,等于${#ARRAY}
从数组中获取某一片段之内的元素(操作类似于字符串操作)
格式:
${ARRAY[@]:offset:length}
数组删除元素:
unset ARRAY[index]
示例:
[root@python ~]# declare -a arr2
[root@python ~]# arr2=(a b c d )
[root@python ~]# arr2[1]=x
[root@python ~]# echo ${arr2[*]}
a x c d
[root@python ~]# echo ${#arr2[*]}
4
[root@python ~]# echo ${#arr2[1]}
1
[root@python ~]# echo ${arr2[1]}
x
显示当前时间
1. 格式化输出 +%Y-%m-%d
2. 格式%s表示自1970-01-01 00:00:00以来的秒数
3. 指定时间输出 --date='2009-01-01 11:11:11'
4. 指定时间输出 --date='3 days ago' (3天之前,3天之后可以用-3)
示例:
[root@python ~]# echo `date +%Y-%m-%d-%H:%M:%S`
2018-08-25-14:07:16
[root@python ~]# echo `date +%s`
1535220472
[root@python ~]# echo `date --date='2009-01-01 11:11:11'`
Thu Jan 1 11:11:11 EST 2009
[root@python ~]# echo `date --date='3 days ago'`
Wed Aug 22 14:10:28 EDT 2018
在脚本后面加一个&
test.sh &
这样的话虽然可以在后台运行,但是当用户注销(logout)或者网络断开时,终端会收到Linux HUP信号(hangup)信号从而关闭其所有子进程 ]
不挂断的运行命令,忽略所有挂断(hangup)信号
nohup test.sh &
标准输入、输出、错误可以使用文件描述符0、1、2引用
使用重定向可以把信息重定向到其他位置
1. ls >file 或者 ls 1>file(ls >>file)
2. lk 2>file(lk是一个错误命令)
3. ls >file 2>&1
4. ls > /dev/null(把输出信息重定向到无底洞)
示例
command >/dev/null 2>&1
示例 表示每分钟执行一次bash /root/bash.sh 命令
* * * * * bash /root/bash.sh
查看定时任务
[root@python ~]# crontab -l
* * * * * bash /root/bash.sh
删定时任务
[root@python ~]# crontab -l
* * * * * bash /root/bash.sh
[root@python ~]# crontab -r
You have new mail in /var/spool/mail/root
[root@python ~]# crontab -l
no crontab for root
查看crontab执行日志
[root@python ~]# tail -f /var/log/cron
必须打开rsyslog服务cron文件中才会有执行日志(service rsyslog status)
[root@python ~]# tail -f /var/spool/mail/root (查看crontab执行的情况)
查看cron服务状态
[root@python ~]# service crond status
启动cron服务
[root@python ~]# service crond start
基本示例:
基本格式 :
* * * * * command
分 时 日 月 周 命令
第1列表示分钟1~59 每分钟用*或者 */1表示
第2列表示小时1~23(0表示0点)
第3列表示日期1~31
第4列表示月份1~12
第5列标识号星期0~6(0表示星期天)
第6列要运行的命令
crontab 示例:
30 21 * * * /usr/local/etc/rc.d/lighttpd restart 上面的例子表示每晚的21:30重启apache。 45 4 1,10,22 * * /usr/local/etc/rc.d/lighttpd restart 上面的例子表示每月1、10、22日的4 : 45重启apache。 10 1 * * 6,0 /usr/local/etc/rc.d/lighttpd restart 上面的例子表示每周六、周日的1 : 10重启apache。 0,30 18-23 * * * /usr/local/etc/rc.d/lighttpd restart 上面的例子表示在每天18 : 00至23 : 00之间每隔30分钟重启apache。 0 23 * * 6 /usr/local/etc/rc.d/lighttpd restart 上面的例子表示每星期六的11 : 00 pm重启apache。 * */1 * * * /usr/local/etc/rc.d/lighttpd restart 每一小时重启apache * 23-7/1 * * * /usr/local/etc/rc.d/lighttpd restart 晚上11点到早上7点之间,每隔一小时重启apache 0 11 4 * mon-wed /usr/local/etc/rc.d/lighttpd restart 每月的4号与每周一到周三的11点重启apache 0 4 1 jan * /usr/local/etc/rc.d/lighttpd restart 一月一号的4点重启apache
交互式的:顾名思义,这种shell中的命令时由用户从键盘交互式地输入的,运行的结果也能够输出到终端显示给用户看。
非交互式的:这种shell可能由某些自动化过程启动,不能直接从请求用户的输入,也不能直接输出结果给终端用户看。输出最好写到文件。比如使用Shell脚本。
登录式:意思是这种是在某用户由/bin/login登陆进系统后启动的shell,跟这个用户绑定。这个shell是用户登陆后启动的第一个进程。login进程在启动shell时传递第0个参数指明shell的名字,该参数第一个字符为"-",指明这是一个login shell。比如对bash而言,启动参数为"-bash"。
非登录式:不需login而由某些程序启动的shell。传递给shell的参数,是没有'-'前缀的。还以Bash为例,当以非login方式启动时,它会调用~/.bashrc,随后~/.bashrc中调用/etc/bashrc,最后/etc/bashrc调用所有/etc/profile.d目录下的脚本。
一旦打开一个交互式login shell,或者以--login选项登录的非交互式shell,都会首先加载并执行/etc/profile中的命令,然后再依次加载~/.bash_profile, ~/.bash_login, 和~/.profile中的命令。
当bash以login shell启动时,它会执行/etc/profile中的命令,然后/etc/profile调用/etc/profile.d目录下的所有脚本;然后执行~/.bash_profile,~/.bash_profile调用~/.bashrc,最后~/.bashrc又调用/etc/bashrc。要识别一个shell是否为login shell,只需在该shell下执行echo $0。
注意: /etc/profile中的设置只对Login Shell生效,而crontab运行脚本的shell环境是non-login的,不会加载/etc/profile的设置。
需求:对CentOS6系统进行配置优化
Optimization_host.sh #!/bin/bash #time 20161122 #2016-11-30 by innocence_caosm #此脚本在centos6.8上面试运行没有问题,其他版本慎用!!! #注意: #1、缩进问题 #2、严谨性 #3、精简至上原则 Ipaddr(){ echo -e "\033[32;1m========================配置ip地址以及主机名称======================================\033[0m" read -p "请输入你的ip地址:" IPADDR read -p "请输入你的子网掩码:" NETMASK read -p "请输入你的网关地址:" GATEWAY read -p "请输入你的DNS1:" DNS1 sed -i '/^ONBOOT/s/no/yes/' /etc/sysconfig/network-scripts/ifcfg-eth0 sed -i '/^BOOTPROTO/s/dhcp/static/' /etc/sysconfig/network-scripts/ifcfg-eth0 sed -i "/^IPADDR/s/[0-9].\+/$IPADDR/ " /etc/sysconfig/network-scripts/ifcfg-eth0 sed -i "/^NETMASK/s/[0-9].\+/$NETMASK/ " /etc/sysconfig/network-scripts/ifcfg-eth0 sed -i "/^GATEWAY/s/[0-9].\+/$GATEWAY/ " /etc/sysconfig/network-scripts/ifcfg-eth0 sed -i "/^DNS1/s/[0-9].\+/$DNS1/ " /etc/sysconfig/network-scripts/ifcfg-eth0 service network restart >&/dev/null ping -c 3 -w 5 www.baidu.com >&/dev/null if [[ $? != 0 ]];then echo " 不能上网请检查配置 " else echo -e "\033[32;1m=====================NetWork Already Configure Finish ============================\033[0m" fi sleep 2 } Ip_hostname(){ echo -e "\033[32;1m==========================配置主机名称==============================================\033[0m" read -p "请输入你的主机名称:" HOSTNAME sed -i '3,$d' /etc/hosts sed -i '2,$d' /etc/sysconfig/network sed -i '/^HOSTNAME.*$/d' /etc/hosts echo "HOSTNAME=$HOSTNAME" >> /etc/sysconfig/network IPADDR=`ip a | grep "global eth0" | awk '{print $2}' | awk -F "/" '{print $1}'` echo -e "$IPADDR\t$HOSTNAME" >>/etc/hosts echo -e "\033[32;1m===========================主机名配置成功==========================================\033[0m" echo "" sleep 2 } # yum_163 ConfigYum(){ echo -e "\033[32;1m===========================更新为国内YUM源==========================================\033[0m" cd /etc/yum.repos.d/ ping -c 1 www.163.com>/dev/null if [ $? -eq 0 ];then mv CentOS6-Base-163.repo{,.$(date +%F)} wget -q http://mirrors.163.com/.help/CentOS6-Base-163.repo >/dev/null sleep 2 sed -i "s/\$releasever/6.8/g" CentOS6-Base-163.repo #sed -i '/s/$releasever/6.8/g' CentOS6-Base-163.repo #此处可提升为判断系统版本号,给出不同的版本节点 else echo "无法连接网络!!!!" exit $? fi echo -e "\033[32;1m============================正在更新YUM源配置=======================================\033[0m" yum clean all >>/dev/null yum list >>/dev/null #action "配置国内YUM完成" /bin/true echo -e "\033[32;1m======================================配置YUM源完成===============================\033[0m" echo "" sleep 2 } #time sync SyncSysTime(){ echo -e "\033[32;1m=========================================配置时间====================================\033[0m" \cp /var/spool/cron/root /var/spool/cron/root.$(date +%F) 2>/dev/null NTPDATE=`grep ntpdate /var/spool/cron/root 2>/dev/null |wc -l` if [ $NTPDATE -eq 0 ];then echo "#times sync by lee at $(date +%F)" >>/var/spool/cron/root echo "*/5 * * * * /usr/sbin/ntpdate time.windows.com >/dev/null 2>&1" >> /var/spool/cron/root fi #action "配置时间同步完成" /bin/true echo -e "\033[32;1m=========================================配置时间完成====================================\033[0m" echo "" sleep 2 } #Charset zh_CN.UTF-8 InitI18n(){ echo -e "\033[32;1m======================================更改为中文字符集===================================\033[0m" \cp /etc/sysconfig/i18n /etc/sysconfig/i18n.$(date +%F) echo "LANG="zh_CN.UTF-8"" >/etc/sysconfig/i18n source /etc/sysconfig/i18n echo '#cat /etc/sysconfig/i18n' grep LANG /etc/sysconfig/i18n #action "更改字符集zh_CN.UTF-8完成" /bin/true echo -e "\033[32;1m====================================更改为中文字符集完成===================================\033[0m" echo "" sleep 2 } #Close Selinux and Iptables Firewall(){ echo -e "\033[32;1m======================================禁用SELINUX及关闭防火墙=============================\033[0m" cp /etc/selinux/config /etc/selinux/config.$(date +%F) /etc/init.d/iptables status >>/dev/null if [ $? -eq 0 ];then #判断防火墙是否开启,开启时返回值是0 /etc/init.d/iptables stop >>/dev/null fi $(cat /etc/selinux/config |grep SELINUX=enforcing) if [ $? -eq 0 ] ;then sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config setenforce 0 fi #getenforce #action "禁用selinux及关闭防火墙完成" /bin/true echo -e "\033[32;1m======================================禁用SELINUX及关闭防火墙完成=============================\033[0m" echo "" sleep 2 } Yum(){ echo -e "\033[32;1m======================================安装常用软件=============================\033[0m" yum install -y lrzsz nptdate bash-completion wget echo "" sleep 2 } echo -e "\033[32;1m======================================安装常用软件完成=============================\033[0m" Core(){ echo -e "\033[32;1m======================================内核参数调整=============================\033[0m" # 内核参数调优 grep -q "fs.file-max = 6815744" /etc/sysctl.conf || cat >> /etc/sysctl.conf << EOF ######################################################################################################################## vm.swappiness = 0 vm.overcommit_memory = 1 net.core.rmem_default = 262144 net.core.rmem_max = 16777216 net.core.wmem_default = 262144 net.core.wmem_max = 16777216 net.core.somaxconn = 60000 net.core.netdev_max_backlog = 60000 net.ipv4.tcp_max_orphans = 60000 net.ipv4.tcp_orphan_retries = 3 net.ipv4.tcp_max_syn_backlog = 60000 net.ipv4.tcp_max_tw_buckets = 10000 net.ipv4.ip_local_port_range = 1024 65500 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_synack_retries = 1 net.ipv4.tcp_syn_retries = 1 net.ipv4.tcp_fin_timeout = 30 net.ipv4.tcp_keepalive_time = 1200 net.ipv4.tcp_mem = 786432 1048576 1572864 fs.aio-max-nr = 1048576 fs.file-max = 6815744 kernel.sem = 250 32000 100 10000 kernel.pid_max = 65536 fs.inotify.max_user_watches = 1048576 kernel.kptr_restrict = 1 kernel.ctrl-alt-del = 1 EOF sysctl -p # 提高系统打开文件数、打开进程数限制,减小默认栈空间大小限制 grep -q "* - nofile 1048576" /etc/security/limits.conf || cat >> /etc/security/limits.conf << EOF ######################################################################################################################## * - nofile 1048576 * - nproc 65536 * - stack 1024 EOF # 提高Shell打开文件数、打开进程数限制,减小默认栈空间大小限制 grep -q "ulimit -n 1048576" /etc/profile || cat >> /etc/profile << EOF ######################################################################################################################## ulimit -n 1048576 ulimit -u 65536 ulimit -s 1024 alias grep='grep --color=auto' export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S " EOF echo -e "\033[32;1m======================================内核参数调整完毕=============================\033[0m" #menu2 menu2(){ while true do clear cat << EOF ---------------------------------------- |****Please Enter Your Choice:[0-6]****| ---------------------------------------- (1) 配置ip地址以 (2) 配置为国内YUM源镜像 (3) 设置时间同步 (4) 配置中文字符集 (5) 禁用SELINUX及关闭防火墙 (6) 配置主机名称 (0) 返回上一级菜单 EOF read -p "Please enter your Choice[0-6]: " input2 case "$input2" in 0) clear break ;; 1) Ipaddr ;; 2) ConfigYum ;; 3) SyncSysTime ;; 4) InitI18n ;; 5) Firewall ;; 6) Ip_hostname ;; *) Warning ;; esac done } #menu main(){ while true do clear echo "========================================" echo ' Linux Optimization ' echo "========================================" cat << EOF |-----------System Infomation----------- | DATE :$DATE | HOSTNAME :$HOSTNAME | USER :$USER | IP :$IPADDR | DISK_USED :$DISK_SDA | CPU_AVERAGE:$cpu_uptime ---------------------------------------- |****Please Enter Your Choice:[1-3]****| ---------------------------------------- (1) 一键优化 (2) 自定义优化 (3) 退出 EOF #choice read -p "Please enter your choice[0-3]: " input1 case "$input1" in 1) Ipaddr ConfigYum SyncSysTime InitI18n Firewall Ip_hostname ;; 2) menu2 ;; 3) clear break ;; *) Warning ;; esac done } Warning(){ echo "----------------------------------" echo "| Warning!!! |" echo "| Please Enter Right Choice! |" echo "----------------------------------" sleep 2 ((ErrorNo+=1)) if [ $ErrorNo -eq 3 ];then #判断错误次数,已达到自动退出目的 echo -e '\033[31;1mError So Much ,The Script Exiting!\033[0m' sleep 5 exit fi clear } if $UID != 0 ;then echo 'must use Root run this script!' else #获取一些初始变量,磁盘使用情况未配置 ErrorNo=0 DATE=$(date +%F) IPADDR=`ifconfig |grep Bcast|awk '{print $2}'|awk -F: '{print $2}'` DISK_SDA=`df -hT | grep '/$' | awk '{print $6}'` cpu_uptime=`uptime|awk -F: '{print $4}'` main fi
CentOS7** 系统优化脚本
centos 7 优化 #!/bin/bash # 服务优化 grep -q '7.' /etc/redhat-release if [ $? -ne 0 ]; then Services=$(chkconfig --list | grep '0' | awk '{print $1}' | grep -Ev 'sshd|network|crond|syslog|ntpd') for Service in $Services do service $Service stop chkconfig --level 0123456 $Service off done else Services=(atd avahi-daemon cups dmraid-activation firewalld irqbalance kdump mdmonitor postfix) for Service in ${Services[*]} do systemctl disable ${Service} systemctl stop ${Service} done systemctl enable rc-local fi # 内核参数调优 grep -q "fs.file-max = 6815744" /etc/sysctl.conf || cat >> /etc/sysctl.conf << EOF ######################################## vm.swappiness = 0 vm.overcommit_memory = 1 net.core.rmem_default = 262144 net.core.rmem_max = 16777216 net.core.wmem_default = 262144 net.core.wmem_max = 16777216 net.core.somaxconn = 60000 net.core.netdev_max_backlog = 60000 net.ipv4.tcp_max_orphans = 60000 net.ipv4.tcp_orphan_retries = 3 net.ipv4.tcp_max_syn_backlog = 60000 net.ipv4.tcp_max_tw_buckets = 10000 net.ipv4.ip_local_port_range = 1024 65500 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_synack_retries = 1 net.ipv4.tcp_syn_retries = 1 net.ipv4.tcp_fin_timeout = 30 net.ipv4.tcp_keepalive_time = 1200 net.ipv4.tcp_mem = 786432 1048576 1572864 fs.aio-max-nr = 1048576 fs.file-max = 6815744 kernel.sem = 250 32000 100 10000 kernel.pid_max = 65536 fs.inotify.max_user_watches = 1048576 kernel.kptr_restrict = 1 kernel.ctrl-alt-del = 1 EOF sysctl -p # 提高系统打开文件数、打开进程数限制,减小默认栈空间大小限制 grep -q "* - nofile 1048576" /etc/security/limits.conf || cat >> /etc/security/limits.conf << EOF ######################################## * - nofile 1048576 * - nproc 65536 * - stack 1024 EOF # 提高Shell打开文件数、打开进程数限制,减小默认栈空间大小限制 grep -q "ulimit -n 1048576" /etc/profile || cat >> /etc/profile << EOF ######################################## ulimit -n 1048576 ulimit -u 65536 ulimit -s 1024 alias grep='grep --color=auto' export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S " EOF # 禁用并关闭selinux sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config setenforce 0 # 优化SSH服务 sed -i 's/.*UseDNS yes/UseDNS no/' /etc/ssh/sshd_config sed -i 's/.*GSSAPIAuthentication yes/GSSAPIAuthentication no/' /etc/ssh/sshd_config #sed -i '/^PasswordAuthentication/s/yes/no/' /etc/ssh/sshd_config grep -q '7.' /etc/redhat-release if [ $? -ne 0 ]; then service sshd restart else systemctl restart sshd.service fi # 脚本目录加入PATH环境变量 grep -q "/root/script" $HOME/.bashrc || cat >> $HOME/.bashrc << EOF ######################################## export PATH=/root/script:\$PATH EOF mkdir -p /root/script /root/src # 挂载tmpfs文件系统 mount --bind /dev/shm /tmp grep -q "mount --bind /dev/shm /tmp" /etc/rc.local || echo "mount --bind /dev/shm /tmp" >> /etc/rc.local
思路:
对刚安装完成的虚拟主机进行优化处理,简化工作流程
对服务进行优化
对防火墙 selinux进行优化
字符编码进行优化
network进行优化
ssh 进行优化
yum 源进行优化
date 时间进行优化
2017-11-29 17:25:54 #/bin/bash #by innocence_caosm #源码自动安装zabbix客户端脚本。 #需要把zabbix安装包放在/tmp/ 下面执行。 #安装gcc cc插件 #此脚本已在centos6.5以及6.8版本测试过,其他版本慎用。 yum install -y gcc cc #需要注意修改的参数 server_ip=133.1.11.103 version=zabbix-3.2.7 #检查zabbix用户是否存在 user=zabbix group=zabbix #create group if not exists egrep "^$group" /etc/group >& /dev/null if [ $? -ne 0 ] then groupadd $group fi #create user if not exists egrep "^$user" /etc/passwd >& /dev/null if [ $? -ne 0 ] then useradd -g $group $user -s /sbin/nologin echo zabbix |passwd --stdin $user >& /dev/null fi #检查原有zabbix服务,如果有则停掉 ps -ef |grep zabbix|grep -v grep if [ $? -eq 0 ] then /etc/init.d/zabbix-agent stop || /etc/init.d/zabbix-agentd stop fi #编译安装 tar -zxvf /tmp/$version.tar.gz -C /usr/local/src/;cd /usr/local/src/$version/ ./configure --prefix=/usr/local/$version/ --enable-agent make&&make install #修改配置文件 sed -i.bak 's/127.0.0.1/$server_ip/g' /usr/local/$version/etc/zabbix_agentd.conf hostname=cat /etc/sysconfig/network | sed -n '2p' | awk -F'=' '{print $2}' sed -i "s/Hostname=Zabbix server/Hostname="$hostname"/g" /usr/local/$version/etc/zabbix_agentd.conf #配置init.d启动 cp /usr/local/src/$version/misc/init.d/fedora/core/zabbix_agentd /etc/init.d/zabbix_agentd sed -i 's/BASEDIR=\/usr\/local/BASEDIR=\/usr\/local\/$version/g' /etc/init.d/zabbix_agentd #配置开机启动 chkconfig --add zabbix_agentd chkconfig zabbix_agentd on /etc/init.d/zabbix_agentd start #查看zabbix启动 netstat -lnp |grep zabbix if [ $? -eq 0 ] then echo "Zabbix agent install have completed." fi
思路:
由于需要批量部署zabbix 客户端,简化操作流程,在这样的条件下写了这个脚本。
1.安装系统所需要的依赖插件
2.把客户端源码放在指定位置进行解压处理
3.检查系统用户是否存在
4.对配置进行修改处理
5.启动进行检测
[root@localhost opt]# cat web_url.sh
#!/bin/bash
for i in `cat web_url`
do
curl=`curl -I -s $i |head -1|cut -d " " -f2`
if [ "$curl" == "200" ];then
echo curl $i is ok
else
echo "$i is fail" | mail -s "web fail url" yunwei@jiduo365.com
fi
done
[root@localhost opt]# cat web_url
http://192.168.0.123:8080/lemon/portal/index.do
http://192.168.0.123:8080/photo
思路:
由于内网环境处于调试初期阶段,服务不稳定,需要对指定的几个url进行做监控处理。
1.把需要尽快的url地址写到文档中
2.运用for循环来遍历url地址
3.检测状态码是否正常,正常则打印出来,不正常则把url 信息通过邮箱发送给管理员
#!/bin/bash #此脚本用于统计nginx日志距离当前时间15分钟之内不同接口的访问量统计 LOG=/usr/local/nginx/logs/interface.access.log TMP=/tmp/url.tmp URLSTATS=/var/log/interface_urlstats.log RECEIVERS="xmwang@etone.tv bliu@etone.tv jfxiao@etone.tv" #删除临时统计文件 [ -f $TMP ] && rm -fr $TMP for i in `seq 20` do d=`date +%d/%h/%Y:%H:%M -d "$i minutes ago"` #将每个时间段的URL进行统计并追加到临时文件 awk -v b="$d" '{if ($4 ~ b)a[$7]++}END{for(i in a)printf("%-42s %-d\n", i,a[i])}' $LOG >> $TMP done #将汇总到临时文件的URL统计进行汇总 if [ -s $TMP ];then awk '{a[$1]+=$2;}END{for(i in a)printf("%-42s %-d\n", i,a[i])}' $TMP | sort -nr -k2 > $URLSTATS mail -s "$(date +%F-%H:%M) 20分钟内URL访问量统计" "$RECEIVERS" <$URLSTATS else echo "需要统计的时间段日志文件没有被成功处理" fi
1. 根据seq循环15次并调用date获取最近的20分钟的时间,
2. 使用awk进行过滤日志并格式化打印,然后结合sort排序,
3. 最终过滤内容通过mail发送邮件
#!/bin/sh set -x logs_path="/usr/local/nginx/logs" oldlogs_path="/nginx_oldlogs/" for i in `ls $logs_path/* |grep -v nginx.pid |grep -v oldlogs` do mv "$i" "$i"_${HOS}_$(date -d "yesterday" +"%Y%m%d") mv "$i"_${HOS}_$(date -d "yesterday" +"%Y%m%d") $oldlogs_path done #向nginx主进程发信号重新打开日志 nginx_pid= `ps -ef |grep nginx|grep master|awk '{print $1}'` kill -USR1 $nginx_pid /usr/local/nginx/sbin/nginx -t && /usr/local/nginx/sbin/nginx -s reload sleep 2 #docker exec -it tengine /usr/local/nginx/sbin/nginx -s reopen #sleep 1 #clear the expired logs cd $oldlogs_path #find ./ -mtime +90 -exec rm -rf {} \; echo "The old logfiles is deleted!!"
思路:
对日志进行管理,结合cron每天进行切割,
1.定义日志的位置,及存储的位置。
2.对日志进行重新命名 移动到指定的位置
3.向nginx主进程发信号重新打开日志
4.对旧的日志进行删除处理
#!/bin/bash
USER=bak
PASSWD=123456
IO_SQL_STATUS=$(mysql -u$USER -p$PASSWD -e 'show slave status\G' |awk -F: '/Slave_.*_Running/{gsub(": ",":");print $0}') #gsub去除冒号后面的空格
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!"
fi
done
#!/usr/bin/expect
spawn ssh root@192.168.10.10
set timeout 10 //设置超时时间
expect "*password:"
send "nbc@123\r" //输入密码
expect {
"*yes/no" { send "yes\r"; exp_continue} //第一次ssh连接会提示yes/no,继续
"*password:" { send "$password\r" } //出现密码提示,发送密码
}
interact //交互模式,用户会停留在远程服务器上面.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。