网站建设优秀网站建,网站搭建的流程及费用是多少?,淘宝联盟个人网站怎么做,手机设置管理网站首页2019独角兽企业重金招聘Python工程师标准 导语 #xff1a; 在Linux环境下#xff0c;我们一般通过Shell来与内核交流#xff0c;并最终实现我们想要使用计算机资源的目的。由于Linux的开放性特点#xff0c;使得在Linux下对Shell的选择也很多#xff0c;Ce… 2019独角兽企业重金招聘Python工程师标准 导语 在Linux环境下我们一般通过Shell来与内核交流并最终实现我们想要使用计算机资源的目的。由于Linux的开放性特点使得在Linux下对Shell的选择也很多CentOS 6.3系统中可以使用的Shell有/bin/sh、/bin/bash、/bin/tcsh、/bin/csh这几种/etc/shells文件说明了当前系统有哪些可用的Shell。不同的Shell有不同的特点以及操作方式我们这里以CentOS默认使用的Shell为讲解案例即Bash。 Linux下使用Shell处理文本时最常用的工具 CentOS 6.3默认通过/etc/profile文件定义了HISTSIZE1000也就是最多可以记录最近所使用的1000条命令当有第1001条命令执行时第一条命令会被覆盖执行history -c命令可以清空所有的历史记录。 记录命令历史的除了可以查看历史记录外还可以在需要时直接调用历史记录再次执行该命令 1上下键翻阅历史命令找到合适的命令后直接回车即可执行。 2. 输入!string调用命令历史string为关键字如!vim将调用最后一次执行的以vim开头的命令。或者通过!n来准确定位历史记录如!242将直接调用命令历史的第242条记录并执行。 3. 通过Ctrlr快捷键打开搜索功能接着输入关键字即可在命令历史中搜索相关命令回车完成执行操作。如果没有搜索到适合的命令按ESC键退出搜索。 标准输入的文件描述符为0标准输出的文件描述符为1错误输出的文件描述符为2。但有时我们需要改变这样的标准输入与输出方式Linux中我们可以使用重定向符、、、、|重新定义输入与输出。 管道符|的使用案例使用ifconfig eth0 | grep ‘inet addr’命令过滤包含IP地址的行ifconfig本身会输出大量网络接口的信息由于这里使用了管道符号|所以ifconfig命令的所有输出都将作为grep命令的输入内容最终实现过滤包含IP地址的行。 以下通过几个简单的实例演示重定向的使用方法 Bash快捷键 花括号{}的使用 一、SHELL编程概念 1SHELL、SHELL编程、SHELL脚本、SHELL命令区别 Shell命令解释器是用户和操作系统沟通的桥梁 Shell编程基于Shell解释器实现软件自动化功能 Shell编程语言是非类型的解释型语言。 SHELL脚本实现Shell编程实体 SHELL命令具体实现某个功能、内容的指令 SHELL变量两种局部变量和环境变量赋值符号使用$符号引用 SHELL编程变量三种系统变量、环境变量、用户变量 shel脚本变量类型 : 局部变量、环境变量、shell变量 元字符通常在Linux中分为两类 Shell元字符由Linux Shell进行解析 正则表达式元字符由vi/grep/sed/awk等文本处理工具进行解析 SHELL种类 sh/dash/bash/ash/zsh SHELL 配制文件 ~/.bashrc , .bash_profile , .environmnet 查询当前shell下的进程 ps -o pid,ppid,cmd Bash两种工作模式 互动模式 、Shell Script模式 互动模式 系统管理员由键盘键入命令必须等待shell执行该命令之后才能继续执行下一个命令。 Shell Script模式 管理这可以设计shell script ,把要执行的命令写在一个文件中交友Bash去读取和执行。 bash变量类型 环境变量、本地变量局部变量、位置变量、特殊变量 本地变量 VARNAMEVALUE :作用域为整个bash进程 局部变量 local VARNAMEVALUE : 作用域为当前代码段 环境变量 作用域为当前shell进程及其子进程 export VARNAMEVALUE VARNAMEVALUE export VARNAME 导出 位置变量 $1,$2........ 注意 使用chsh命令可以改变默认的shell。 # chsh 用户名 -s 新shell
# chsh linuxtechi -s /bin/sh 特殊变量 $ : 上一个命令的执行状态返回值 * : 代表任意的字符串可以是空字符串 ? : 代表一个字符单不可以为空 $# :计算传递进来的参数 $0 : 在脚本中获取脚本名称 $? : 检查之前的命令是否运行成功 tail-1 : 获取文件的最后一行 head-1 : 获取文件的第一行 awk{print $3} : 获取一个文件每一行的第三个元素 awk{ if ($1 FIND) print $2} :文件中每行第一个元素是 FIND如何获取第二个元素 调试 bash 脚本 将 -xv 参数加到 #!/bin/bash 后 例子 #!/bin/bash –xv 程序执行 可能有两类返回值 程序执行结果 程序状态码返回代码0-255 0正确执行 1-255 错误执行12127系统预留 输出重定向 2 2 撤销变量 unset VARNAME 查看当shell中变量 set 查看当前shell中的环境变量 printenv env export 脚本 命令的堆砌按实际需要结合命令流程控制机制实现的源程序。 在大多数Linux和其他类Unix系统上默认的shell是Bash。 SHELLSHELL编程SHELL脚本SHELL命令关系 SHELL编程变量定义存储到内存中除非你的SHELL终端断开否则一直长存内存缓冲区变量名称不能使用特殊符号变量名称之间不能使用-横杠可以使用_下划线 SHELL编程变量变量名和变量值中间使用不能使用空格SHELL变量用途主要减少重复去调用化复杂为简单化简单为自动化 SHELL编程思想通过手工操作的Linux/SHELL命令进行堆积 脚本在执行时会启动一个子shell进程 命令行中启动的脚本会继承当前 shell环境变量 系统自动执行的脚本非命令启动就需要自定义需要各环境变量 Shell的工作原理 Shell可以被称作是脚本语言因为它本身是不需要编译的而是通过解释器解释之后再编译执行和传统语言相比多了解释的过程所以效率会略差于传统的直接编译的语言。 注意事项 1开头加解释器#!/bin/bash 2语法缩进使用四个空格多加注释说明。 3命名建议规则变量名大写、局部变量小写函数名小写名字体现出实际作用。 4默认变量是全局的在函数中变量local指定为局部变量避免污染其他作用域。 5有两个命令能帮助我调试脚本set -e 遇到执行非0时退出脚本set-x 打印执行过程。 6写脚本一定先测试再到生产上。 SHELL和SHELL编程概念 1 SHELLSHELL是一款命令解释器用户可以输入指令传递给SHELLSHELL指令传递到Linux内核Linux内核处理数据处理完毕之后将数据返回给SHELL需要经过SHELL解释解释完毕之后将最终的数据返回给用户 2 SHELL是一个中间件位于用户和Linux内核之间的是用户和Linux内核的沟通桥梁 3 SHELL是中间件可以看成是一款软件软件的种类 4 SHELL编程基于SHELL解释器执行的各种指令和代码从而实现各种需求 5 SHELL编程的产物是SHELL脚本脚本文件脚本文件中写入单个或者多个Linux指令以实现某个具体的功能 6bash的配置文件 profile类 : 登录式shell bashrc类 : 非登录式shell 登录式shell /etc/profile--/etc/profile.d/*.sh--~/.bash_profile--/.bashrc---/etc/bashrc 非登录式shell ~/.bashrc--/etc/bashrc--/etc/profile.d/*.sh SHELL编程开始编程规范 1 任何的编程语言开始以打印世界你好表示开启新的一天 2 创建普通文件的指令touch、vi、vim、cat、echo、mv、cp等 3 基于编程工具vi、vim、gedit、sumlime、notepad等推荐使用vi和vim编程 4 SHELL编程内容第一行以#!开头其后接SHELL解释器的类型例如/bin/bash等正文每个功能写一行逐行编写 5 SHELL脚本在被执行时从上往下执行SHELL指令从上到下 Shell中的四则运算 运算符含义加法运算-减法运算*乘法运算/除法运算 其它运算符 、、!、、-o、-a 运算符含义%求余相等赋值!不相等!与-o或-a非 关系运算符 运算符含义-eq两个数相等返回true-ne两个数不相等返回true-gt左侧数大于右侧数返回true-It左侧数小于右侧数返回true-ge左侧数大于等于右侧数返回true-le左侧数小于等于右侧数返回true 测试两个数值是否相等 [rootlocalhost ~]# [ 1024 -eq 1024 ] //测试1024是否等于1024
[rootlocalhost ~]# echo $?
0 //两个数值相等
修改第一个数值为1124后再次进行测试。
[rootlocalhost ~]# [ 1124 -eq 1024 ]
[rootlocalhost ~]# echo $?
1 //两个数值不相等
[rootlocalhost ~]# number1500 //number1为500
[rootlocalhost ~]# number2254 //number2为254
[rootlocalhost ~]# [ $number1 -gt $number2 ]
[rootlocalhost ~]# echo $?
0 //number1大于number2
[rootlocalhost ~]# 字符串运算符 运算符含义两个字符串相等返回true!两个字符串不相等返回true-z字符串长度为0返回true-n 字符串长度不为0返回true 运算符 含义-d file检测文件是否是目录如果是则返回 true-r file检测文件是否可读如果是则返回 true-w file检测文件是否可写如果是则返回 true-x file检测文件是否可执行如果是则返回 true-s file检测文件是否为空文件大小是否大于0不为空返回 true-e file检测文件包括目录是否存在如果是则返回 true 要测试两个字符串是否相等
[rootlocalhost ~]# [ abc abc ]
[rootlocalhost ~]# echo $?
0 //两个字符串相等
把第一个字符串更改为bac后进行测试
[rootlocalhost ~]# [ bac abc ]
[rootlocalhost ~]# echo $?
1 //两个字符串不相等
如果把运算符改为“!”
[rootlocalhost ~]# [ bac ! abc ]
[rootlocalhost ~]# echo $?
0
判断环境变量是否为空或者非空
[rootlocalhost ~]# [ -z $python1 ]
[rootlocalhost ~]# echo $?
0
[rootlocalhost ~]# [ -n $python1 ]
[rootlocalhost ~]# echo $?
0 //python1变量为空
[rootlocalhost ~]# python1test //对python1变量进行赋值
[rootlocalhost ~]# [ -z $python1 ]
[rootlocalhost ~]# echo $?
1 //python1变量不为空
[rootlocalhost ~]# 条件测试的逻辑操作符 逻辑操作符分以下3种 -a逻辑与只有当操作符两边的条件均为真时结果为真否则为假。 -o逻辑或操作符两边的条件只要有一个为真结果为真只有当两边所有条件为假时结果为假。 !逻辑否条件为假结果为真。 如果要测试两个文件的状态
[rootlocalhost 20190105]# ll test1 test2
-rw-rw-r--. 1 root root 0 6月 4 09:25 test1
-rw-rw-r--. 1 root root 0 6月 4 09:25 test2
[rootlocalhost 20190105]# [ -r test1 -a -r test2 ] //测试文件 test1 和 test2 是否都可读
[rootlocalhost 20190105]# echo $?
0
[rootlocalhost 20190105]# [ -x test1 -o -x test2 ] //测试文件 test1 和 test2 是否至少有一个可执行
[rootlocalhost 20190105]# echo $?
1
如果要测试两个数值变量
[rootlocalhost 20190105]# number110
[rootlocalhost 20190105]# number220
[rootlocalhost 20190105]# [ $number1 -eq 10 -a $number2 -gt 20 ] //测试是否number1 大于10 且 number2 大于20
[rootlocalhost 20190105]# echo $?
1
如果要测试文件test1 是否为不可读
[rootlocalhost 20190105]# ls -l test1
-rw-rw-r--. 1 root root 0 6月 4 09:25 test1
[rootlocalhost 20190105]# [ ! -r test1 ] //测试文件test1 是否为不可读
[rootlocalhost 20190105]# echo $?
1
[rootlocalhost 20190105]# 条件测试的逻辑操作符 逻辑操作符分以下3种 -a逻辑与只有当操作符两边的条件均为真时结果为真否则为假。 -o逻辑或操作符两边的条件只要有一个为真结果为真只有当两边所有条件为假时结果为假。 !逻辑否条件为假结果为真。 如果要测试两个文件的状态
[rootlocalhost 20190105]# ll test1 test2
-rw-rw-r--. 1 root root 0 6月 4 09:25 test1
-rw-rw-r--. 1 root root 0 6月 4 09:25 test2
[rootlocalhost 20190105]# [ -r test1 -a -r test2 ] //测试文件 test1 和 test2 是否都可读
[rootlocalhost 20190105]# echo $?
0
[rootlocalhost 20190105]# [ -x test1 -o -x test2 ] //测试文件 test1 和 test2 是否至少有一个可执行
[rootlocalhost 20190105]# echo $?
1
如果要测试两个数值变量
[rootlocalhost 20190105]# number110
[rootlocalhost 20190105]# number220
[rootlocalhost 20190105]# [ $number1 -eq 10 -a $number2 -gt 20 ] //测试是否number1 大于10 且 number2 大于20
[rootlocalhost 20190105]# echo $?
1
如果要测试文件test1 是否为不可读
[rootlocalhost 20190105]# ls -l test1
-rw-rw-r--. 1 root root 0 6月 4 09:25 test1
[rootlocalhost 20190105]# [ ! -r test1 ] //测试文件test1 是否为不可读
[rootlocalhost 20190105]# echo $?
1
[rootlocalhost 20190105]# test命令 test $[num1] -eq $[num2] #判断两个变量是否相等
test num1num2 #判断两个数字是否相等 参数含义-e file文件存在则返回真-r file文件存在并且可读则返回真-w file文件存在并且可写则返回真-x file文件存在并且可执行则返回真-s file文件存在并且内容不为空则返回真-d file文件目录存在则返回真 Bash脚本的用法展示 一、条件选择、判断if·、case 二、四个循环for、while、until、select 三、循环里的一些命令与技巧continue、break、shift... 四、信号捕获trap 条件判断 如果用户不存在 添加用户给密码并显示添加成功 否则 显示如果以及没在没有添加 bash中如何实现条件判断 条件测试类型 整数测试 字符测试 文件测试 条件测试的表达式 [ expression ] [ [ expression ] ] test expression 整数比较 -eq : 测试两个整数是否相等比如$A -eq $B -ne : 测试两个整数是否不等不等为真相等为假 -gt : 测试一个数是否大于另一个数小于为真否则为假 -lt : 测试 一个数是否小于另一个数小于为真否则为假 -gt : 大于或等于 -gt : 小于或等于 命令的间逻辑关系 逻辑与 第一个条件为假时第二条件不用再判断最终结果已经有 第一个条件为真时第二条件必须得判断 逻辑或 如果用户user6 不存在就添加用户user6 ! id user6 useradd user6 id user6 || useradd user6 如果/etc/inittab文件的行数大于100就显示好大的文件。 [ wc -l /etc/inittab | cut -d -f1 -gt 100 ] echo Large file. 变量名称 1、只能包含字母、数字和下划线并且不能数字开头 2、不应该跟系统中已有的环境变量重名 3、最好做到见名知义 如果用户存在就显示用户已存在否则就添加此用户 id user1 echo user1 exists. || useradd user1 如果用户不存在就添加否则显示其已经存在 id user1 useradd user1 || echo user1 exists. 如果用户不存在添加并且给密码否则显示其已经存在 id user1 useradd user1 echo user1 | passwd --stdin user1 || echo user1 exists. shell中如何进行算术运算 A3 B6 1、let 算术运算表达式 let c$A$B 2、$[算术运算表达式] C$[$A$B] 3、$[算术运算表达式] C$(($A$B)) 4、expr算术运算表达式,表达式中各操作及运算符要有空格 而且要使用命令引用。 Cexpr $A $B 案例 给定一个用户判断其UID与GID是否一样如果一样就显示此用户为“good guy”: 否则就显示此用户为“bad guy” #!/bin/bash USERNAMEuser1 USERIDid -u $USERNAME GROUPIDid -g $USERNAME if [ $USEID -eq $GROUPID ];then echo Good guy else echo Bad guy fi 进一步要求不使用id命令获得其id号 #!/bin/bash # USERNAMEuser1 USERIDgrep ^USERNAME\ /etc/passwd | GROUPIDgrep ^USERNAME\ /etc/passwd | if [ $USERID - eq $ GROUPID ]; then echo Goo guy. else echo Bad guy. fi 二、Shell编程四剑客find、sed、awk、grep功能及用途 Find工具主要用于文件、文件夹的查找找到文件的路径 Sed工具非交互模式编辑器、vim交互式编辑器用于文件内容修改 Awk工具主要用于对文件内容进行处理、输出预定的结果 Grep工具主要用于操作系统文件内容的查找对文件的内容的操作匹配文件中的关键词 Find命令工具 主要用于对操作系统文件路径的查找 find path -option [ -print ] [ -exec -ok command ] { } \ find . 查找当前目录所有文件、文件夹find / -name test.txt|xargs rm -rf {} \;查找test.txt文件并删除find . -name *.txt -exec cp {} /root/ \;查找当前目录以.txt结尾文件并且将该文件cp至/root目录推荐使用exec恢复/tmp/下文件、目录原来权限 文件权限默认是644 目录权限默认是755 find . -type d -exec chmod 755 -R {} \;\结束标记修改当前目录类型是目录的权限改完默认权限 find . -type f -exec chmod 644 -R {} \; 修改当前目录类型是文件的权限改完默认权限 查找当前目录文件大小-size参数find . -size 20M -a -size -200M -exec rm -rf {} \;find . -name *.log ! -name access.log ! -name error.log -size 30M -size -40M -type f按天数、时间去查找文件及文件夹 find . -name *.log ! -name access.log ! -name error.log -mtime 30 -exec rm -rf {} \;-mtime -n n #按文件更改时间来查找文件-n指n天以内n指n天以前 -atime -n n #按文件访问时间来查找文件 -ctime -n n #按文件创建时间来查找文件 9.查找系统所有的以.rpm结尾的软件包并且将软件包拷贝至/root/20180327/; find / -name *.rpm -exec cp {} /root/20180327/ \; 10.find / -name httpd 查找系统httpd名称的文件或者目录 find / -name access.log 查找系统access.log路径 find /usr/ -name “*.log”查看以.log结尾的文件*表示0个或者多个匹配 查找当前目录名称以.log结尾是文件属性大小大于100M权限是644的文件 find . -name *.log -type f -size 100M -perm 644 ! -name test1.log atimeaccess time文件被访问的时间 ctimechange time文件属性被修改时间 mtimemodify time文件内容修改时间 查找txt文档修改时间小于一天大于5M权限755 查找log文件大于100M权限644去掉test1.log文件修改时间小于30分钟 find . -name *.log -type f -size 100M -perm 644 ! -name test1.log -mtime -30 -mmin -1 拷贝到/tmp目录、在当前目录只有一级目录 应用场景 根据你的需求假设网卡的配置文件 eth0查找网卡的配置文件修改IP 恢复权限 恢复文档文件权限 find . -type f -exec chmod -R 644 {} \; 恢复目录权限 find . -type d -exec chmod -R 755 {} \; 把大于5M的文件文档移到/tmp/目录 Sed命令工具 SED是一个非交互式文本编辑器它可对文本文件和标准输入进行编辑标准输入可以来自键盘输入、文本重定向、字符串、变量甚至来自于管道的文本与VIM编辑器类似它一次处理一行内容Sed可以编辑一个或多个文件简化对文件的反复操作、编写转换程序等。 在处理文本时把当前处理的行存储在临时缓冲区中称为“模式空间”pattern space紧接着用SED命令处理缓冲区中的内容处理完成后把缓冲区的内容输出至屏幕或者写入文件。 逐行处理直到文件末尾然而如果打印在屏幕上实质文件内容并没有改变除非你使用重定向存储输出或者写入文件。其语法参数格式为 sed /^SELINUX/s/enforcing/disabled/g /etc/selinux/config #把enforcing/disabled/替换成/etc/selinux/config sed s/^SELINUX.*/SELINUXdisabled /g /etc/selinux/config #把所有的SELINUXdisabled替换成/etc/selinux/config 基于sed打印最大、最小值 238739 23923823 322938293829832 328922222222228 2382938923 -293238293 使用#sed s/ /\n/g test.txt|grep -v ^$|sort -n|sed -n 1p;$p查询 -8923293892839283928 3242348923233232323 匹配IP地址 严格匹配IP地址 意思同上 shell变量为弱类型定义变量不需要声明类型但使用时需要明确变量大的类型可以是使用Declare指定类型Declare常见参数 /- -可用来指定变量的属性“”为取消变量所设的属性 -f 仅显示函数 r 将变量设置为只读 x 指定的变量会成为环境变量可供shell以外的程序来使用。 i 指定类型为数值字符串或运算符 SHELL变量详解 变量是一个可变的值SHELL变量主要是为了减少重复引用SHELL变量是弱类型使用时直接赋值即可ABC123ABC是变量名称123位变量的值SHELL变量在定义的时候不需要声明可以声明declare声明 shell使用案例 #/bin/bash wget https://mirrors.tuna.tsinghua.edu.cn/apache/httpd/httpd-2.4.27.tar.bz2 yum update apr apr-devel apr-util apr-util-devel -y tar -xf httpd-2.4.27.tar.bz2 cd httpd-2.4.27 ./configure --prefix/usr/local/apache2/ --enable-so --enable-rewrite --enable-ssl make make install 2、自动删除test.txt文件脚本脚本的功能实现从/root/目录cp拷贝test.txt到/tmp目录并且在/tmp目录创建一个目录abc,并且删除原/root下test.txt。 #/bin/bash #the auto cp file and rm files FILES/root/test.txt #把/root/test.txt定义为FILES DIR/tmp #把/tmp定义为DIR cp $FILES $DIR mkdir -p $DIR/abc rm -rf $FILES echo -------------- echo The shell exec scuccessful 2Shell编程特点 q 语法和结构通常比较简单 q 学习和使用通常比较简单 q 基于Shell解释器运行不需要编译运行 q 程序的开发产能优于运行效能。 3Linux Shell的种类非常多常见的SHELL分类 q Bourne Shell/usr/bin/sh或/bin/sh q Bourne Again Shell/bin/bash最常用大部分系统自带 q C Shell/usr/bin/csh q K Shell/usr/bin/ksh q Shell for Root/sbin/sh 注shell是操作系统的最外层shell可以合并编程语言以控制进程和文件以及启动和控制其他程序。 简单来说shell就是一个用户跟操作系统之间交互的命令解释器 如图shell在系统各种的位置 shell独立于内核它是链接内核和应用程序的桥梁。内核是linux系统的心脏从开机自检就驻扎在计算机内存中直到计算机关闭为止。用户的应用程序存储在计算机硬盘上仅当需要时才被调入内存。shell是一种应用程序当用户登陆linux系统时shell就会被调用到内存执行。 查看常见的shell解释器 [rootlocalhosts ~]# cat /etc/shells /bin/sh /bin/bash /sbin/nologin /bin/tcsh /bin/csh 注意/bin/bash是大多数linux中默认的shell解释器。之后的所有脚本的编写都是bash脚本 我们来编写第一个脚本frist.sh linux不以后缀名区分文件为了方便记忆这里我就以.sh为结尾 写第一个脚本 [rootlocalhosts 桌面]# vim first.sh #!/bin/bash #auto my frist scripts #by authors cd echo hello world mkdir /root/shell free -m 注释 #/bin/bash 主要是为了声明我所写的均为bash语言(我是用的是bash解释器)[定义我的脚本是shell脚本].{固定格式} 第二行为注释行注释信息不生效 #auto echo hello world! #by authors tree 2016 本脚本是由谁来写的写这个是为了完成什么目的。 执行过程 [rootlocalhosts ~]# ll first.sh #查看是否具有执行权限 -rw-r--r-- 1 root root 65 Aug 30 06:50 first.sh [rootlocalhosts ~]# chmod ox first.sh #添加执行权限 [rootlocalhosts ~]# ll first.sh #查看是否具有执行权限 -rwxr-xr-x 1 root root 65 Aug 30 06:50 first.sh 执行的结果 [rootlocalhosts ~]# ./first.sh
hello worldtotal used free shared buffers cachedMem: 2006 728 1277 0 28 330
-/ buffers/cache: 370 1636
Swap: 1999 0 1999或者可以用 /bin/bash/脚本来执行这样的就不需要加权限了。 编写LAMP YUM自动安装脚本 [rootlocalhosts ~]# vim lamp.sh
#!/bin/bash
#2018/5/23
#auto install linux for lamp
#Intall HTTP WEB service yum install httpd httpd-devel -y
#Intall MYSQL service
yum install mysql-server mysql mysql-devel –y
#Intall PHP service
yum install php php-devel php-mysql –y
#启动httpd和mysql服务,并关闭防火墙和selinux
/etc/init.d/httpd restart
/etc/init.d/mysqld restart
/etc/init.d/iptables stop
setenforce 0
echo The shell script Exec Success.
exit 执行脚本,就能自动安装LAMP了。 [rootlocalhosts ~]# sh lamp.sh 使用命令/var/www/html/phpinfo.php 追加到/var/www/html/phpinfo.php 中。 执行脚本的不同方式 第一种使用绝对路径执行 例如 /bin/bash first_shell.sh 第二种使用相对路径执行如./的方式 ./first_shell.sh 第三种使用 sh命令来执行 格式 sh 脚本名 不需要执行权限 sh first_shell.sh 第四种使用 . (空格)脚本名称的方式执行 不需要执行权限 . a.sh 第五种使用 source 脚本名称 不需要执行权限(主要用于生效配置文件) 注意建议使用后三种,在生产环境中不要轻易的给文件可执行权限; 执行脚本的方法 $source ./script.sh 或者 $ . ./script.sh source或者.命令是shell的内建命令这种方式也不会创建子shell,而是直接在交互式 shell下逐行执行脚本中的命令。 2、变量 变量用来保存有用信息比如路径名文件名数字等变量的本质是存储数据的一个或多个计算机内存地址 接下来我们来探讨脚本中作重要的东西---变量,变量的定义是可以存放一个可变的值的空间 可以通过不同的环境进行改变就是一个可以变的值. 默认情况下: 在Linux中可以将每个shell看成不同的执行环境,所以相同的一个变量名称在不同的变量执行环境中的变量值是不同的. 常见的shell变量分类 自定义变量、环境变量、位置变量、预定义变量 变量的输出 一般使用echo 输出变量 echo $变量名 shell变量总结 1. 声明变量不用声明类型 2. 可以存储不同类型内容 3. 使用时要明确变量类型 区分大小写。 自定义变量 自定义变量是用户根据自己的环境自己定义的变量,Bash中比较简单的变量; 不用进行提前声明而是直接指定变量名称并赋给初始值; 定义变量的基本格式为 变量名变量值 要求: 等号两遍不允许出现空格; 变量名称只能以字母和下划线开头名称中不能包含、- * 、 / . , 、 % * 等一些特殊字符. 举例 var”hello world” 变量名的命名须遵循如下规则 首个字符必须为字母a-zA-Z。 中间不能有空格可以使用下划线_。 不能使用标点符号。 不能使用bash里的关键字可用help命令查看保留关键字。 变量的使用 格式$变量名或者${变量名} echo $var 或者echo ${var} 举例: 来进行定义一个变量名字为Linux值为7.2 [rootlocalhosts ~]# Linux7.2 #为变量Linux赋值 [rootlocalhosts ~]# echo $Linux #输出变量Linux的值 7.2 [ro[rootlocalhosts ~]# linux6.5 #为变量linux赋值 [ro[rootlocalhosts ~]# echo $linux #输出变量linux的值 6.5 可以直接在命令行定义一个变量并赋予值通过echo进行输出变量 $是引用变量的特殊字符必须使用$符号 echo和调用的变量之间必须要有空格 注意大小写的变量的值是不同的 举例2:当需要一起调用两组变量时 [rootlocalhosts ~]#echo $Linux $linux 7.2 6.5 直接使用echo 后面跟$调用的变量 如果有多个则空格隔开 举例3:当变量名和后面的字符容易混淆的时候应该使用{}将变量名括起来 [rootlocalhosts ~]#echo system{$Linux} system{7.2} 取消变量 语法unset 变量 [rootlocalhosts ~]# unset linux [rootlocalhosts ~]# echo $linux 其他的特殊操作 双引号( ) 1.当号右边赋值出现空格的时候需要使用双引号将其扩起 [rootlocalhosts ~]# webserver nginx 1.11 [rootlocalhosts ~]# echo $webserver nginx 1.11 2、来看下没有引号有单引号和双引号的区别 # Ya # echo $Y a # echo $x $x # echo $x a read命令 除了上面的赋值之外还可以使用read命令进行赋值read命令用来提示用户输入信息从而实现简单的交互式过程其实我们所输入的命令就是一种交互式的过程 执行时需要从标准输入设备键盘读取一行并以空格为分隔符 执行时需要从标准输入设备键盘读取一行并以空格为分隔符 [rootxuegod63 ~]# read kernel system #同时定义两个变量操作 3.10 7.2 -à手动输入的变量值 由于read命令提供了-p参数这里可以缩写为 #!/bin/bash #by authors tree 20160904 read -p Enter your name: name echo hello $name,welcome to my class exit 0 注意 由于使用read存在一定的风险既有可能需要等待用户输入但用户一直不输入就没法继续运行。 这时候可以使用read的另外一个参数-t -t是一个计时器指定read命令需要等待输入的秒数当计时满时直接返回一个非零退出状态。 #!/bin/bash if read -t 5 -p please enter your name: name then echo hello $name ,welcome to my script else echo sorry,too slow fi exit 0 SHELL编程实战优化 SHELL脚本优化引入变量 SHELL变量是一个可变的值跟常量是对应关系常量是一个固定的值变量可变 变量相当于别名xiaoming110101199410234012获取身份证ID号$xiaoming SHELL脚本引入if、for、while、case条件判断检查SHELL脚本功能、需求是否有缺陷检查SHELL脚本能否扩展批量生产 SHELL9个实例 1、 获取随机字符串或数字 获取随机8位字符串 获取随机8位数字 2 、定义一个颜色输出字符串函数 3、 批量创建用户 4 、检查软件包是否安装 5、 检查服务状态 6 、检查主机存活状态 方法1 将错误IP放到数组里面判断是否ping失败三次 方法2 将错误次数放到FAIL_COUNT变量里面判断是否ping失败三次 方法3 利用for循环将ping通就跳出循环继续如果不跳出就会走到打印ping失败 7 、监控CPU、内存和硬盘利用率 1CPU 借助vmstat工具来分析CPU统计信息。 2内存 3硬盘 8 、批量主机磁盘利用率监控 前提监控端和被监控端SSH免交互登录或者密钥登录。 写一个配置文件保存被监控主机SSH连接信息文件内容格式IP User Port 9 、检查网站可用性 1检查URL可用性 2判断三次URL可用性 思路与上面检查主机存活状态一样。 10、用ping命令统计某个网段的IP状态如192.168.0200到254之间的IP登录状态情况。 答 #/bin/bash # NET192.168.0 trap echo quit .;exit 1INT #添加捕捉信号按CTRLC退出 for I in {200..254}; do if ping -c 1 -W 1 $NET.$I /dev/null; then echo $NET.$I is up. else echo $NET.$I is down. fi done 11、查看用户有没有登录并每个一段时间刷新。 #!/bin/bash # who |grep hadoop /dev/null RETVAL$? until [ $RETVAL -eq 0 ]; do echo hadoop is no come. sleep 5 who | grep hadoop /dev/null RETVAL$? done echo hadoop is logged in. 12、100以内正整数的和 #!/bin/bash declare -i SUM0 for I in (1..100); do let SUM$I done echo $SUM declare -i SUM20 for ((J2,I100,J2)); do let SUM2$J done echo $SUM2 13、写一个猜数字脚本当用户输入的数字和预设数字随机生成一个小于100的数字一样时直接退出否则让用户一直输入并且提示用户的数字比预设数字大或者小。 答 #!/bin/bash mecho $RANDOM n1$[$m%100] while : do read -p Please input a number: n if [ $n $n1 ] then break elif [ $n -gt $n1 ] then echo bigger continue else echo smaller continue fi done echo You are right. 14、1、写一个脚本执行后输入名字产生随机数01-99之间的数字。 2、如果相同的名字重复输入抓到的数字还是第一次抓取的结果 3、前面已经抓到的数字下次不能在出现相同数字。 4、第一个输入名字后屏幕输出信息并将名字和数字记录到文件里程序不能退出 继续等待别的学生输入。 while : do read -p Please input a name: name if [ -f /work/test/1.log ];then bbcat /work/test/1.log | awk -F: {print $1} | grep $name if [ $bb ! $name ];then #名字不重复情况下 aaecho $RANDOM | awk -F {print $2 $3} while : do ddcat /work/test/1.log | awk -F: {print $2} | grep $aa if [ $aa $dd ];then #数字已经存在情况下 echo 数字已存在. aaecho $RANDOM | awk -F {print $2 $3} else break fi done echo $name:$aa | tee -a /work/test/1.log else aacat /work/test/1.log | grep $name | awk -F: {print $2} #名字重复 echo $aa echo 重复名字. fi else aaecho $RANDOM | awk -F {print $2 $3} echo $name:$aa | tee -a /work/test/1.log fi done 15、写一个猜数字脚本当用户输入的数字和预设数字随机生成一个小于100的数字一样时直接退出否则让用户一直输入并且提示用户的数字比预设数字大或者小。 #!/bin/bash mecho $RANDOM n1$[$m%100] while : do read -p Please input a number: n if [ $n $n1 ] then break elif [ $n -gt $n1 ] then echo bigger continue else echo smaller continue fi done echo You are right. 16、创建一个函数能接受两个参数 1)第一个参数为URL即可下载的文件第二个参数为目录即下载后保存的位置 2)如果用户给的目录不存在则提示用户是否创建如果创建就继续执行否则函数返回一个51的错误值给调用脚本 3)如果给的目录存在则下载文件下载命令执行结束后测试文件下载成功与否如果成功则返回0给调用脚本否则返回52给调用脚本 提示在函数中返回错误值给调用脚本使用return 答 #!/bin/bash if [ ! -d $2 ] then echo please make directory exit 51 fi cd $2 wget $1 necho $? if [ $n -eq 0 ];then exit 0 else exit 52 fi 17、脚本的功能 脚本可以带参数也可以不带参数可以有多个每个参数必须是一个目录脚本检查参数个数若等于0则列出当前目录本身否则显示每个参数包含的子目录。 #!/bin/bash if [ $# 0 ] then ls -ld pwd else for i in seq 1 $# do a$i echo ls ${!a} ls -l ${!a} |grep ^d done fi 标注 你可能会对${!a}有疑问这里是一个特殊用法在shell中$1为第一个参数$2为第二个参数以此类推那么这里的数字要是一个变量如何表示呢比如n3,我想取第三个参数能否写成 $$n shell中是不支持的那怎么办 就用脚本中的这种方法 a$n, echo ${!a} 18、提示用户输入网卡的名字然后我们用脚本输出网卡的ip。 看似简单但是需要考虑多个方面比如我们输入的不符合网卡名字的规范怎么应对。名字符合规范但是根本就没有这个网卡有怎么应对。 #!/bin/bash while : do read -p 请输入网卡名: e e1echo $e | sed s/[-0-9]//g e2echo $e | sed s/[a-zA-Z]//g if [ -z $e ] then echo 你没有输入任何东西 continue elif [ -z $e1 ] then echo 不要输入纯数字在centos中网卡名是以eth开头后面加数字 continue elif [ -z $e2 ] then echo 不要输入纯字母在centos中网卡名是以eth开头后面加数字 continue else break fi done ip() { ifconfig | grep -A1 $1 |tail -1 | awk {print $2} | awk -F : {print $2} } myipip $e if [ -z $myip ] then echo 抱歉没有这个网卡。 else echo 你的网卡IP地址是$myip fi 19、写一个脚本执行后打印一行提示“Please input a number:要求用户输入数值然后打印出该数值然后再次要求用户输入数值。直到用户输入end停止。 #!/bin/bash while : do read -p Please input a number:(end for exit) n num echo $n |sed -r s/[0-9]//g|wc -c if [ $n end ] then exit elif [ $num -ne 1 ] then echo what you input is not a number!Try again! else echo your input number is: $n fi done 20、使用传参的方法写个脚本实现加减乘除的功能。例如 sh a.sh 1 2这样会分别计算加、减、乘、除的结果。 要求 1 脚本需判断提供的两个数字必须为整数 2 当做减法或者除法时需要判断哪个数字大 3 减法时需要用大的数字减小的数字 4 除法时需要用大的数字除以小的数字并且结果需要保留两个小数点。 #!/bin/bash if [ $# -ne 2 ] then echo The number of parameter is not 2, Please useage: ./$0 1 2 exit 1 fi is_int() { if echo $1|grep -q [^0-9] then echo $1 is not integer number. exit 1 fi } max() { if [ $1 -ge $2 ] then echo $1 else echo $2 fi } min() { if [ $1 -lt $2 ] then echo $1 else echo $2 fi } sum() { echo $1 $2 $[$1$2] } minus() { bigmax $1 $2 smallmin $1 $2 echo $big - $small $[$big-$small] } mult() { echo $1 * $2 $[$1*$2] } div() { bigmax $1 $2 smallmin $1 $2 decho scale 2; $big / $small|bc echo $big / $small $d } is_int $1 is_int $2 sum $1 $2 minus $1 $2 mult $1 $2 div $1 $2 21、写一个脚本 计算100以内所有能被3整除的正整数的和 #!/bin/bash sum0 for i in {1..100};do if [ $[$i%3] -eq 0 ];then sum$[$i$sum] fi done echo sum:$sum 22、 #!/bin/bash #written by aming. if [ $# -eq 0 -o $# -gt 2 ] then echo use $0 --add username or $0 --del username or $0 --help. exit 1 fi case $1 in --add) n0 for u in echo $2|sed s/,/ /g; do if awk -F: {print $1} /etc/passwd |grep -qw $u then echo The user $u exist. else useradd $u echo -e $u\n$u|passwd $u /dev/null 21 echo The user $u added successfully. n$[$n1] fi done if [ $n -eq 0 ]; then exit 2 fi ;; --del) n0 for u in echo $2|sed s/,/ /g; do if awk -F: {print $1} /etc/passwd|grep -qw $u then userdel -r $u echo The user $u deleted successfully. n$[$n1] else echo The user $u not exist. fi done if [ $n -eq 0 ]; then exit 3 fi ;; --help) echo -e --add can add user,and the passwd is the same as username. It can add multiuser such as --add user1,user2,user3... echo --del cat delete user.It can delete user such as --del user1,user2,user3... ;; *) echo use $0 --add username or $0 --del username or $0 --help. exit 1 ;; esac 23、要求如下 只支持三个选项 ‘--del’ ‘--add’ --help输入其他选项报错。 使用‘--add’需要验证用户名是否存在存在则反馈存在。且不添加。 不存在则创建该用户切添加与该用户名相同的密码。并且反馈。 使用‘--del’ 需要验证用户名是否存在存在则删除用户及其家目录。不存在则反馈该用户不存在。 --help 选项反馈出使用方法 支持以分隔 一次删除多个或者添加多个用户。 能用echo $? 检测脚本执行情况 成功删除或者添加为0,报错信息为其他数字。 能以分割。一次性添加或者 删除多个用户。 例如 adddel.sh --add user1,user2,user3....... 不允许存在明显bug。 #!/bin/bash #written by aming. if [ $# -eq 0 -o $# -gt 2 ] then echo use $0 --add username or $0 --del username or $0 --help. exit 1 fi case $1 in --add) n0 for u in echo $2|sed s/,/ /g; do if awk -F: {print $1} /etc/passwd |grep -qw $u then echo The user $u exist. else useradd $u echo -e $u\n$u|passwd $u /dev/null 21 echo The user $u added successfully. n$[$n1] fi done if [ $n -eq 0 ]; then exit 2 fi ;; --del) n0 for u in echo $2|sed s/,/ /g; do if awk -F: {print $1} /etc/passwd|grep -qw $u then userdel -r $u echo The user $u deleted successfully. n$[$n1] else echo The user $u not exist. fi done if [ $n -eq 0 ]; then exit 3 fi ;; --help) echo -e --add can add user,and the passwd is the same as username. It can add multiuser such as --add user1,user2,user3... echo --del cat delete user.It can delete user such as --del user1,user2,user3... ;; *) echo use $0 --add username or $0 --del username or $0 --help. exit 1 ;; esac 24、假设当前MySQL服务的root密码为123456写脚本检测MySQL服务是否正常比如可以正常进入mysql执行show processlist并检测一下当前的MySQL服务是主还是从如果是从请判断它的主从服务是否异常。如果是主则不需要做什么 #!/bin/bash Mysql_cmysql -uroot -p123456 $Mysql_c -e show processlist /tmp/mysql_pro.log 2/tmp/mysql_log.err nwc -l /tmp/mysql_log.err|awk {print $1} if [ $n -gt 0 ] then echo mysql service sth wrong. else $Mysql_c -e show slave status\G /tmp/mysql_s.log n1wc -l /tmp/mysql_s.log|awk {print $1} if [ $n1 -gt 0 ] then y1grep Slave_IO_Running: /tmp/mysql_s.log|awk -F : {print $2}|sed s/ //g y2grep Slave_SQL_Running: /tmp/mysql_s.log|awk -F : {print $2}|sed s/ //g if [ $y1 Yes ] [ $y2 Yes ] then echo slave status good. else echo slave down. fi fi fi 25、写一个脚本判断你的Linux服务器里是否开启web服务监听80端口如果开启了请判断出跑的是什么服务是httpd呢还是nginx又或者是其他的什么 #!/bin/bash # if netstat -an | grep ^tcp | awk {print$4}| grep -q 80$;then echo Web Service:lsof -i:80 | awk {print$1} | grep -v COMMAND | sort | uniq else echo There is no Web Service fi 26、批量杀进程 把当前用户下所有进程名字中含有aming的进程关闭。 #!/bin/bash ps -u $USER |awk $NF ~ /aming/ {print $1}|xargs kill 27、用shell实现以并发进程的形式将mysql数据库所有的表备份到当前目录并把所有的表压缩到一个压缩包文件里。 假设数据库名字为mydb用户名为aming密码为passwd。 提示 在shell中加上可以将命令丢到后台从而可以同时执行多条命令达到并发的效果。 #!/bin/bash predate %F for d in mysql -uaming -ppasswd mydb -e show tables|grep -v Tables_in_ do mysqldump -uaming -ppasswd mydb $d $d.sql done tar czf $pre.tar.gz *.sql rm -f *.sql 28、有两个文件a.txt和b.txt需求是把a.txt中有的并且b.txt中没有的行找出来并写入到c.txt然后计算c.txt文件的行数。 #!/bin/bash nwc -l a.txt|awk {print $1} [ -f c.txt ] rm -f c.txt for i in seq 1 $n do lsed -n $ip a.txt if ! grep -q ^$l$ b.txt then echo $l c.txt fi done wc -l c.txt 或者用grep实现 grep -vwf b.txt a.txt c.txt wc -l c.txt 29、题目如下 a0.5 b3 ca*b 求c的值 #!/bin/bash a0.5 b3 cecho scale1;$a*$b|bc echo $c 30、需求是把所有的成员平均得分成若干个小组。这里我会提供一个人员列表比如成员有50人需要分成7个小组要求随机性每次和每次分组的结构应该不一致。 假设成员列表文件为members.txt #!/bin/bash fmembers.txt nwc -l $f|awk {print $1} get_n() { lecho $1|wc -c n1$RANDOM n2$[$n1$l] g_id$[$n1%7] if [ $g_id -eq 0 ] then g_id7 fi echo $g_id } for i in seq 1 7 do [ -f n_$i.txt ] rm -f n_$i.txt done for i in seq 1 $n do namesed -n $ip $f gget_n $name echo $name n_$g.txt done nu(){ wc -l $1|awk {print $1} } max(){ ma0 for i in seq 1 7 do nnu n_$i.txt if [ $n -gt $ma ] then ma$n fi done echo $ma } min(){ mi50 for i in seq 1 7 do nnu n_$i.txt if [ $n -lt $mi ] then mi$n fi done echo $mi } ini_min1 while [ $ini_min -le 7 ] do m1max m2min ini_minm2 for i in seq 1 7 do nnu n_$i.txt if [ $n -eq $m1 ] then f1n_$i.txt elif [ $n -eq $m2 ] then f2n_$i.txt fi done nametail -n1 $f1 echo $name $f2 sed -i /$name/d $f1 ini_min$[$ini_min1] done for i in seq 1 7 do echo $i 组成员有 cat n_$i.txt echo done 31、将文件内所有的单词的重复次数计算出来只需要列出重复次数最多的10个单词。 假设文档名字叫做a.txt sed s/[^a-zA-Z]/ /g a.txt|xargs -n1 |sort |uniq -c |sort -nr |head 32、设计一个shell程序在每月第一天备份并压缩/etc目录的所有内容存放在/root/bak目录里且文件名为如下形式yymmdd_etc.tar.gzyy为年mm为月dd为日。 #!/bin/sh if [ -d /root/bak ] then mkdir /root/bak fi prefixdate %y%m%d ddate %m if [ $d 01 ] then cd /etc/ tar czf /root/bak/$prefix_etc.tar.gz ./ fi 33、在文本文档1.txt第5行后面增加如下内容 # This is a test file. # Test insert line into this file. 答 sed -i 5a # This is a test file.\n# Test insert line into this file. 1.txt 34、写一个shell脚本。提示你输入一个暂停的数字然后从1打印到该数字。然后询问是否继续。继续的话在输入个在数字 接着打印。不继续退出。 例如果输入的是5打印1 2 3 4 5 然后继续 输入15 然后打印 6 7 ...14 15 依此类推。 #!/bin/bash read -p 请输入您想要暂停的数字 number_1 for i in seq 1 $number_1; do echo $i done read -p 是否继续输入数字 a if [ $a yes ];then read -p 请继续输入您想要暂停的数字 number_2 number_3$[$number_11] if [ $number_2 -gt $number_1 ];then for h in seq $number_3 $number_2; do echo $h done else echo 输入数字错误请输入大于的数字! fi else exit fi 35、已知nginx访问的日志文件在/usr/local/nginx/logs/access.log内 请统计下早上10点到12点 来访ip最多的是哪个? 日志样例 111.199.186.68 - [15/Sep/2017:09:58:37 0800] //plugin.php?idsecurity:job 200 POST //plugin.php?idsecurity:job HTTP/1.1http://a.lishiming.net/forum.php?modviewthreadtid11338extrapage%3D1%26filter%3Dauthor%26orderby%3Ddateline Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3141.7 Safari/537.36 0.516 203.208.60.208 - [15/Sep/2017:09:58:46 0800] /misc.php?modpatchactionipnotice_r0.05560809863330207inajax1ajaxtargetip_notice 200 GET /misc.php?modpatchactionipnotice_r0.05560809863330207inajax1ajaxtargetip_notice HTTP/1.1http://a.lishiming.net/forum.php?modforumdisplayfid65filterauthororderbydateline Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3141.7 Safari/537.36 0.065 答 grep 15/Sep/2017:1[0-2]:[0-5][0-9]: /usr/local/nginx/logs/access.log|awk {print $1}|sort -n|uniq -c |tail -n1 36、一个同学提到一个问题他不小心用iptables规则把sshd端口22给封掉了结果不能远程登陆要想解决这问题还要去机房登陆真机去删除这规则。 问题来了要写个监控脚本监控iptables规则是否封掉了22端口如果封掉了给打开。 写好脚本放到任务计划里每分钟执行一次。 #!/bin/bash # check sshd port drop /sbin/iptables -nvL --line-number|grep dpt:22|awk -F {print $4} /tmp/drop.txt icat /tmp/drop.txt|head -n 1|egrep -iE DROP|REJECT|wc -l if [ $i -gt 0 ] then /sbin/iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT fi 37、需求将用户家目录考虑到执行脚本的用户可能是普通用户也可能是root下面小于5KB的文件打包成tar.gz的压缩包并以当前日期为文件名前缀例如今天打包的文件为2017-09-14.tar.gz。 #!/bin/bash tdate %F cd $HOME tar czf $t.tar.gz find . -type f -size -5k 38、写一个shell脚本通过curl -I 返回的状态码来判定所访问的网站是否正常。比如当状态码为200时才算正常。 #/bin/bash urlhttp://www.apelearn.com/index.php stacurl -I $url 2/dev/null |head -1 |awk {print $2} if [ $sta ! 200 ] then python /usr/local/sbin/mail.py xxxqq.com $url down. $url down fi 39、1 每10分钟检测一次指定网卡的流量 2 如果流量为0则重启网卡 #!/bin/bash LANGen n1sar -n DEV 1 60 |grep eth0 |grep -i average|awk {print $5}|sed s/\.//g n2sar -n DEV 1 60 |grep eth0 |grep -i average|awk {print $6}|sed s/\.//g if [ $n1 000 ] [ $n2 000 ] then ifdown eth0 ifup eth0 fi 然后写个cron10分钟执行一次 40、用shell脚本判断输入的日期是否合法。就是判断日期是都是真实的日期比如20170110就是合法日期20171332就不合法。 #!/bin/bash #check date if [ $# -ne 1 ] || [ ${#1} -ne 8 ] then echo Usage: bash $0 yyyymmdd exit 1 fi datem$1 year${datem:0:4} month${datem:4:2} day${datem:6:2} if echo $day|grep -q ^0 then dayecho $day |sed s/^0// fi if cal $month $year /dev/null 2/dev/null then daymcal $month $year|egrep -v $year|Su|grep -w $day if [ $daym ! ] then echo ok else echo Error: Please input a wright date. exit 1 fi else echo Error: Please input a wright date. exit 1 fi 41、先判断是否安装http和mysql没有安装进行安装安装了检查是否启动服务若没有启动则需要启动服务。 说明操作系统为centos6httpd和mysql全部为rpm包安装。 #!/bin/bash if_install() { nrpm -qa|grep -cw $1 if [ $n -eq 0 ] then echo $1 not install. yum install -y $1 else echo $1 installed. fi } if_install httpd if_install mysql-server chk_ser() { p_nps -C $1 --no-heading |wc -l if [ $p_n -eq 0 ] then echo $1 not start. /etc/init.d/$1 start else echo $1 started. fi } chk_httpd chk_mysqld 42、写一个脚本产生随机3位的数字并且可以根据用户的输入参数来判断输出几组。 比如脚本名字为 number3.sh。 执行方法 bash number3.sh 直接产生一组3位数字。 bash number3.sh 10 插上10组3位数字。 思路 可以使用echo $RANDOM获取一个随机数字然后再除以10取余获取0-9随机数字三次运算获得一组。 #!/bin/bash get_a_num() { n$[$RANDOM%10] echo $n } get_numbers() { for i in 1 2 3; do a[$i]get_a_num done echo ${a[]} } if [ -n $1 ]; then mecho $1|sed s/[0-9]//g if [ -n $m ]; then echo Useage bash $0 n, n is a number, example: bash $0 5 exit else for i in seq 1 $1 do get_numbers done fi else get_numbers fi 43、写一个getinterface.sh 脚本可以接受选项[iI]完成下面任务 1使用一下形式getinterface.sh [-i interface | -I ip] 2当用户使用-i选项时显示指定网卡的IP地址当用户使用-I选项时显示其指定ip所属的网卡。 例sh getinterface.sh -i eth0 sh getinterface.sh -I 192.168.0.1 3当用户使用除[-i | -I]选项时显示[-i interface | -I ip]此信息。 4当用户指定信息不符合时显示错误。比如指定的eth0没有而是eth1时 #!/bin/bash ip add |awk -F : $1 ~ /^[1-9]/ {print $2}|sed s/ //g /tmp/eths.txt [ -f /tmp/eth_ip.log ] rm -f /tmp/eth_ip.log for eth in cat /tmp/eths.txt do ipip add |grep -A2 : $eth |grep inet |awk {print $2} |cut -d / -f 1 echo $eth:$ip /tmp/eth_ip.log done useage() { echo Please useage: $0 -i 网卡名字 or $0 -I ip地址 } wrong_eth() { if ! grep -q $1 /tmp/eth_ip.log then echo 请指定正确的网卡名字 exit fi } wrong_ip() { if ! grep -qw $1 /tmp/eth_ip.log then echo 请指定正确的ip地址 exit fi } if [ $# -ne 2 ] then useage exit fi case $1 in -i) wrong_eth $2 grep $2 /tmp/eth_ip.log |awk -F : {print $2} ;; -I) wrong_ip $2 grep $2 /tmp/eth_ip.log |awk -F : {print $1} ;; *) useage exit esac 44、比如1.txt内容 1 2 3 4 5 6 7 处理后应该是 1 2 3 4 5 6 7 sed N;N;s/\n/ /g 1.txt 45、先普及一小段知识,我们用ps aux可以查看到进程的PID而每个PID都会在/proc内产生。如果查看到的pid而proc内是没有的则是进程被人修改了这就代表你的系统很有可能已经被入侵过了。 请大家用上面知识编写一个shell定期检查下自己的系统是否被人入侵过。 #!/bin/bash ps aux|awk /[0-9]/ {print $2}|while read pid do resultfind /proc/ -maxdepth 1 -type d -name $pid if [ -z $result ]; then echo $pid abnormal! fi done 46、1 编写一个名为chname的程序将当前目录下所有的.txt文件更名为.doc文件。 2 编写一个名为chuser的程序执行中每隔5分钟检查指定的用户是否登录系统用户名从命令行输入如果指定的用户已经登录则显示相关信息。 #!/bin/bash find . -type f -name *.txt /tmp/txt.list for f in cat /tmp/txt.list do necho $f|sed -r s/(.*)\.txt/\1/ echo mv $f $n.doc done 2 #!/bin/bash read -p Please input the username: user while : do if who | grep -qw $user then echo $user login. else echo $user not login. fi sleep 300 done 47、1 编写一个名为ifuser的程序它执行时带用户名作为命令行参数判断该用户是否已经在系统中登录并给出相关信息。 2 编写一个名为menu的程序实现简单的弹出式菜单功能用户能根据显示的菜单项从键盘选择执行对应的命令。 1 #!/bin/bash read -p Please input the username: user if who | grep -qw $user then echo $user is online. else echo $user not online. fi 2. #!/bin/bash function message() { echo 0. w echo 1. ls echo 2.quit read -p Please input parameter: Par } message while [ $Par -ne 2 ] ; do case $Par in 0) w ;; 1) ls ;; 2) exit ;; *) echo Unkown command ;; esac message done 48、1 编写一个名为iffile程序它执行时判断/bin目录下date文件是否存在 2 编写一个名为greet的问候程序它执行时能根据系统当前的时间向用户输出问候信息。设从半夜到中午为早晨中午到下午六点为下午下午六点到半夜为晚上。 #!/bin/bash if [ -f /bin/date ] then echo /bin/date file exist. else echo /bin/date not exist. fi 2 #!/bin/bash hdate %H if [ $h -ge 0 ] [ $h -lt 12 ] then echo Good morning. elif [ $h -ge 12 ] [ $h -lt 18 ] then echo Good afternoon. else echo Good evening. fi 49、输入一串随机数字然后按千分位输出。 比如输入数字串为“123456789”输出为123,456,789 #!/bin/bash read -p 输入一串数字 num vecho $num|sed s/[0-9]//g if [ -n $v ] then echo 请输入纯数字. exit fi length${#num} len0 sum for i in $(seq 1 $length) do len$[$len1] if [[ $len 3 ]] then sum,${num:$[0-$i]:1}$sum len0 else sum${num:$[0-$i]:1}$sum fi done if [[ -n $(echo $sum | grep ^, ) ]] then echo ${sum:1} else echo $sum fi 上面这个答案比较复杂下面再来一个sed的 #!/bin/bash read -p 输入一串数字 num vecho $num|sed s/[0-9]//g if [ -n $v ] then echo 请输入纯数字. exit fi echo $num|sed -r {:number;s/([0-9])([0-9]{3})/\1,\2/;t number} 50、检查错误 #!/bin/bash sh -n $1 2/tmp/err if [ $? -eq 0 ] then echo The script is OK. else cat /tmp/err read -p Please inpupt Q/q to exit, or others to edit it by vim. n if [ -z $n ] then vim $1 exit fi if [ $n q -o $n Q ] then exit else vim $1 exit fi fi 51、一个网站使用了cdn全国各地有几十个节点。需要你写一个shell脚本来监控各个节点是否正常。 假如 1 监控的url为www.aming.com/index.php 2 源站ip为88.88.88.88 3 以及各个节点ip列表文件为/tmp/ip.txt #!/bin/bash urlwww.aming.com/index.php s_ip88.88.88.88 curl -x $s_ip:80 $url /tmp/source.html 2/dev/null for ip in cat /tmp/ip.txt do curl -x $ip:80 $url 2/dev/null /tmp/$ip.html [ -f /tmp/$ip.diff ] rm -f /tmp/$ip.diff touch /tmp/$ip.diff diff /tmp/source.html /tmp/$ip.html /tmp/$ip.diff 2/dev/null nwc -l /tmp/$ip.diff|awk {print $1} if [ $n -lt 0 ] then echo node $ip sth wrong. fi done 52、写一个脚本 判断当前主机的CPU生产商其信息在/proc/cpuinfo文件中vendor id一行中。 如果其生产商为AuthenticAMD就显示其为AMD公司 如果其生产商为GenuineIntel就显示其为Intel公司 否则就说其为非主流公司。 #!/bin/bash mcat /proc/cpuinfo |grep vendor_id|awk -F: {print $2}|tail -1 if [ $m GenuineIntel ] then echo cpu is 英特尔 elif [ $m AuthenticAMD ] then echo cpu is AMD else echo cpu is 非主流 fi 53、破解字符串 说明题目中最后一个字符串少写了一位应该是890684ba #!/bin/bash for n in {0..32767} do MD5echo $n | md5sum | cut -c 1-8 if [ $MD5 $1 ];then echo $n $c break fi done 54、用shell写一个监控服务器cpu使用率的监控脚本。 思路用top -bn1 命令取当前空闲cpu百份比值只取整数部分然后用100去剑这个数值。 55、脚本添加了只要使用率超过80%就会发一封报警邮件脚本每隔5秒钟执行一次 #! /bin/bash ##monitoring the cpu value if alwasy higher or not ##written by zhdya_20171012 while : do sum0 for i in top -bn1 | awk {print $9}| sed -n 8,$p | cut -d . -f 1 do sum$[$sum$i] done echo the cpu already used $sum% if [ $sum -gt 80 ] then echo the cpu already used $sum%, pls pay attention.. ##sendmail fi sleep 5 done 56、说明本shell题目是一个网友在公众号中提问的正好利用这个每日习题的机会拿出来让大家一起做一做。 给出一个进程PID打印出该进程下面的子进程以及子进程下面的所有子进程。只需要考虑子进程的子进程再往深层次则不考虑 57、用shell写一个监控服务器cpu使用率的监控脚本。 思路用top -bn1 命令取当前空闲cpu百份比值只取整数部分然后用100去剑这个数值。 #!/bin/bash while : do idletop -bn1 |sed -n 3p |awk {print $5}|cut -d . -f1 use$[100-$idle] if [ $use -gt 90 ] then echo cpu use percent too high. #发邮件省略 fi sleep 10 done 58、上一篇文章我们介绍了命名管道FIFO利用里面的知识点实现这个需求。 需求背景 领导要求小明备份数据库服务器里面的100个库数据量在几十到几百G需要以最快的时间完成5小时内并且不能影响服务器性能。 需求分析 由于数据量比较大单个库备份时间少则10几分钟多则几个小时我们算平均每个库30分钟若一个库一个库的去备份则需要3000分钟相当于50个小时。很明显不可取。但全部丢到后台去备份100个并发数据库服务器也无法承受。所以需要写一个脚本能够控制并发数就可以实现了。 #!/bin/sh ##假设100个库的名字存到了一个文件里文件名字为/tmp/databases.list ##其中备份数据库用了mysqldump这里你可以换成xtrabackup更快 function bak_data { dbname$1 ddate %y%d mysqldump -uroot -pxxxxx $dbname /backup/$1.$d } mkfifo $tmp_fifofile exec 1000$tmp_fifofile rm -f $tmp_fifofile thread10 for ((i0;i$thread;i)); do echo 1000 done for d in cat /tmp/databases.list do read -u6 { bak_data $d echo 1000 } done wait exec 1000- 59、我们使用的云主机购买一块云盘后默认并不是挂载状态的用shell写一个脚本只要把盘符和挂载点以参数的形式提供给脚本该脚本就可以自动格式化、挂载。 要求 1 不用分区直接格式化 2 格式化为ext4文件系统类型 #!/bin/bash echo Useage $0 盘符 挂载点, 如 $0 /dev/xvdb /data if [ $# -ne 2 ] then exit fi if [ ! -b $1 ] then echo 你提供的盘符不正确请检查后再操作 exit 1 fi mkfs -t ext4 $1 if [ ! -d $2 ] ;then mkdir -p $2 fi negrep $2 /etc/fstab|wc -l if [ $n -eq 0 ] then echo $1 $2 ext4 defaults 0 0 /etc/fstab mount -a else mount $1 $2 echo 配置文件/etc/fstab中已经存在挂载点$2,请检查一下. fi 60、自动封/解封ip 需求背景 discuz论坛每天有很多注册机注册的用户然后发垃圾广告帖子。虽然使用了一些插件但没有效果。分析访问日志发现有几个ip访问量特别大所以想到可以写个shell脚本通过分析访问日志把访问量大的ip直接封掉。 但是这个脚本很有可能误伤所以还需要考虑到自动解封这些ip。 思路 1 可以每分钟分析1次访问日志设定一个阈值把访问量大的ip用iptables封掉80端口 2 每20分钟检测一次已经被封ip的请求数据包数量设定阈值把没有请求的或者请求量很小的解封 #! /bin/bash ## To block the ip of bad requesting. ## Writen by aming 2017-11-18. log/data/logs/www.xxx.com.log tmpdir/tmp/badip #白名单ip不应该被封 goodip27.133.28.101 [ -d $tmpdir ] || mkdir -p $tmpdir tdate -d -1 min %Y:%H:%M #截取一分钟以前的日志 grep $t: $log $tmpdir/last_min.log #把一分钟内日志条数大于120的标记为不正常的请求 awk {print $1} $tmpdir/last_min.log |sort -n |uniq -c |sort -n |tail |awk $1120 {print $2}|grep -v $good_ip $tmpdir/bad.ip d3date %M #每隔20分钟解封一次ip if [ $d3 -eq 20 ] || [ $d3 -eq 40 ] || [ $d3 -eq 00 ]; then /sbin/iptables -nvL INPUT|grep DROP |awk $110 {print $8}$tmpdir/good.ip if [ -s $tmpdir/good.ip ]; then for ip in cat $tmpdir/good.ip do /sbin/iptables -D INPUT -p tcp --dport 80 -s $ip -j DROP d4date %Y%m%d-%H:%M echo $d4 $ip unblock $tmpdir/unblock.ip done fi #解封后再把iptables的计数器清零 /sbin/iptables -Z INPUT fi if [ -s $tmpdir/bad.ip ] ; then for ip in cat $tmpdir/bad.ip do /sbin/iptables -A INPUT -p tcp --dport 80 -s $ip -j DROP d4date %Y%m%d-%H:%M echo $d4 $ip block $tmpdir/block.ip done fi 61、写个shell脚本能够实现一键安装并配置samba服务执行该脚本时需要带一个参数为共享的目录目录可以不存在若不存在需要脚本自动创建。 #!/bin/bash is_samba_installedrpm -qa|grep samba|wc -l if [ $is_samba_installed ! 0 ] then echo You had already installed Samba. exit 0 fi echo It will install Samba. sleep 1 cnfdir/etc/samba/smb.conf chkok(){ if [ $? ! 0 ] then echo Error, Please try again. exit 1 fi } yum install -y samba chkok sed -i s/MYGROUP/WORKGROUP/ $cnfdir sed -i s/user/share/ $cnfdir sed -i $a\[fish] $cnfdir if [ -d $1 ] then cd $1 echo test test.txt sed -i $a\[fish]\n\tcomment Share All\n\tpath $1\n\tbrowseable yes\n\tpublic yes\n\twritable no $cnfdir else mkdir $1 cd $1 echo test test.txt sed -i $a\[fish]\n\tcomment Share All\n\tpath $1\n\tbrowseable yes\n\tpublic yes\n\twritable no $cnfdir fi /etc/init.d/smb start chkok echo Please input [\\sambaIP\sharename] to access the share dir. 62、用shell写一个脚本实现一键管理docker容器比如启动/关闭/删除容器等操作。 要求 1 脚本支持启动全部容器、关闭全部容器、删除全部容器 2 需要提示用户如何使用该脚本需给出范例 #! /bin/bash ##start,restart,delete the docker containers ##written by zhdya_20171114 listdocker ps -a |awk {print $2}| grep -v ID echo echo -e pls check the follow list of container: \n$list read -p pls choose an action which you want!1.start 2.stop 3.rm act echo echo -e stop\nstart\nrm\nrmi /tmp/docker.txt ##judge if input the words or not! if [ -z $act ] then echo you type was wrong,pls just input start.stop.rm.rmi. exit fi ##judge if input a wrong words!! if grep -wq $act /tmp/docker.txt then case $act in start) docker start $(docker ps -a | awk { print $1} | tail -n 2) echo already start all of container,pls checking it.. ;; stop) docker stop $(docker ps -a | awk { print $1} | tail -n 2) echo already restart all of container,pls checking it.. ;; rm) docker rm $(docker ps -a | awk { print $1} | tail -n 2) echo already rm all of container,pls checking it.. ;; *) docker rmi $(docker images | awk {print $3} |tail -n 2) echo already rm all of container,pls checking it.. esac else echo you type was wrong,pls just input start.stop.rm.rmi. fi 63、用shell脚本实现部署mysql主从架构。 思路是这样的 1master.sh脚本用来安装master的mysql 2然后通过expect脚本rsync工具把slave.sh脚本、/etc/my.cnf、 /etc/init.d/mysqld 还有mysqldump下来的all.sql以及在master下载下来的mysql二进制安装包传到slave上 3通过expect脚本来运行slave.sh的脚本来安装并且配置好主从期间用slave.tmp来记录master机子的binlog的状态以便于传到slave后用命令添加进去。 cp_slave.expect #!/usr/bin/expect set user [lindex $argv 0] set host [lindex $argv 1] set passwd [lindex $argv 2] set file [lindex $argv 3] spawn rsync -avzP $file $user$host:/tmp set timeout 600 expect { yes/no { send yes\r} password: { send $passwd\r } } expect eof ins_rsync.expect #!/usr/bin/expect set user [lindex $argv 0] set host [lindex $argv 1] set passwd [lindex $argv 2] spawn ssh $user$host expect { yes/no { send yes\r;exp_continue} password: { send $passwd\r } } expect ]* send yum install -y rsync\rexit\r interact slave.expect #!/usr/bin/expect set host [lindex $argv 0] set passwd [lindex $argv 1] set cm [lindex $argv 2] spawn ssh root$host expect { yes/no { send yes\r} password: { send $passwd\r } } expect ]* send $cm\rexit\r interact slave.sh #!/bin/bash ####this is for building slave script ##by lv. ####master ip address mas_ip192.168.47.24 ###mysql password conf my_passwdhd8832508 ####replication user and password rp_userhd rp_passwdhd8832508 ###check ok check(){ if [ $? ! 0 ] then echo error,please check log. exit 1 fi } ##close seliux sed -i s/SELINUXenforcing/SELINUXdisabled/ /etc/selinux/config selinux_sgetenforce if [ $selinux_s Enforcing -o $selinux_s enforcing ] then setenforce 0 fi ##close iptables iptables-save /etc/sysconfig/iptables_date %s iptables -F service iptables save ##install the mirror.aliyun.com cd /etc/yum.repos.d/ if rpm -qa |grep epel-release /dev/null then rpm -e epel-release fi if [ -f epel.repo ] then /bin/mv epel.repo epel.repo.bak fi yum install -y wget if [ -f CentOS-Base.repo ] then /bin/mv CentOS-Base.repo CentOS-Base.repo.bak wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo wget http://mirrors.aliyun.com/repo/epel-6.repo -O /etc/yum.repos.d/epel.repo fi yum clean all yum makecache #first to update datetime [ rpm -qa |grep ntpdate|wc -l -eq 1 ] || yum install -y ntpdate ntpdate 0.openwrt.pool.ntp.org 21 /dev/null;clock -w ###install lib software syum(){ if ! rpm -qa|grep -q $1 then yum install -y $1 check else echo $1 is already installed fi } ## install some packges for the first on setup. for p in gcc perl perl-devel libaio libaio-devel pcre-devel zlib-devel cmake glibc pcre compat-libstdc-33 do syum $p done ###check file is already in tmp if [ ! -f /tmp/my.cnf ] [ ! -f /tmp/mysqld ] [ ! -f /tmp/mysql-* ] [ ! -f /tmp/slave.tmp ] then echo error,please try to sync again exit 1 fi mysqlls /tmp |grep tar.gz versionecho /tmp/$mysql|awk -F - {print $2}|cut -d. -f2 ######install mysql cd /tmp tar -zxf $mysql mv echo $mysql|sed s/.tar.gz//g /usr/local/mysql cd /usr/local/mysql if ! grep ^mysql: /etc/passwd then useradd -s /sbin/nologin -M mysql check fi [ -d /data/mysql ] /bin/mv /data/mysql /data/mysql_date %s mkdir -p /data/mysql chown -R mysql:mysql /data/mysql ###initialize case $version in 1) /usr/local/mysql/scripts/mysql_install_db --usermysql --datadir/data/mysql check sed -i /^server-id/d /tmp/my.cnf check sed -i /\[mysqld\]/a\server-id2 /tmp/my.cnf check ;; 6) /usr/local/mysql/scripts/mysql_install_db --usermysql --datadir/data/mysql check sed -i /^server_id/d /tmp/my.cnf check sed -i /\[mysqld\]/a\server_id 2 /tmp/my.cnf check ;; 7) pswd5_7/usr/local/mysql/bin/mysqld --usermysql --datadir/data/mysql --initialize 21 |sed -r -n /localhost: /p|sed s/.* //g /usr/local/mysql/bin/mysql_ssl_rsa_setup --datadir/data/mysql check sed -i /^server_id/d /tmp/my.cnf check sed -i /\[mysqld\]/a\server_id 2 /tmp/my.cnf check ;; esac ###cp conf file /bin/cp -rf /tmp/my.cnf /etc/my.cnf check /bin/cp -rf /tmp/mysqld /etc/init.d/ check chmod 755 /etc/init.d/mysqld chkconfig --add mysqld chkconfig mysqld on service mysqld start check ####change mysql password if [ $version -eq 7 ] then /usr/local/mysql/bin/mysql -uroot -p$pswd5_7 --connect-expired-password -e set passwordpassword($my_passwd); check else /usr/local/mysql/bin/mysql -uroot -e set passwordpassword($my_passwd); check fi ###input date if [ -f /tmp/all.sql ] then /usr/local/mysql/bin/mysql -uroot -p$my_passwd /tmp/all.sql check else echo date error. exit 1 fi ######binlog slave_bingrep mysql-bin /tmp/slave.tmp slave_posgrep ^[0-9] /tmp/slave.tmp ###stop slave /usr/local/mysql/bin/mysql -uroot -p$my_passwd -e stop slave; check ###configure slave /usr/local/mysql/bin/mysql -uroot -p$my_passwd -e change master to master_host$mas_ip,master_port3306,master_user$rp_user,master_password$rp_passwd,master_log_file$slave_bin,master_log_pos$slave_pos; check ###start slave /usr/local/mysql/bin/mysql -uroot -p$my_passwd -e start slave; check ###check repecation status show/usr/local/mysql/bin/mysql -uroot -p$my_passwd -e show slave status\G;|grep Slave_IO_Running: slaveIOecho $show|awk -F: {print $2} Slave_SQLecho $show|awk -F: {print $2} if [ $slaveIO Yes ] [$Slave_SQL Yes ] then echo mysql repliation is start /bin/rm -rf /tmp/all.sql /tmp/$mysql /tmp/mysqld /tmp/my.cnf /tmp/slave.tmp else echo error,please check the log. fi master.sh #!/bin/bash #####this is building mysql replication### ##by lv. mlpwd ararch ###mysql password conf my_passwdhd8832508 ####replication user and password rp_userhd rp_passwdhd8832508 ###slave conf s_userroot s_host192.168.47.25 s_passwdhd8832508 ###check ok check(){ if [ $? ! 0 ] then echo error,please check log. exit 1 fi } ####check the file is exist for wj in $ml/cp_slave.expect $ml/ins_rsync.expect $ml/slave.expect $ml/slave.sh do if [ ! -f $wj ] then echo error,your miss $wj file. exit 1 else /bin/chmod x $wj check fi done ##close seliux sed -i s/SELINUXenforcing/SELINUXdisabled/ /etc/selinux/config selinux_sgetenforce if [ $selinux_s Enforcing -o $selinux_s enforcing ] then setenforce 0 fi ##close iptables iptables-save /etc/sysconfig/iptables_date %s iptables -F service iptables save ##install the mirror.aliyun.com aliyun(){ cd /etc/yum.repos.d/ if rpm -qa |grep epel-release /dev/null then rpm -e epel-release fi if [ -f epel.repo ] then /bin/mv epel.repo epel.repo.bak fi yum install -y wget if [ -f CentOS-Base.repo ] then /bin/mv CentOS-Base.repo CentOS-Base.repo.bak wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo wget http://mirrors.aliyun.com/repo/epel-6.repo -O /etc/yum.repos.d/epel.repo fi yum clean all yum makecache } if [ grep aliyun.com /etc/yum.repos.d/CentOS-Base.repo|wc -l -eq 0 ] then aliyun else echo aliyun epel is already installed. fi #first to update datetime [ rpm -qa |grep ntpdate|wc -l -eq 1 ] || yum install -y ntpdate ntpdate 0.openwrt.pool.ntp.org 21 /dev/null;clock -w ###install lib software syum(){ if ! rpm -qa|grep -q $1 then yum install -y $1 check else echo $1 is already installed fi } ## install some packges for the first on setup. for p in gcc perl perl-devel libaio libaio-devel pcre-devel zlib-devel cmake glibc pcre compat-libstdc-33 do syum $p done ###variables,fuctions mysql_5_1http://mirrors.sohu.com/mysql/MySQL-5.1/mysql-5.1.73-linux-$ar-glibc23.tar.gz mysql_5_6http://mirrors.sohu.com/mysql/MySQL-5.6/mysql-5.6.31-linux-glibc2.5-$ar.tar.gz mysql_5_7http://mirrors.sohu.com/mysql/MySQL-5.7/mysql-5.7.12-linux-glibc2.5-$ar.tar.gz ####################################### conf_mysql(){ cd /usr/local/mysql if ! grep ^mysql: /etc/passwd then useradd -s /sbin/nologin -M mysql check fi [ -d /data/mysql ] /bin/mv /data/mysql /data/mysql_date %s mkdir -p /data/mysql chown -R mysql:mysql /data/mysql ###initialize case $version in 5.1) ./scripts/mysql_install_db --usermysql --datadir/data/mysql check ;; 5.6) ./scripts/mysql_install_db --usermysql --datadir/data/mysql check ;; 5.7) pswd5_7./bin/mysqld --usermysql --datadir/data/mysql --initialize 21 |sed -r -n /localhost: /p|sed s/.* //g ./bin/mysql_ssl_rsa_setup --datadir/data/mysql check ;; esac } cp_mysql(){ ###my.cnf if [ -f /usr/local/mysql/support-files/my-huge.cnf ] then /bin/cp -rf support-files/my-huge.cnf /etc/my.cnf check sed -i /^\[mysqld\]$/a\datadir /data/mysql /etc/my.cnf check else /bin/cp -rf support-files/my-default.cnf /etc/my.cnf check sed -i /^\[mysqld\]$/a\socket /tmp/mysql.sock /etc/my.cnf sed -i /^\[mysqld\]$/a\port 3306 /etc/my.cnf sed -i /^\[mysqld\]$/a\datadir /data/mysql /etc/my.cnf check sed -i /^\[mysqld\]$/a\basedir /usr/local/mysql /etc/my.cnf fi ####/etc/init.d/mysqld if [ $version 5.7 ] then /bin/cp support-files/mysql.server /etc/init.d/mysqld check sed -i s#^datadir#datadir/data/mysql# /etc/init.d/mysqld sed -i s#^basedir#basedir/usr/local/mysql# /etc/init.d/mysqld check chmod 755 /etc/init.d/mysqld chkconfig --add mysqld chkconfig mysqld on service mysqld start check else /bin/cp support-files/mysql.server /etc/init.d/mysqld sed -i s#^datadir#datadir/data/mysql# /etc/init.d/mysqld chmod 755 /etc/init.d/mysqld chkconfig --add mysqld chkconfig mysqld on service mysqld start check fi } ###install mysql insall_mysql(){ echo Chose the version of mysql. select mysql_v in 5.1 5.6 5.7 do case $mysql_v in 5.1) cd /usr/local/src [ -f ${mysql_5_1##*/} ] || wget $mysql_5_1 tar zxf ${mysql_5_1##*/} check_ok [ -d /usr/local/mysql ] /bin/mv /usr/local/mysql /usr/local/mysql_date %s mv echo ${mysql_5_1##*/}|sed s/.tar.gz//g /usr/local/mysql check_ok version5.1 conf_mysql cp_mysql break ;; 5.6) cd /usr/local/src [ -f ${mysql_5_6##*/} ] || wget $mysql_5_6 tar zxf ${mysql_5_6##*/} check_ok [ -d /usr/local/mysql ] /bin/mv /usr/local/mysql /usr/local/mysql_bak mv echo ${mysql_5_6##*/}|sed s/.tar.gz//g /usr/local/mysql check_ok version5.6 conf_mysql cp_mysql break ;; 5.7) cd /usr/local/src [ -f ${mysql_5_7##*/} ] || wget $mysql_5_7 tar zxf ${mysql_5_7##*/} check_ok [ -d /usr/local/mysql ] /bin/mv /usr/local/mysql /usr/local/mysql_bak mv echo ${mysql_5_7##*/}|sed s/.tar.gz//g /usr/local/mysql check_ok version5.7 conf_mysql cp_mysql break ;; *) echo only 1(5.1) 2(5.6) or 3(5.7) exit 1 ;; esac done } ####change mysql password passwd_mysql(){ if [ $version 5.7 ] then /usr/local/mysql/bin/mysql -uroot -p$pswd5_7 --connect-expired-password -e set passwordpassword($my_passwd); check else /usr/local/mysql/bin/mysql -uroot -e set passwordpassword($my_passwd); check fi } ###### if [ ps aux|grep mysql|wc -l -gt 1 ] then echo mysql is already start else insall_mysql passwd_mysql fi ####start install slave echo ############################# echo ## ## echo ## slave install ## echo ## ## echo ############################# ##first check master tool if ! rpm -qa|grep -q rsync then yum install -y rsync fi if ! rpm -qa|grep -q expect then yum install -y expect fi ###replication building for master first if [ ps aux|grep mysql|wc -l -gt 1 ] [ grep log_bin mysql-bin /etc/my.cnf|wc -l -eq 0 ] [ grep log-binmysql-bin /etc/my.cnf|wc -l -eq 0 ] then /etc/init.d/mysqld stop check sed -i /^\[mysqld\]$/a\server_id 1 /etc/my.cnf sed -i /^\[mysqld\]$/a\log_bin mysql-bin /etc/my.cnf sed -i /^\[mysqld\]$/a\binlog_format MIXED /etc/my.cnf check /etc/init.d/mysqld start check fi master_bin/usr/local/mysql/bin/mysql -uroot -p$my_passwd -e show master status \G;|grep File|awk {print $2} master_pos/usr/local/mysql/bin/mysql -uroot -p$my_passwd -e show master status \G;|grep Position|awk {print $2} echo $master_bin /tmp/slave.tmp echo $master_pos /tmp/slave.tmp /usr/local/mysql/bin/mysql -uroot -p$my_passwd -e grant replication slave on *.* to $rp_user$s_host identified by $rp_passwd; check /usr/local/mysql/bin/mysql -uroot -p$my_passwd -e flush privileges; check ###dump date /usr/local/mysql/bin/mysqldump -uroot -p$my_passwd --single-transaction -A /tmp/all.sql check ####cp file to slave if [ pwd ! $ml ] then cd $ml fi ./ins_rsync.expect $s_user $s_host $s_passwd for file in /usr/local/src/mysql-* /etc/my.cnf /etc/init.d/mysqld ./slave.sh /tmp/slave.tmp /tmp/all.sql do ./cp_slave.expect $s_user $s_host $s_passwd $file done ./slave.expect $s_host $s_passwd /tmp/slave.sh 64、写一个shell脚本当我们执行时提示要输入对方的ip和root密码然后可以自动把本机的公钥增加到对方机器上从而实现密钥认证。 #!/bin/bash read -p Input IP: ip ping $ip -w 2 -c 2 /dev/null ## 查看ip是否可用 while [ $? -ne 0 ] do read -p your ip may not useable, Please Input your IP: ip ping $ip -w 2 -c 2 /dev/null done read -p Input root\s password of this host: password ## 检查命令子函数 check_ok() { if [ $? ! 0 ] then echo Error!. exit 1 fi } ## yum需要用到的包 myyum() { if ! rpm -qa |grep -q $1 then yum install -y $1 check_ok else echo $1 already installed fi } for p in openssh-clients openssh expect do myyum $p done ## 在主机A上创建密钥对 if [ ! -f ~/.ssh/id_rsa ] || [ ! -f ~/.ssh/id_rsa.pub ] then if [ -d ~/.ssh ] then mv ~/.ssh/ ~/.ssh_old fi echo -e \n | ssh-keygen -t rsa -P check_ok fi ## 传私钥给主机B if [ ! -d /usr/local/sbin/rsync_keys ] then mkdir /usr/local/sbin/rsync_keys fi cd /usr/local/sbin/rsync_keys if [ -f rsync.expect ] then ddate %F-%T mv rsync.expect $d.expect fi #创建远程同步的expect文件 cat rsync.expect EOF #!/usr/bin/expect set host [lindex \$argv 0] #主机B的密码 set passwd [lindex \$argv 1] spawn rsync -av /root/.ssh/id_rsa.pub root\$host:/tmp/tmp.txt expect { yes/no { send yes\r; exp_continue} password: { send \$passwd\r } } expect eof spawn ssh root\$host expect { password: { send \$passwd\r } } expect ]* send \[ -f /root/.ssh/authorized_keys \] cat /tmp/tmp.txt /root/.ssh/authorized_keys \r expect ]* send \[ -f /root/.ssh/authorized_keys \] || mkdir -p /root/.ssh/ \r send \[ -f /root/.ssh/authorized_keys \] || mv /tmp/tmp.txt /root/.ssh/authorized_keys\r expect ]* send chmod 700 /root/.ssh; chmod 600 /root/.ssh/authorized_keys\r expect ]* send exit\r EOF check_ok /usr/bin/expect /usr/local/sbin/rsync_keys/rsync.expect $ip $password echo OK,this script is successful. ssh $ip to test it 65、写一个shell脚本查询指定域名的过期时间并在到期前一周每天发一封提醒邮件。 思路 大家可以在linux下使用命令“whois 域名”如whois apelearn.com来获取该域名的一些信息。 提示 whois命令需要安装jwhois包 #!/bin/bash t1date %s is_install_whois() { which whois /dev/null 2/dev/null if [ $? -ne 0 ] then yum install -y jwhois fi } notify() { e_dwhois $1|grep Expiry Date|awk {print $4}|cut -d T -f 1 e_tdate -d $e_d %s necho 86400*7|bc e_t1$[$e_t-$n] if [ $t1 -ge $e_t1 ] [ $t1 -lt $e_t ] then /usr/local/sbin/mail2.py aming_test163.com Domain $1 will be expire. Domain $1 expire date is $e_d. fi } is_install_whois notify aminglinux.com 66、至少用两种方法批量把当前目录下面所有文件名后缀为.bak的后缀去掉比如1.txt.bak去掉后为1.txt 答 假设取消的后缀为.bak 方法一 for i in ls *.bak do mv $i echo $i|sed s/\.bak//g done 方法二 for i in ls *.bak do newnameecho $i|awk -F .bak {print $1} mv $i $newname done 67、在生产环境中经常遇到tomcat无法彻底关闭也就是说用tomcat自带shutdown.sh脚本无法将java进程完全关掉。所以需要借助shell脚本将进程杀死然后再启动。 写一个shell脚本实现上述功能。彻底杀死一个进程的命令是 kill -9 pid. 答 注明以下脚本为猿课同学实际线上跑的shell脚本考虑的方面比较多大家可以学一学他的思路 #!/bin/bash ###功能 重启 tomcat 进程 ###要求对于tomcat中的某些应用使用shutdown.sh是无法完全停掉所有服务的 实际操作中都需要kill掉tomcat再重启 ## ### root can not run this script. ## if [ $USER root ] then echo root cannt run this script!please run with other user! exit 1 fi ## ### check the Parameter ## if [[ $# -ne 1 ]] then echo Usage:$0 tomcatname exit 1 fi ## ### only one process can run one time ## TMP_FILE_U/tmp/.tmp.ps.keyword.$USER.956327.txt #echo $TMP_FILE_U KEYWORD1$0 KEYWORD2$1 # 使用赋值会多fork出一个进程,所以要先重定向到一个文本,再统计. ps ux |grep $KEYWORD1|grep \$KEYWORD2\|grep -v grep $TMP_FILE_U Pro_countcat $TMP_FILE_U |wc -l if [ $Pro_count -gt 1 ] then echo An other process already running ,exit now! exit 1 fi ################################################### # # # begin of the script # # # ################################################### ## ### set the Parameter ## TOMecho $1|sed s#/##g TOMCAT_DIRECTORY~/usr/local/$TOM STARTUP_SCRIPT$TOMCAT_DIRECTORY/bin/startup.sh TOMCAT_LOG$TOMCAT_DIRECTORY/logs/catalina.out CONF_FILE$TOMCAT_DIRECTORY/conf/server.xml TEMPFILE/tmp/.tmpfile.x.89342.c4r3.tmp ## ### check if the tomcat directory exist ## if [ ! -d $TOMCAT_DIRECTORY ] then echo the tomcat \$TOM\ not exist.check again! exit 1 fi ## ### log roteta and delete log one week ago ## rotate_log(){ TIME_FORMART$(date %Y%m%d%H%M%S) LOG_DIR$(dirname $TOMCAT_LOG) mv $TOMCAT_LOG ${TOMCAT_LOG}_${TIME_FORMART} find $LOG_DIR -type f -ctime 7 -exec rm -rf {} \; } ## ### function start the tomcat ## start_tomcat() { #echo start-tomcat-func if [ -x $STARTUP_SCRIPT ] then rotate_log $STARTUP_SCRIPT sleep 1 tail -f $TOMCAT_LOG else if [ -e $STARTUP_SCRIPT ] then chmod x $STARTUP_SCRIPT # echo permition added! if [ -x $STARTUP_SCRIPT ] then rotate_log $STARTUP_SCRIPT sleep 1 tail -f $TOMCAT_LOG else echo The script not have excute permision,Couldnt add permision to Script! exit 1 fi else echo error,the script \startup.sh\ not exist! exit 1 fi fi } ## ### function stop the tomcat ## stop_tomcat() { rm -rf $TEMPFILE ps ux |grep /$TOM/ |grep -v grep /$TOM/|grep java $TEMPFILE Pro_Countcat $TEMPFILE|wc -l PIDScat $TEMPFILE|awk {print $2} rm -rf $TEMPFILE #echo $Pro_Count if [ $Pro_Count -eq 0 ] then echo The tomcat not running now! else if [ $Pro_Count -ne 1 ] then echo The have $Pro_Count process running,killed! kill -9 echo $PIDS WCps aux | grep /$TOM/ | grep -v grep /$TOM/ | grep java |wc -l [ $WC -ne 0 ] (echo kill process failed!;exit 1) else echo Process killed! kill -9 echo $PIDS WCps aux | grep /$TOM/ | grep -v grep /$TOM/ | grep java |wc -l [ $WC -ne 0 ] (echo kill process failed!;exit 1) fi fi } ########################### #### #### #### The main script #### #### #### ########################### echo -e are you sure restart $TOM?(y or n) read ANS if [ $ANSa ! ya ] then echo -e bye! \n exit 1 fi stop_tomcat echo start tomcat ... sleep 2 start_tomcat # end 68、在centos6系统里我们可以使用ntsysv关闭不需要开机启动的服务当然也可以使用chkconfig工具来实现。 写一个shell脚本用chkconfig工具把不常用的服务关闭。脚本需要写成交互式的需要我们给它提供关闭的服务名字。 #!/bin/bash LANGen c1 while [ ! $c q ] do echo -e \033[35mPlease chose a service to close from this list: \033[0m chkconfig --list |awk /3:on/ {print $1} read -p Which service to close: s chkconfig $s off service $s stop read -p If you wants to quit this program, tab q, or tab Ctrl c: c done 69、统计并发量 需求背景 需要统计网站的并发量并绘图。 思路 1 借助zabbix成图 2 通过统计访问日志每秒的日志条数来判定并发量 3 zabbix获取数据间隔30s 说明 只需要写出shell脚本即可不用关心zabbix配置。 假设日志路径 /data/logs/www.aaa.com_access.log 日志格式如下 112.107.15.12 - [07/Nov/2017:09:59:01 0800] www.aaa.com /api/live.php 200- Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0) 答 #!/bin/bash log/data/logs/www.aaa.com_access.log tdate -d -1 second %Y:%H:%M:%S #可以大概分析一下每分钟日志的量级比如说不超过3000 ntail -3000 $log |grep -c $t echo $n 70、需求背景是 一个业务有3台服务器ABC做负载均衡由于规模太小目前并未使用专业的自动化运维工具。有新的需求时开发同事改完代码会把变更上传到其中一台服务器A上。但是其他2台服务器也需要做相同变更。 写一个shell脚本把A服务器上的变更代码同步到B和C上。 其中你需要考虑到不需要同步的目录假如有tmp、upload、logs、caches 答 : #!/bin/bash echo 该脚本将会把A机器上的/data/wwwroot/www.aaa.com目录同步到B,C机器上; read -p 是否要继续(y|n) rs() { rsync -azP \ --exclude logs \ --exclude upload \ --exclude caches \ --exclude tmp \ www.aaa.com/ $1:/data/wwwroot/www.aaa.com/ } if [ $REPLY y -o $REPLY Y ] then echo 即将同步…… sleep 2 cd /data/wwwroot/ rs B机器ip rs C机器ip echo 同步完成。 elif [ $REPLY n -o $REPLY N ] then exit 1 else echo 请输入字母y或者n fi 71、写一个脚本让用户输入多个城市的名字可以是中文要求不少于5个然后把这些城市存到一个数组里最后用for循环把它们打印出来。 #!/bin/bash read -p 请输入至少5个城市的名字用空格分隔: city necho $city|awk {print NF} if [ $n -lt 5 ] then echo 输入的城市个数至少为5 exit fi name($city) for i in ${name[]} do echo $i done 72、写一个截取tomcat catalina.out日志的脚本 tomcat实例t1-t4 # tree -L 1 /opt/TOM/ /opt/TOM/ ├── crontabs ├── t1 ├── t2 ├── t3 └── t4 5 directories, 0 files # find /opt/TOM/ -name catalina.out /opt/TOM/t1/logs/catalina.out /opt/TOM/t3/logs/catalina.out /opt/TOM/t4/logs/catalina.out /opt/TOM/t2/logs/catalina.out 要求 1.这个脚本可以取tomcat实例t1-t4的日志 2.这个脚本可以自定义取日志的起始点 比如取今天早上10点之后到现在的数据 3.这个脚本可以自定义取日志的起始点和终点比如取今天早上9点到晚上8点的数据 catalina.out 日志内容 Mar 29, 2016 1:52:24 PM org.apache.coyote.AbstractProtocol start INFO: Starting ProtocolHandler [http-bio-8080] Mar 29, 2016 1:52:24 PM org.apache.coyote.AbstractProtocol start INFO: Starting ProtocolHandler [ajp-bio-8009] Mar 29, 2016 1:52:24 PM org.apache.catalina.startup.Catalina start INFO: Server startup in 2102 ms 答 #!/bin/bash ## #Author: 7期孙东 # export LANGen_US.UTF-8 export PATH$PATH IPADD/sbin/ifconfig | grep inet addr | head -1 | awk {print $2}| awk -F . {print $NF} LOGFILE/opt/TOM/$1/logs/catalina.out YEARdate %Y DATEdate %m%d_%H%M TOMCAT$1 BEGIN_TIME$YEAR$2 END_TIME$YEAR$3 ##judge is a.m.or p.m. TIME_HOUR1echo ${BEGIN_TIME:9:2} cut_log() { N_DATE1echo $1 | sed s/_/ /g D_DATE1echo $2 | sed s/_/ /g E_DATE1echo $3 | sed s/_/ /g [ $4 ] N_DATE2echo $4 | sed s/_/ /g [ $5 ] D_DATE2echo $5 | sed s/_/ /g [ $6 ] E_DATE2echo $6 | sed s/_/ /g BEGINgrep -nE ${N_DATE1}|${D_DATE1}|${E_DATE1} ${LOGFILE} | head -1 | cut -d : -f1 [ $N_DATE2 ] ENDgrep -nE ${N_DATE2}|${D_DATE2}|${E_DATE2} ${LOGFILE} | tail -1 | cut -d : -f1 [ ! -z ${TIME_HOUR1} ] if [ ${TIME_HOUR1} -gt 12 ] ; then BEGIN1grep -nE ${N_DATE1}|${D_DATE1}|${E_DATE1} ${LOGFILE} |grep PM |grep ${E_DATE1} | head -1 | cut -d : -f1 if [ ! -z ${BEGIN1} ] ; then [ ${BEGIN1} -gt ${BEGIN} ] ; BEGIN${BEGIN1} fi fi if [ $BEGIN ] [ -z $END ] ; then if [ $N_DATE2 ]; then echo ${END_TIME}时间点没有访问日志请重新设置时间点. else sed -n ${BEGIN},[ DISCUZ_CODE_0 ]quot;p ${LOGFILE} /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.log fi elif [ $END ];then [ $BEGIN ] || BEGIN1 sed -n ${BEGIN},${END}p ${LOGFILE} /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.log else [ $END_TIME ! $YEAR ] echo 该时段 ${BEGIN_TIME}${END_TIME} 没有日志. [ $END_TIME $YEAR ] echo 该时段 ${BEGIN_TIME}now 没有日志. fi if [ -s /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.log ]; then cd /home/gcweb tar -zcf ${IPADD}_${TOMCAT}_${DATE}.tar.gz ${IPADD}_${TOMCAT}_${DATE}.log rm -f /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.log sz /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.tar.gz echo Success to get logs. rm -f /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.tar.gz fi } get_time() { case $1 in 4) N_DATEdate -d $2 %Y-%m-%d 2/dev/null D_DATEdate -d $2 %Y/%m/%d 2/dev/null E_DATEdate -d $2 %h %e,_%Y 2/dev/null|sed s/ /_/g echo $N_DATE $D_DATE $E_DATE ;; 7) TIMEecho $2 | awk -F_ {print $1,$2} N_DATEdate -d $TIME %Y-%m-%d_%H 2/dev/null D_DATEdate -d $TIME %Y/%m/%d_%H 2/dev/null E_DATEdate -d $TIME %h %e,_%Y %l 2/dev/null|sed s/ /_/g echo $N_DATE $D_DATE $E_DATE ;; 9) TIMEecho $2 | awk -F_ {print $1,$2} N_DATEdate -d $TIME %Y-%m-%d_%H:%M 2/dev/null D_DATEdate -d $TIME %Y/%m/%d_%H:%M 2/dev/null E_DATEdate -d $TIME %h %e,_%Y %l:%M 2/dev/null|sed s/ /_/g echo $N_DATE $D_DATE $E_DATE ;; *) echo 1 ;; esac } check_arguments () { if [ $1 1 ] || [ -z $1 ] ;then echo 你输入时间参数的格式无法识别, usage: 0108、0108_10、0108_1020 exit 3 fi } check_tomcat () { if [ ! -s ${LOGFILE} ] ;then echo tomcat_name: ${TOMCAT} is not exist echo you can choose: /bin/ls /home/gcweb/usr/local/ fi if [ $1 -lt 2 ] || [ ! -s ${LOGFILE} ];then echo usage: $0 tomcat_name {begin_time|begin_time end_time} exit 2 fi } case $# in 0) echo usage: $0 tomcat_name {begin_time|begin_time end_time} exit 1 ;; 1) check_tomcat $# ;; 2) check_tomcat $# lenecho $2 | awk {print length($0)} A_DATE$(get_time $len $BEGIN_TIME) eval $( echo $A_DATE |awk {print N_DATE$1,D_DATE$2,E_DATE$3}) check_arguments ${N_DATE} cut_log ${N_DATE} ${D_DATE} ${E_DATE} ;; 3) check_tomcat $# len1echo $2 | awk {print length($0)} len2echo $3 | awk {print length($0)} A_DATE$(get_time ${len1} $BEGIN_TIME) eval $( echo $A_DATE |awk {print N_DATE1$1,D_DATE1$2,E_DATE1$3}) check_arguments ${N_DATE1} A_DATE$(get_time ${len2} $END_TIME) eval $( echo $A_DATE |awk {print N_DATE$1,D_DATE$2,E_DATE$3}) check_arguments ${N_DATE} cut_log ${N_DATE1} ${D_DATE1} ${E_DATE1} ${N_DATE} ${D_DATE} ${E_DATE} ;; *) echo usage: $0 tomcat_name {begin_time|begin_time end_time};你使用的参数太多哦. ;; esac 73、阿里云的机器今天收到客服来的电话说服务器的磁盘io很重。于是登录到服务器查看并没有发现问题所以怀疑是间歇性地。 正要考虑写个脚本的时候幸运的抓到了一个线索造成磁盘io很高的幕后黑手是mysql。此时去show processlist但未发现队列。原来只是一瞬间。 只好继续来写脚本思路是每5s检测一次磁盘io当发现问题去查询mysql的processlist。 帮助你可以用iostat -x 1 5 来判定磁盘的io主要看%util 答 #!/bin/bash while : do niostat -x 1 5 |tail -n3|head -n1 |awk {print $NF}|cut -d. -f1 if [ $n -gt 70 ] then echo date util% is $n% /tmp/mysql_processlist.log mysql -uroot -pxxxxxx -e show full processlist /tmp/mysql_processlist.log fi sleep 5 done 74、贷款有两种还款的方式等额本金法和等额本息法 简单说明一下等额本息法与等额本金法的主要区别 等额本息法的特点是每月的还款额相同在月供中“本金与利息”的分配比例中前半段时期所还的利息比例大、本金比例小还款期限过半后逐步转为本金比例大、利息比例小。所支出的总利息比等额本金法多而且贷款期限越长利息相差越大。 等额本金法的特点是每月的还款额不同它是将贷款额按还款的总月数均分等额本金再加上上期剩余本金的月利息形成一个月还款额所以等额本金法第一个月的还款额最多 尔后逐月减少越还越少。所支出的总利息比等额本息法少。 两种还款方式的比较不是我们今天的讨论范围我们的任务就是做一个贷款计算器。 其中等额本息每月还款额的计算公式是 [贷款本金×月利率×1月利率^还款月数]÷[1月利率^还款月数1] 答 #!/bin/bash # Author: Maria.12期-马黎阳 # Date Time: 2016-03-07 09:04:01 # Description: 贷款计算器. read -p 请输入贷款总额单位万元 dkzewy read -p 请输入贷款年利率如年利率为6.5%直接输入6.5 dknll read -p 请输入贷款年限单位年 dknx echo 贷款计算方式 echo 1)等额本金计算法 echo 2)等额本息计算法 read -p 请选择贷款方式1|2 dkfs dkzeecho scale2;$dkzewy*10000 | bc -l dkllecho scale6;$dknll/100 | bc -l dkyllecho scale6;$dkll/12 | bc -l dkqc$[$dknx*12] echo 期次 本月还款额 本月利息 未还款额 debjjsf() { yhbjecho scale2;($dkze/$dkqc)/1 | bc -l whbj$dkze for((i1;i$dkqc;i)) do bylxecho scale2;($whbj*$dkyll)/1 | bc -l bybxecho scale2;($yhbj$bylx)/1 | bc -l yhkeecho scale2;($yhbj*$i)/1 | bc -l whbjecho $dkze-$yhke | bc -l if [ $i -eq $dkqc ] then yhbjecho scale2;($yhbj$whbj)/1 | bc -l whbj0.00 bybxecho scale2;($yhbj$bylx)/1 | bc -l fi echo $i $bybx $bylx $whbj done } debxjsf() { bybxecho scale2;(($dkze*$dkyll*((1$dkyll)^$dkqc))/(((1$dkyll)^$dkqc)-1))/1 | bc -l whbj$dkze for((i1;i$dkqc;i)) do bylxecho scale2;($whbj*$dkyll)/1 | bc -l yhbjecho scale2;($bybx-$bylx)/1 | bc -l whbjecho scale2;($whbj-$yhbj)/1 | bc -l if [ $i -eq $dkqc ] then bybxecho scale2;($yhbj$whbj)/1 | bc -l whbj0.00 fi echo $i $bybx $bylx $whbj done } case $dkfs in 1) debjjsf ;; 2) debxjsf ;; *) exit 1 ;; esac 75、要求两类机器一共300多台写个脚本自动清理这两类机器里面的日志文件。在堡垒机批量发布也要批量发布到crontab里面。 A类机器日志存放路径很统一B类机器日志存放路径需要用*匹配因为这个目录里除了日志外还有其他文件不能删除。匹配的时候可用*.log A类/opt/cloud/log/ 删除7天前的 B类: /opt/cloud/instances/ 删除15天前的 要求写在一个脚本里面。不用考虑堡垒机上的操作只需要写出shell脚本。 #!/bin/bash dir1/opt/cloud/instances/ dir2/opt/cloud/log/ if [ -d $dir1 ];then find $dir1 -type f -name *.log -mtime 15 |xargs rm -f elif [ -d $dir2 ];then find $dir2 -type f -mtime 7 |xargs rm -f fi 76、有如下文本其中前5行内容为 1111111:13443253456 2222222:13211222122 1111111:13643543544 3333333:12341243123 2222222:12123123123 用shell脚本处理后按下面格式输出 [1111111] 13443253456 13643543544 [2222222] 13211222122 12123123123 [3333333] 12341243123 #! /bin/bash sort -n filename |awk -F : {print $1}|uniq id.txt for id in cat id.txt; do echo [$id] awk -v id2$id -F : $1id2 {print $2} filename // 另外的方式为: awk -F : $1id {print $2} filename done 77、写一个脚本查找/data/log目录下最后创建时间是3天前后缀是*.log的文件打包后发送至192.168.1.2服务上的/data/log下并删除原始.log文件仅保留打包后的文件 #!/bin/bash find /data/log -name “*.log” -mtime 3 /tmp/file.list cd /data/log tar czvf log.tar.gz cat /tmp/file.list|xargs rsync -a log.tar.gz 192.168.1.2:/data/log //这一步需要提前做一个免密码登录 for f in cat /tmp/file.list do rm -f $f done 78、请使用条件函数if撰写一个shell函数 函数名为 f_judge实现以下功能 1当/home/log 目录存在时 将/home目录下所有tmp开头的文件或目录移/home/log 目录。 2当/home/log目录不存在时创建该目录然后退出。 #!/bin/bash f_judge (){ if [ -d /home/log ] then mv /home/tmp* /home/log/ else mkdir -p /home/log exit fi } 79、linux系统中根目录/root/下有一个文件ip-pwd.ini,内容如下 10.111.11.1,root,xyxyxy 10.111.11.1,root,xzxzxz 10.111.11.1,root,123456 10.111.11.1,root,xxxxxx …… 文件中每一行的格式都为linux服务器的ip,root用户名,root密码请用一个shell批量将这些服务器中的所有tomcat进程kill掉。 讲解 有了ip用户名和密码剩下的就是登录机器然后执行命令了。批量登录机器并执行命令咱们课程当中有讲过一个expect脚本。所以本题就是需要这个东西来完成。 首先编辑expect脚本 kill_tomcat.expect #!/usr/bin/expect set passwd [lindex $argv 0] set host [lindex $argv 1] spawn ssh root$host expect { yes/no { send yes\r; exp_continue} password: { send $passwd\r } } expect ]* send killall java\r expect ]* send exit\r 编辑完后需要给这个文件执行权限 chmod ax kill_tomcat.expect 然后编辑shell脚本 #!/bin/bash nwc -l ip-pwd.ini for i in seq 1 $n do ipsed -n $np ip-pwd.ini |awk -F , {print $1} pwsed -n $np ip-pwd.ini |awk -F , {print $3} ./kill_tomcat.expect $pw $ip done 80、linux系统 /home目录下有一个文件test.xml内容如下 configuration artifactItems artifactItem groupIdzzz/groupId artifactIdaaa/artifactId /artifactItem artifactItem groupIdxxx/groupId artifactIdyyy/artifactId /artifactItem !-- /artifactItemgroupIdsome groupId/groupId version1.0.1.2.333.555/version /artifactItem-- /artifactItems /configuration 请写出shell脚本删除文件中的注释部分内容获取文件中所有artifactItem的内容并用如下格式逐行输出 artifactItemgroupIdartifactId 分析这个文件比较特殊但是却很有规律。注释部分内容其实就是!-- --中间的内容所以我们想办法把这些内容删除掉就ok了。而artifactItem的内容其实就是获取artifactItem/artifactItem中间的内容。然后想办法用提到的格式输出即可。 答 #!/bin/bash egrep -v !--|-- 1.txt |tee 2.txt //这行就是删除掉注释的行 grep -n artifactItem 2.txt |awk {print $1} |sed s/:// /tmp/line_number.txt nwc -l /tmp/line_number.txt|awk {print $1} get_value(){ sed -n $1,$2p 2.txt|awk -F {print $2}|awk -F {print $1,$2} /tmp/value.txt nuwc -l /tmp/value.txt|awk {print $1} for i in seq 1 $nu do xsed -n $ip /tmp/value.txt|awk {print $1} ysed -n $ip /tmp/value.txt|awk {print $2} echo artifactItem:$x:$y done } n2$[$n/2] for j in seq 1 $n2 do m1$[$j*2-1] m2$[$j*2] nu1sed -n $m1p /tmp/line_number.txt nu2sed -n $m2p /tmp/line_number.txt nu3$[$nu11] nu4$[$nu2-1] get_value $nu3 $nu4 done 81、写一个脚本依次向/etc/passwd中的每个用户问好并且说出对方的ID是什么 Hello,rootyour UID is 0. awk -F : {print Hello,$1,your uid is $3.} /etc/passwd 82、交互式脚本根据提示需要用户输入一个数字作为参数最终打印出一个正方形。 在这里我提供一个linux下面的特殊字符■可以直接打印出来。 示例 如果用户输入数字为5则最终显示的效果为 ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ #!/bin/bash read -p please input a number: sum aecho $sum |sed s/[0-9]//g if [ -n $a ] then echo 请输入一个纯数字。 exit 1 fi for n in seq $sum do for m in seq $sum do if [ $m -lt $sum ] then echo -n ■ else echo ■ fi done done 83、用户交互脚本 写一个脚本执行后打印一行提示“Please input a number:要求用户输入数值然后打印出该数值然后再次要求用户输入数值。直到用户输入end停止。 #!/bin/bash while : do read -p Please input a number:(end for exit) n num echo $n |sed -r s/[0-9]//g|wc -c if [ $n end ] then exit elif [ $num -ne 1 ] then echo what you input is not a number!Try again! else echo your input number is: $n fi done 84、判断所给目录内哪些二级目录下没有text.txt文件。 有text.txt文件的二级目录根据文件计算选项中单词数最大的值选项间以|分割单词间以空格分隔。 假如脚本名字为1.sh 运行脚本的格式为 ./1.sh 123 root其中123为目录名字而root为要计算数量的单词。 答 说明 这个shell脚本题目出的有点歧义。 原题给的描述不是很清楚我另外又改了一下需求依然不是很清晰。在这里我再做一个补充 对于有test.txt的目录计算出该test.txt文件里面所给出单词的次数。不用找最大。 #!/bin/bash if [ $# -ne 2 ] then echo useage $0 dir word exit 1 fi if [ -d $1 ] then cd $1 else echo $1目录不存在 exit 1 fi for f in ls $1 do if [ -d $f ] then if [ -f $f/test.txt ] then ngrep -cw $2 $f/test.txt echo $1/$f/test.txt 里面有$n个$2 else echo $1/$f 下面没有test.txt fi fi done 85、用shell写一个简易计算器可以实现加、减、乘、除运算假如脚本名字为1.sh执行示例./1.sh 1 2 #!/bin/bash if [ $# -ne 3 ] then echo 参数个数不为3 echo 当使用乘法时需要加上脱义符号例如 $0 1 \* 2 exit 1; fi num1echo $1|sed s/[0-9.]//g ; if [ -n $num1 ] then echo $1 不是数字 ; exit 1 fi num3echo $3|sed s/[0-9.]//g ; if [ -n $num3 ] then echo $3 不是数字 ; exit 1 fi case $2 in ) echo scale2;$1$3 | bc ;; -) echo scale2;$1-$3 | bc ;; \*) echo scale2;$1*$3 | bc ;; /) echo scale2;$1/$3 | bc ;; *) echo $2 不是运算符 ;; esac 86、需求背景 服务器上跑的lamp环境上面有很多客户的项目每个项目就是一个网站。 由于客户在不断增加每次增加一个客户就需要配置相应的mysql、ftp以及httpd. 这种工作是重复性非常强的所以用脚本实现非常合适。 mysql增加的是对应客户项目的数据库、用户、密码ftp增加的是对应项目的用户、密码使用vsftpd虚拟用户模式httpd就是要增加虚拟主机配置段。 #!/bin/bash webdir/home/wwwroot ftpudir/etc/vsftpd/vuuser mysqlc/usr/bin/mysql -uroot -xxxxxx httpd_config_f/usr/local/apache2/conf/extra/httpd-vhosts.conf add_mysql_user() { mysql_pmkpasswd -s 0 -l 12 echo $pro $mysql_p /tmp/$pro.txt $mysqlc EOF grant all on $p.* to $pro127.0.0.1 identified by $mysql_p; EOF } add_ftp_user() { ftp_pmkpasswd -s 0 -l 12 echo $pro /root/login.txt echo $ftp_p /root/login.txt db_load -T -t hash -f /root/login.txt /etc/vsftpd/vsftpd_login.db cd $ftpudir cp aaa $pro //这里的aaa是一个文件是之前的一个项目可以作为配置模板 sed -i s/aaa/$pro/ $pro //把里面的aaa改为新的项目名字 /etc/init.d/vsftpd restart } config_httpd() { mkdir $webdir/$pro chown vsftpd:vsftpd $webdir/$pro echo -e VirtualHost *:80 \n DocumentRoot /home/internet/www/$pro/ \n ServerName $dom \n #ServerAlias \n/VirtualHost $httpd_config_f /usr/local/apache2/bin/apachectl graceful } read -p input the project name: pro read -p input the domain: dom add_mysql_user add_ftp_user config_httpd 87、 获取子进程 说明本shell题目是一个网友在公众号中提问的正好利用这个每日习题的机会拿出来让大家一起做一做。 给出一个进程PID打印出该进程下面的子进程以及子进程下面的所有子进程。只需要考虑子进程的子进程再往深层次则不考虑 #!/bin/bash read -p please input a pid number: p ps -elf /tmp/ps.log is_ppid(){ awk {print $5} /tmp/ps.log /tmp/ps1.log if ! grep -qw $1 /tmp/ps1.log then echo PID $1 不是系统进程号或者它不是父进程 return 1 fi } is_ppid $p if [ $? -eq 1 ] then exit fi print_cpid(){ p$1 awk -v p1$p $5 p1 {print $4} /tmp/ps.log |sort -n |uniq /tmp/p1.log nwc -l /tmp/p1.log|awk {print $1} if [ $n -ne 0 ] then echo PID $p 子进程 pid 如下: cat /tmp/p1.log else echo PID $p 没有子进程 fi } print_cpid $p for cp in cat /tmp/p1.log do print_cpid $cp done 另外一条命令查询的方法是pstree -p pid 88、用shell打印下面这句话中字母数小于6的单词。 Bash also interprets a number of multi-character options. #!/bin/bash for s in Bash also interprets a number of multi-character options do necho $s|wc -c if [ $n -lt 6 ] then echo $s fi done 89、输入数字执行对应命令 写一个脚本实现如下功能 输入一个数字然后运行对应的一个命令。显示命令如下*cmd meau** 1---date 2--ls 3--who 4--pwd 当输入1时会运行date, 输入2时运行ls, 依此类推。 90、要求 把一个文本文档的前5行中包含字母的行删除掉同时把6到10行中的全部字母删除掉。 答 假设文本名字叫做1.txt并且文本行数大于10脚本如下 #!/bin/bash ##先获取该文本的行数 nuwc -l 1.txt |awk {print $1} ##对前5行进程处理 for i in seq 1 5 do ##使用sed把每一行的内容赋值给变量 lsed -n $ip 1.txt ##用grep 判定是否匹配字母,-v取反-q不输出内容 if echo $l |grep -vq [a-zA-Z] then echo $l fi done ##对6-10行做删除字母处理 for i in seq 6 10 do lsed -n $ip 1.txt echo $l|sed s/[a-zA-Z]//g done ##剩余的直接输出 for i in seq 11 $nu do sed -n $ip 1.txt done ##若想把更改内容写入到1.txt还需要把以上内容重定向到一个文本中然后删除1.txt再把刚刚重定向的文件更名为1.txt 91、自动重启nginx服务 服务器上跑的是LNMP环境近期总是有502现象。502为网站访问的状态码200正常502错误是nginx最为普通的错误状态码。由于502只是暂时的并且只要一重启php-fpm服务则502消失但不重启的话则会一直持续很长时间。所以有必要写一个监控脚本监控访问日志的状态码一旦发生502则自动重启一下php-fpm。 我们设定 1. access_log /data/log/access.log 2. 脚本死循环每10s检测一次假设每10s钟的日志条数为300左右 3. 重启php-fpm的方法是 /etc/init.d/php-fpm restart 答 其实不是重启nginx应该说是自动重启php-fpm服务。 #! /bin/bash log/data/log/access.log N10 while :; do ##因为10秒钟大概产生300条日志 tail -n 300 $log gt; /tmp/log n_502grep -c 502 /tmp/log 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 fi sleep 10 done 92、备份数据库【答案】 #! /bin/bash ### backup mysql data ### Writen by Aming. PATH/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/mysql/bin d1data %w d2date %d passyour_mysql_password bakdir/bak/mysql r_bakdir192.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$pass --default-character-setgbk discuz $bakdir/$d1.sql rsync -az $bakdir/$d1.sql $r_bakdir/$d2.sql echo mysql backup end at date %F %T. 然后加入cron 0 3 * * * /bin/bash /usr/local/sbin/mysqlbak.sh 93、使用传参的方法写个脚本实现加减乘除的功能。例如 sh a.sh 1 2这样会分别计算加、减、乘、除的结果。 要求 1 脚本需判断提供的两个数字必须为整数 2 当做减法或者除法时需要判断哪个数字大 3 减法时需要用大的数字减小的数字 4 除法时需要用大的数字除以小的数字并且结果需要保留两个小数点。 #!/bin/bash if [ $# -ne 2 ] then echo The number of parameter is not 2, Please useage: ./$0 1 2 exit 1 fi is_int() { if echo $1|grep -q [^0-9] then echo $1 is not integer number. exit 1 fi } max() { if [ $1 -ge $2 ] then echo $1 else echo $2 fi } min() { if [ $1 -lt $2 ] then echo $1 else echo $2 fi } sum() { echo $1 $2 $[$1$2] } minus() { bigmax $1 $2 smallmin $1 $2 echo $big - $small $[$big-$small] } mult() { echo $1 * $2 $[$1*$2] } div() { bigmax $1 $2 smallmin $1 $2 decho scale 2; $big / $small|bc echo $big / $small $d } is_int $1 is_int $2 sum $1 $2 minus $1 $2 mult $1 $2 div $1 $2 94、写一个脚本 计算100以内所有能被3整除的正整数的和 #!/bin/bash sum0 for i in {1..100};do if [ $[$i%3] -eq 0 ];then sum$[$i$sum] fi done echo sum:$sum 95、带选项的用户脚本 要求如下 只支持三个选项 ‘--del’ ‘--add’ --help输入其他选项报错。 使用‘--add’需要验证用户名是否存在存在则反馈存在。且不添加。 不存在则创建该用户切添加与该用户名相同的密码。并且反馈。 使用‘--del’ 需要验证用户名是否存在存在则删除用户及其家目录。不存在则反馈该用户不存在。 --help 选项反馈出使用方法 支持以分隔 一次删除多个或者添加多个用户。 能用echo $? 检测脚本执行情况 成功删除或者添加为0,报错信息为其他数字。 能以分割。一次性添加或者 删除多个用户。 例如 adddel.sh --add user1,user2,user3....... 不允许存在明显bug。 #!/bin/bash #written by aming. if [ $# -eq 0 -o $# -gt 2 ] then echo use $0 --add username or $0 --del username or $0 --help. exit 1 fi case $1 in --add) n0 for u in echo $2|sed s/,/ /g; do if awk -F: {print $1} /etc/passwd |grep -qw $u then echo The user $u exist. else useradd $u echo -e $u\n$u|passwd $u /dev/null 21 echo The user $u added successfully. n$[$n1] fi done if [ $n -eq 0 ]; then exit 2 fi ;; --del) n0 for u in echo $2|sed s/,/ /g; do if awk -F: {print $1} /etc/passwd|grep -qw $u then userdel -r $u echo The user $u deleted successfully. n$[$n1] else echo The user $u not exist. fi done if [ $n -eq 0 ]; then exit 3 fi ;; --help) echo -e --add can add user,and the passwd is the same as username. It can add multiuser such as --add user1,user2,user3... echo --del cat delete user.It can delete user such as --del user1,user2,user3... ;; *) echo use $0 --add username or $0 --del username or $0 --help. exit 1 ;; esac 96、假设当前MySQL服务的root密码为123456写脚本检测MySQL服务是否正常比如可以正常进入mysql执行show processlist并检测一下当前的MySQL服务是主还是从如果是从请判断它的主从服务是否异常。如果是主则不需要做什么。 #!/bin/bash Mysql_cmysql -uroot -p123456 $Mysql_c -e show processlist /tmp/mysql_pro.log 2/tmp/mysql_log.err nwc -l /tmp/mysql_log.err|awk {print $1} if [ $n -gt 0 ] then echo mysql service sth wrong. else $Mysql_c -e show slave status\G /tmp/mysql_s.log n1wc -l /tmp/mysql_s.log|awk {print $1} if [ $n1 -gt 0 ] then y1grep Slave_IO_Running: /tmp/mysql_s.log|awk -F : {print $2}|sed s/ //g y2grep Slave_SQL_Running: /tmp/mysql_s.log|awk -F : {print $2}|sed s/ //g if [ $y1 Yes ] [ $y2 Yes ] then echo slave status good. else echo slave down. fi fi fi 97、写一个脚本判断你的Linux服务器里是否开启web服务监听80端口如果开启了请判断出跑的是什么服务是httpd呢还是nginx又或者是其他的什么 #!/bin/bash portnetstat -lnp | grep 80 if [ -z port ]; then echo not start service.; exit; fi web_serverecho $port | awk -F/ {print $2}|awk -F : {print $1} case $web_server in httpd ) echo apache server. ;; nginx ) echo nginx server. ;; * ) echo other server. ;; esac 98、监控磁盘使用率 写一个shell脚本检测所有磁盘分区使用率和inode使用率并记录到以当天日期为命名的日志文件里当发现某个分区容量或者inode使用量大于85%时发邮件通知你自己。 思路就是先df -h 然后过滤出已使用的那一列然后再想办法过滤出百分比的整数部分然后和85去比较同理inode也是一样的思路。 #!/bin/bash ## This script is for record Filesystem Use%,IUse% everyday and send alert mail when % is more than 85%. log/var/log/disk/date %F.log date %F %T $log df -h $log echo $log df -i $log for i in df -h|grep -v Use%|sed s/%//|awk {print $5}; do if [ $i -gt 85 ]; then usedf -h|grep -v Use%|sed s/%//|awk $5$i {print $1,$5} echo $use use fi done if [ -e use ]; then ##这里可以使用咱们之前介绍的mail.py发邮件 mail -s Filesystem Use% check rootlocalhost use rm -rf use fi for j in df -i|grep -v IUse%|sed s/%//|awk {print $5}; do if [ $j -gt 85 ]; then iusedf -i|grep -v IUse%|sed s/%//|awk $5$j {print $1,$5} echo $iuse iuse fi done if [ -e iuse ]; then mail -s Filesystem IUse% check rootlocalhost iuse rm -rf iuse fi 思路 1、df -h、df -i 记录磁盘分区使用率和inode使用率date %F 日志名格式 2、取出使用率(第5列)百分比序列for循环逐一与85比较大于85则记录到新文件里当for循环结束后汇总超过85的一并发送邮件(邮箱服务因未搭建发送本地root账户)。 此脚本正确运行前提 该系统没有逻辑卷的情况下使用因为逻辑卷df -h、df -i 时使用率百分比是在第4列而不是第5列。如有逻辑卷则会漏统计逻辑卷使用情况。 99、写个shell看看你的Linux系统中是否有自定义用户普通用户若是有一共有几个 假设所有普通用户都是uid大于1000的 #!/bin/bash nawk -F : $31000 /etc/passwd|wc -l if [ $n -gt 0 ] then echo There are $n common users. else echo No common users. fi 100、请详细查看如下几个数字的规律并使用shell脚本输出后面的十个数字。 10 31 53 77 105 141 ....... 试题解析 我想大多数人都会去比较这些数字的差值 10 31 53 77 105 141 21 22 24 28 36 但是这个差值看并没有什么规律而我们再仔细看的时候发现这个差值的差值是有规律的 10 31 53 77 105 141 21 22 24 28 36 1 2 4 8 #! /bin/bash x21 m10 echo $m for i in seq 0 14; do j$[2**$i] m$[$m$x] echo $m x$[$x$j] done 101、需求 根据web服务器上的访问日志把一些请求量非常高的ip给拒绝掉 分析 我们要做的不仅是要找到哪些ip请求量不合法并且还要每隔一段时间把之前封掉的ip若不再继续请求了给解封。 所以该脚本的关键点在于定一个合适的时间段和阈值。 比如 我们可以每一分钟去查看一下日志把上一分钟的日志给过滤出来分析并且只要请求的ip数量超过100次那么就直接封掉。 而解封的时间又规定为每半小时分析一次把几乎没有请求量的ip给解封 参考日志文件片段 157.55.39.107 [20/Mar/2015:00:01:24 0800] www.aminglinux.com /bbs/thread-5622-3-1.html 200 - Mozilla/5.0 (compatible; bingbot/2.0; http://www.bing.com/bingbot.htm) 61.240.150.37 [20/Mar/2015:00:01:34 0800] www.aminglinux.com /bbs/search.php?modforumsrchtxtLNMPformhash8f0c7da9searchsubmittruesourcehotsearch 200 - Mozilla/5.0 (compatible; bingbot/2.0; http://www.bing.com/bingbot.htm) #! /bin/bash logfile/home/logs/access.log d1date -d -1 minute %H:%M d2date %M ipt/sbin/iptables ips/tmp/ips.txt block(){ grep $d1: $logfile|awk {print $1} |sort -n |uniq -c |sort -n $ips for ip in awk $1100 {print $2} $ips; do $ipt -I INPUT -p tcp --dport 80 -s $ip -j REJECT echo date %F-%T $ip /tmp/badip.txt done } unblock(){ for i in $ipt -nvL --line-numbers |grep 0.0.0.0/0|awk $215 {print $1}|sort -nr; do $ipt -D INPUT $i done $ipt -Z } if [ $d2 00 ] || [ $d2 30 ]; then unblock block else block fi 102、监控httpd进程 在服务器上写一个监控脚本。 1. 每隔10s去检测一次服务器上的httpd进程数如果大于等于500的时候就需要自动重启一下apache服务并检测启动是否成功 2. 若没有正常启动还需再一次启动最大不成功数超过5次则需要理解发邮件通知管理员并且以后不需要再检测 3. 如果启动成功后1分钟后再次检测httpd进程数若正常则重复之前操作每隔10s检测一次若还是大于等于500那放弃重启并需要发邮件给管理员然后自动退出该脚本。假设其中发邮件脚本为之前咱们使用的mail.py #!/bin/bash check_service() { n0 for i in seq 1 5 do /usr/local/apache2/bin/apachectl restart 2/tmp/apache.err if [ $? -ne 0 ] then n$[$n1] else break fi done if [ $n -eq 5 ] then ##下面的mail.py参考https://coding.net/u/aminglinux/p/aminglinux-book/git/blob/master/D22Z/mail.py python mai.py 123qq.com httpd service down cat /tmp/apache.err exit fi } while : do t_nps -C httpd --no-heading |wc -l if [ $t_n -ge 500 ] then /usr/local/apache2/bin/apachectl restart if [ $? -ne 0 ] then check_service fi sleep 60 fi sleep 10 done 103、用shell脚本实现如下需求 添加user_00 - user_09 10个用户并且给他们设置一个随机密码密码要求10位包含大小写字母以及数字注意需要把每个用户的密码记录到一个日志文件里。 提示 1. 随机密码使用命令 mkpasswd 2. 在脚本中给用户设置密码可以使用echo 然后管道passwd命令 #!/bin/bash for i in seq -w 00 09 do useradd user_$i pmkpasswd -s 0 -l 10 echo user_$i $p /tmp/user0_9.pass echo $p |passwd --stdin user_$i done 104、输入数字执行对应命令 写一个脚本实现如下功能 输入一个数字然后运行对应的一个命令。显示命令如下*cmd meau** 1---date 2--ls 3--who 4--pwd 当输入1时会运行date, 输入2时运行ls, 依此类推。 #!/usr/bin/env bash echo **********cmd menu*********** cmdTip( 1--date 2--ls 3--who 4--pwd ) for tip in ${cmdTip[]}; do echo ${tip} done cmd( date ls who pwd ) read -p Please enter the nature index of the cmd(DEFAULT 1): num echo ${num} if [ -z ${num} ];then num1 fi echo $(${cmd[num-1]}) exit 0 105、用shell打印下面这句话中字母数小于6的单词。 Bash also interprets a number of multi-character options. #!/bin/bash for s in Bash also interprets a number of multi-character options do necho $s|wc -c if [ $n -lt 6 ] then echo $s fi done 106、写一个脚本 创建一个函数能接受两个参数 1).第一个参数为URL即可下载的文件第二个参数为目录即下载后保存的位置 2).如果用户给的目录不存在则提示用户是否创建如果创建就继续执行否则函数返回一个51的错误值给调用脚本 3).如果给的目录存在则下载文件下载命令执行结束后测试文件下载成功与否如果成功则返回0给调用脚本否则返回52给调用脚本 [rootlocalhost tmp]# cat downfile.sh
#!/bin/bash
url$1
dir$2
download()
{
cd $dir /dev/null 21
if [ $? -ne 0 ];thenread -p $dir No such file or directory,create?(y/n) answer
if [ $answer y ];thenmkdir -p $dircd $dirwget $url 1 /dev/null 21elsereturn 51fi
fi
if [ $? -ne 0 ]; thenreturn 52
fi
}
download $url $dir
echo $ 107、写一个脚本 1、创建一个函数可以接受一个磁盘设备路径如/dev/sdb作为参数;在真正开始后面步骤之前提醒用户有危险并让用户选择是否继续而后将此磁盘设备上的所有分区清空提示使用命令dd if/dev/zero of/dev/sdb bs512 count1实现注意其中的设备路径不要写错了 如果此步骤失败返回67给主程序 接着在此磁盘设备上创建两个主分区一个大小为100M一个大小为1G如果此步骤失败返回68给主程序 格式化此两分区文件系统类型为ext3如果此步骤失败返回69给主程序 如果上述过程都正常返回0给主程序 2、调用此函数并通过接收函数执行的返回值来判断其执行情况并将信息显示出来 local Darray(ls /dev/sd[a-z])
for i in ${Darray};do
[[ $i $1 ]] Sd$i break
done
else
return66
fi #当匹配成功进入选择告诉用户是否继续输错的话进入无限循环当用户选择 Y,则清空目标分区且跳出while循环 while :;do read -p Warning!!!This operation will clean $Sd data.Nexty, Quitn [y|n]: Choice case $Choice in y) dd if/dev/zero of$Sd bs512 count1 /dev/null break || return 67 ;; n) exit 88 ;; *) echo Invalid choice,please choice again. ;; esac done 使用echo传递给fdisk进行分区如果此命令失败则跳转出去错误值68需要注意的是有时候这个返回值很诡异笔者之前成功与否都是返回的1后来重启之后就好了如果慎重的话可以对创建的分区进行判断不过就需要使用其他工具截取相关字段了虽有些小麻烦但无大碍 echo-e n\np\n1\n\n100M\nn\np\n2\n\n1024M\nw\n|
fdisk /dev/sdb /dev/null || return 68 格式化之前让内核重新读取磁盘分区表值得注意的是有的系统版本使用partprobe无效譬如笔者的环境是rhel5.8而rhel6.0以后这个命令就很危险了而使用partx -a /dev/sdb则效果更好…此项需慎重如果格式化失败则告知把失败的分区定义成变量且跳出函数并带出错误值69 partprobe
Partfdisk -l /dev/$Sd|tail -2|cut -d” ” -f1
for M in ${Part};do
mke2fs -j $M /dev/null ErrorPart$M return 69
done
return 0
} 下面代码调用函数接收函数返回值根据返回值进行判断哪里出错。 Disk_Mod $1
Res$?
[ $Res-eq 0 ] exit 0
[ $Res-eq 66 ] echo Error! Invalid input.
[ $Res-eq 67 ] echo Error! Command - dd - Faild.
[ $Res-eq 68 ] echo Error! Command - fdisk - Faild.
[ $Res-eq 69 ] echo Error! Command - mke2fs - Faild. 108、编写个shell脚本将当前目录下大于10K的文件转移到/tmp目录下 Q主要是考察awk 这些的用法 #/bin/sh #Programm : # Using for move currently directory to /tmp for FileName in ls -l |awk ‘$510240 {print $9}’ do mv $FileName /tmp done ls -la /tmp echo “Done! ” 109、编写shell脚本获取本机的网络地址。比如本机的ip地址是192.168.100.2/255.255.255.0那么它的网络地址是192.168.100.1/255.255.255.0 方法一 #!/bin/bash #This script print ip and network file”/etc/sysconfig/network-scripts/ifcfg-eth0″ if [ -f $file ] ;then IPgrep “IPADDR” $file|awk -F”” ‘{ print $2 }’ MASKgrep “NETMASK” $file|awk-F”” ‘{ print $2 }’ echo “$IP/$MASK” exit 1 fi 方法二 #!/bin/bash #This programm will printf ip/network # IPifconfig eth0 |grep ‘inet ‘ |sed ’s/^.*addr://g’|sed ’s/ Bcast.*$//g’ NETMASKifconfig eth0 |grep ‘inet ‘|sed ’s/^.*Mask://g’ echo “$IP/$NETMASK” exit 110、字符串替换命令 :s/well/good/ 替换当前行第一个well 为 good :s/well/good/g 替换当前行所有well 为 good :n,$s/well/good/ 替换第 n 行开始到最后一行中每一行的第一个 well 为 good :n,$s/well/good/g 替换第 n 行开始到最后一行中每一行所有 well 为 good n 为数字若 n 为 . 表示从当前行开始到最后一行 :%s/well/good/ 等同于 :g/well/s//good/ 替换每一行的第一个 well 为 good :%s/well/good/g 等同于 :g/well/s//good/g 替换每一行中所有 well 为 good 特殊符号转义可以使用#作为分隔符此时中间出现的 / 不会作为分隔符 :s#well/#good/# 替换当前行第一个 well/ 为 good/ :%s#/usr/bin#/bin#g 可以把文件中所有路径/usr/bin换成/bin 111、删除多行 删除多行步骤如下 1. 首先要显示对应的行数这样方能知道从第几行到第几行删除 : set nu 2. 按Esc键退出在命令行中输入190,6233d(即[190 , 6233]都删除掉) 如果想要情况整个文件内容在直接运行以下命令 清空文件内容 log.txt 112、 行位定位 直接定位到最后一行 按Esc键退出在命令行中输入 G 直接定位到第一行 按Esc键退出在命令行中输入 1 G 直接定位到某一行第行 按Esc键退出在命令行中输入17 G 113、复制一行或多行 1. 复制一行 yy 复制当前行 p 粘贴 2. 复制多行 7yy 从当前行开始复制行 p 粘贴 114、grep 的用法 1. 显示匹配的后n行 after grep -A n 2. 显示匹配的前n行 before grep -B n 3. 显示匹配的前后n行 context grep -C n 4. 忽略大小写 grep -i str 115、 116、 117、 Shell脚本处理浮点数的运算和比较实例 1. 用bc来处理计算包括整型和浮点计算 bc – An arbitrary precision calculator language (1). 通常在Bash脚本中使用bc的范例格式为 variable$(echo “OPTIONS; OPERATIONS” | bc [options]) 即echo “[选项];操作” | bc [选项] (2). 在下面的脚本中提到在第一个选项中“scale”变量表示输出中小数点后的精度可以用于控制计算结果的精度“ibase”和“obase”分别表示输入和输出数据的进制可以用于数值进制的转换。 (3). 浮点数的比较如“if [ $(echo $big $small | bc) -eq 1 ]”将一个逻辑判断式用管道传给bc。如果结果为真则输出1否则输出0然后就可以利用这个结果进行进一步的操作了。 (4). bc本来是用一个文件作为输入进行计算的后面也有演示所以可以将很复杂的计算写到文件中然后让bc工具去处理到处计算结果。 注意一下在使用除法运算符/时要想保留小数需要自己设置scale否则默认时scale小数点后时0位。2. 使用awk来处理浮点计算和浮点数比较 不解释过多了写了示例脚本如下看懂了这个就会知道怎么处理浮点计算和浮点数比较了。 执行的结果如下 另外bc处理一个文件中的计算逻辑演示如下 请“man bc”查看详情同样请“man awk”。 Bash经典用法及其案例 一、条件选择、判断 1条件选择if 1、用法格式 if 判断条件 1 ; then 条件为真的分支代码 elif 判断条件 2 ; then 条件为真的分支代码 elif 判断条件 3 ; then 条件为真的分支代码 else 以上条件都为假的分支代码 fi 逐条件进行判断第一次遇为“真”条件时执行其分支而后结束整个if。 2、经典案例 ① 判断年纪 分析请输入年纪先判断输入的是否含有除数字以外的字符有就报错没有继续判断是否小于150是否大于18。 ② 判断分数 分析请输入成绩先判断输入的是否含有除数字以外的字符有就报错没有继续判断是否大于100是否大于85是否大于60。 2条件判断 case 1、用法格式 case $name in; PART1) cmd ;; PART2) cmd ;; *) cmd ;; esac 注意case 支持glob 风格的通配符 *: 任意长度任意字符 ?: 任意单个字符 [] 指定范围内的任意单个字符 a|b: a 或b 2、案例 判断yes or no 分析请输入yes or no回答Y/y、yes各种大小写组合为yes回答N/n、No各种大小写组合为no。 二、四个循环 1for 1、用法格式 ① for name in 列表 ;do 循环体 done ② for (( exp1; exp2; exp3 )) ;do cmd done exp1只执行一次相当于在for里嵌了while ③ 执行机制依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽循环结束 列表的表示方法可以glob 通配符如{1..10} 、*.sh 也可以变量引用如 seq 1 $name 2、案例 ① 求出12...n的总和 分析sum初始值为0请输入一个数先判断输入的是否含有除数字以外的字符有就报错没有判断是否为0不为0进入for循环i的范围为1~输入的数每次的循环为sumsumi循环结束最后输出sum的值。 ② 求出12...100的总和 分析i1,num0当i100进入循环若i÷2取余1则sumsumiii1。 2while 1、用法格式 while 循环控制条件 ;do 循环 done 循环控制条件进入循环之前先做一次判断每一次循环之后会再次做判断条件为“true” 则执行一次循环直到条件测试状态为“false” 终止循环 2、特殊用法遍历文件的每一行 while read line; do控制变量初始化 循环体 done /PATH/FROM/SOMEFILE 或cat /PATH/FROM/SOMEFILE | while read line; do 循环体 done 依次读取/PATH/FROM/SOMEFILE文件中的每一行且将行赋值给变量line 3、案例 ① 100以内所有正奇数之和 分析sum初始值为0i的初始值为1请输入一个数先判断输入的是否含有除数字以外的字符有就报错没有当i100时进入循环判断 i÷2取余 是否不为0不为0时为奇数sumsumii1为0i1循环结束最后输出sum的值。 3until 循环 1、用法 unitl 循环条件 ;do 循环 done 进入条件循环条件为true 退出条件循环条件为false刚好和while相反所以不常用用while就行。 2、案例 监控xiaoming用户登录就杀死 分析每隔0.5秒扫描直到发现xiaoming用户登录杀死这个进程退出脚本用于监控用户登录。 4select 循环与菜单 1、用法 select variable in list do 循环体命令 done ① select 循环主要用于创建菜单按数字顺序排列的示菜单项将显示在标准错误上并显示PS3 提示符等待用户输入 ② 用户输入菜单列表中的某个数字执行相应的命令 ③ 用户输入被保存在内置变量 REPLY 中 ④ select 是个无限循环因此要记住用 break 命令退出循环或用 exit 按 命令终止脚本。也可以按 ctrlc退出循环 ⑤ select 和 经常和 case 联合使用 ⑥ 与for循环类似可以省略 in list 此时使用位置参量 2、案例 生成菜单并显示选中的价钱 分析PS3是select的提示符自动生成菜单选择5break退出循环。 三、循环里的一些用法 1循环控制语句 continue [N]提前结束第N层的本轮循环而直接进入下一轮判断最内层为第1层 break [N]提前结束第N层循环最内侧为第1层 例while CONDTITON1; do CMD1 if CONDITION2; then continue / break fi CMD2 done 2、案例 ① 求13...4953...100的和 分析做12...100的循环当i51时跳过这次循环但是继续整个循环结果为sum2449 ② 求13...49的和 分析做12...100的循环当i51时跳出整个循环结果为sum625 2循环控制shift命令 1、作用 用于将参数列表list左移指定次数最左端的那个参数就从列表中删除其后边的参数继续进入循环 2、案例 ① 创建指定的多个用户 分析如果没有输入参数参数的总数为0提示错误并退出反之进入循环若第一个参数不为空字符则创建以第一个参数为名的用户并移除第一个参数将紧跟的参数左移作为第一个参数直到没有第一个参数退出。 ② 打印直角三角形的字符 3返回值结果 true 永远返回成功结果 : null command ,什么也不干返回成功结果 false 永远返回错误结果 创建无限循环 while true ;do 循环体 done 4循环中可并行执行使脚本运行更快 1、用法 for name in 列表 ;do { 循环体 } done wait 2、实例 搜寻自己指定ip子网掩码为24的的网段中UP的ip地址 分析请输入一个IP地址例192.168.37.234如果格式不是0.0.0.0 则报错退出正确则进入循环IP变量的值为192.168.37. i的范围为1-254并行ping 192.168.37.1-154ping通就输出此IP为UP。直到循环结束。 四、信号捕获trap 1、用法格式 trap 触发指令 信号自定义进程收到系统发出的指定信号后将执行触发指令而不会执行原操作 trap 信号忽略信号的操作 trap - 信号恢复原信号的操作 trap -p列出自定义信号操作 信号可以3种表达方法信号的数字2、全名SIGINT、缩写INT 2、常用信号 1) SIGHUP: 无须关闭进程而让其重读配置文件 2) SIGINT: 中止正在运行的进程相当于Ctrlc 3) SIGQUIT: 相当于ctrl\ 9) SIGKILL: 强制杀死正在运行的进程 15) SIGTERM 终止正在运行的进程默认为15 18) SIGCONT 继续运行 19) SIGSTOP 后台休眠 9 信号强制杀死捕获不住 3、案例 ① 打印0-9ctrlc不能终止 分析i0当i10每休眠1秒i1捕获2信号并执行echo press ctrlc 分析i0当i10每休眠1秒i1捕获2信号并执行echo press ctrlc ② 打印0-3ctrlc不能终止3之后恢复能终止 分析i0当i3每休眠1秒i1捕获2信号i3时解除捕获2信号。 五、脚本小知识 1、生成随机字符 cat /dev/urandom 生成8个随机大小写字母或数字 cat /dev/urandom |tr -dc [:alnum:] |head -c 8 2、生成随机数 echo $RANDOM 确定范围 echo $[RANDOM%7] 随机7个数0-6 echo $[$[RANDOM%7]31] 随机7个数31-37 3、echo打印颜色字 echo -e \033[31malong\033[0m 显示红色along echo -e \033[1;31malong\033[0m 高亮显示红色along echo -e \033[41malong\033[0m 显示背景色为红色的along echo -e \033[31;5malong\033[0m 显示闪烁的红色along color$[$[RANDOM%7]31] echo -ne \033[1;${color};5m*\033[0m 显示闪烁的随机色along 脚本 1、9x9乘法表 2、彩色等腰三角形 3、国际象棋棋盘 常用shell语句 if语句 一、条件测试的表达式 [ expression ] 括号两端必须要有空格 [[ expression ]] 括号两端必须要有空格 test expression 组合测试条件 -a: and -o: or !: 非 二、整数比较 -eq 测试两个整数是否相等 -ne 测试两个整数是否不等 -gt 测试一个数是否大于另一个数 -lt 测试一个数是否小于另一个数 -ge 大于或等于 -le 小于或等于 三、命令间的逻辑关系 逻辑与 第一个条件为假 第二个条件不用在判断最总结果已经有 第一个条件为真第二个条件必须得判断 逻辑或|| 四、字符串比较 等于 两边要有空格 ! 不等 大于 小于 五、文件测试 -z string 测试指定字符是否为空空着真非空为假 -n string 测试指定字符串是否为不空空为假 非空为真 -e file 测试文件是否存在 -f file 测试文件是否为普通文件 -d file 测试指定路径是否为目录 -r file 测试文件对当前用户是否可读 -w file 测试文件对当前用户是否可写 -x file 测试文件对当前用户是都可执行 -z 是否为空 为空则为真 -a 是否不空 这里如果then不写在if后面if后面就不用分好了还有末尾记得fi结尾呀 SHELL实战 SHELL实战Nginx WEB源码安装 #!/bin/bash #2017年9月6日15:00:17 #auto install nginx web #by author www.jfedu.net ######################## rm -rf /usr/local/nginx/ wget -c http://nginx.org/download/nginx-1.12.1.tar.gz tar -xzvf nginx-1.12.1.tar.gz cd nginx-1.12.1/ ./configure make make install /usr/local/nginx/sbin/nginx 2、SHELL编程实战Vsftpd虚拟用户 #!/bin/bash #2017年9月6日15:20:07 #auto config vsftpd user #by author www.jfedu.net #################### #Install Vsftpd Soft yum install vsftpd* -y #/etc/init.d/vsftp restart service vsftpd restart #Config vsftp virtual user yum install pam libdb-utils libdb --skip-broken -y touch /etc/vsftpd/ftpusers.txt #echo jfedu001 #123456/etc/vsftpd/ftpusers.txt cat/etc/vsftpd/ftpusers.txtEOF jfedu001 123456 EOF db_load -T -t hash -f /etc/vsftpd/ftpusers.txt /etc/vsftpd/vsftpd_login.db chmod 700 /etc/vsftpd/vsftpd_login.db chmod 700 /etc/vsftpd/ftpusers.txt cat/etc/pam.d/vsftpdEOF auth required pam_userdb.so db/etc/vsftpd/vsftpd_login account required pam_userdb.so db/etc/vsftpd/vsftpd_login EOF #Create vsftpd system user useradd -s /sbin/nologin ftpuser cat/etc/vsftpd/vsftpd.confEOF #config virtual user FTP pam_service_namevsftpd guest_enableYES guest_usernameftpuser user_config_dir/etc/vsftpd/vsftpd_user_conf virtual_use_local_privsYES EOF mkdir -p /etc/vsftpd/vsftpd_user_conf/ touch /etc/vsftpd/vsftpd_user_conf/jfedu001 cat/etc/vsftpd/vsftpd_user_conf/jfedu001 EOF local_root/home/ftpuser/jfedu001 write_enableYES anon_world_readable_onlyYES anon_upload_enableYES anon_mkdir_write_enableYES anon_other_write_enableYES EOF #Create virtual user basedir mkdir -p /home/ftpuser/jfedu001 chown -R ftpuser:ftpuser /home/ftpuser service vsftpd restart service firewalld stop setenforce 0 #Vsftpd config done. 注意 1、脚本里为什么要另外在path 加环境变量 答在cron里执行时cron的PATH并不全所以额外定义一下会更保险 2、exec这行在这里的作用是什么 这行用来定义输出内容到哪个文件。 3、请问:本地保存一周远程保存一个月是怎么实现的 每天凌晨三点执行一次每次均拷贝远程地址远程拷贝的前一天数据会被覆盖吗 答 本地一周就用那个 date %w 实现一周不是7天么。 远程一个月是需要加一个任务计划find 找一下一个月以前的文件然后删除掉 4、shell脚本不执行 问题某天研发同事找我说帮他看看他写的shell脚本死活不执行报错。我看了下脚本很简单也没有常规性的错误报“:badinterpreter:Nosuchfileordirectory”错。 看这错我就问他是不是在windows下编写的脚本然后在上传到linux服务器的……果然。 原因在DOS/windows里文本文件的换行符为rn而在*nix系统里则为n所以DOS/Windows里编辑过的文本文件到了*nix里每一行都多了个^M。 解决 1重新在linux下编写脚本 2vi:%s/r//g:%s/^M//g^M输入用Ctrlv,Ctrlm 附sh-x脚本文件名可以单步执行并回显结果有助于排查复杂脚本问题。 5、Shell脚本是什么、它是必需的吗? 答:一个Shell脚本是一个文本文件包含一个或多个命令。作为系统管理员我们经常需要使用多个命令来完成一项任务我们可以添加这些所有命令在一个文本文件(Shell脚本)来完成这些日常工作任务。 6、什么是默认登录shell如何改变指定用户的登录shell 答:在Linux操作系统“/bin/bash”是默认登录shell是在创建用户时分配的。使用chsh命令可以改变默认的shell。示例如下所示: # chsh 用户名 -s 新shell
# chsh linuxtechi -s /bin/sh 7、可以在shell脚本中使用哪些类型的变量? 答在shell脚本我们可以使用两种类型的变量 系统定义变量 用户定义变量 系统变量是由系统系统自己创建的。这些变量通常由大写字母组成可以通过“set”命令查看。 用户变量由系统用户来生成和定义变量的值可以通过命令“echo $变量名”查看。 8、如何将标准输出和错误输出同时重定向到同一位置? 答这里有两个方法来实现 方法一 21 (如# ls /usr/share/doc out.txt 21 ) 方法二 (如# ls /usr/share/doc out.txt ) 9、shell脚本中“if”语法如何嵌套? 答基础语法如下 if [ 条件 ]
then
命令1
命令2
…..
else
if [ 条件 ]
then
命令1
命令2
….
else
命令1
命令2
…..
fi
fi 10、shell脚本中“$?”标记的用途是什么 答在写一个shell脚本时如果你想要检查前一命令是否执行成功在if条件中使用“$?”可以来检查前一命令的结束状态。简单的例子如下 rootlocalhost:~# ls /usr/bin/shar
/usr/bin/shar
rootlocalhost:~# echo $?
0 如果结束状态是0说明前一个命令执行成功。 rootlocalhost:~# ls /usr/bin/share
ls: cannot access /usr/bin/share: No such file or directory
rootlocalhost:~# echo $?
2 如果结束状态不是0说明命令执行失败。 11、在shell脚本中如何比较两个数字 ? 答在if-then中使用测试命令 -gt 等来比较两个数字例子如下 #!/bin/bash
x10
y20
if [ $x -gt $y ]
then
echo “x is greater than y”
else
echo “y is greater than x”
fi 12、shell脚本中break命令的作用 ? 答break命令一个简单的用途是退出执行中的循环。我们可以在while和until循环中使用break命令跳出循环。 13、shell脚本中continue命令的作用 ? 答continue命令不同于break命令它只跳出当前循环的迭代而不是整个循环。continue命令很多时候是很有用的例如错误发生但我们依然希望继续执行大循环的时候。 14、告诉我shell脚本中Case语句的语法 ? 答基础语法如下 case 变量 in
值1)
命令1
命令2
…..
最后命令
!!
值2)
命令1
命令2
……
最后命令
;;
esac 15、shell脚本中while循环语法 ? 答 如同for循环while循环只要条件成立就重复它的命令块。不同于for循环while循环会不断迭代直到它的条件不为真。基础语法 while [ 条件 ]
do
命令…
done 16、 如何使脚本可执行 ? 答使用chmod命令来使脚本可执行。例子如下 # chmod ax myscript.sh 17、“#!/bin/bash”的作用 ? 答#!/bin/bash是shell脚本的第一行称为释伴shebang行。这里#符号叫做hash而! 叫做 bang。它的意思是命令通过 /bin/bash 来执行。 18、for循环的基础语法 for 变量 in 循环列表
do
命令1
命令2
….
最后命令
done 19、如何调试shell脚本 ? 答使用-x参数sh -x myscript.sh可以调试shell脚本。另一个种方法是使用‘-nv’参数( sh -nv myscript.sh)。 20、shell脚本如何比较字符串? 答test命令可以用来比较字符串。测试命令会通过比较字符串中的每一个字符来比较。 21、Bourne shell(bash) 中有哪些特殊的变量 ? 答下面的表列出了Bourne shell为命令行设置的特殊变量。 内建变量 解释
$0 命令行中的脚本名字
$1 第一个命令行参数
$2 第二个命令行参数
….. …….
$9 第九个命令行参数
$# 命令行参数的数量
$* 所有命令行参数以空格隔开 22、在shell脚本中如何测试文件 ? 答test命令可以用来测试文件。基础用法如下表格 Test 用法
-d 文件名 如果文件存在并且是目录返回true
-e 文件名 如果文件存在返回true
-f 文件名 如果文件存在并且是普通文件返回true
-r 文件名 如果文件存在并可读返回true
-s 文件名 如果文件存在并且不为空返回true
-w 文件名 如果文件存在并可写返回true
-x 文件名 如果文件存在并可执行返回true 23、在shell脚本中如何写入注释 ? 答注释可以用来描述一个脚本可以做什么和它是如何工作的。每一行注释以#开头。例子如下 #!/bin/bash
# This is a command
echo “I am logged in as $USER” 24、如何让 shell 就脚本得到来自终端的输入? 答read命令可以读取来自终端使用键盘的数据。read命令得到用户的输入并置于你给出的变量中。例子如下 # vi /tmp/test.sh
#!/bin/bash
echo ‘Please enter your name’
read name
echo “My Name is $name”
# ./test.shPlease enter your name
LinuxTechi
My Name is LinuxTechi 25、如何取消变量或取消变量赋值 ? 答“unset”命令用于取消变量或取消变量赋值。语法如下所示 # unset 变量名 26、如何执行算术运算 ? 答有两种方法来执行算术运算 1.使用expr命令 # expr 5 2 2.用一个美元符号和方括号$[ 表达式 ]例如 test$[16 4] ; test$[16 4] 27、do-while语句的基本格式 ? 答do-while语句类似于while语句但检查条件语句之前先执行命令LCTT 译注意即至少执行一次。。下面是用do-while语句的语法 do
{
命令
} while (条件) 28、在shell脚本如何定义函数呢 ? 答函数是拥有名字的代码块。当我们定义代码块我们就可以在我们的脚本调用函数名字该块就会被执行。示例如下所示 $ diskusage () { df -h ; }
译注下面是我给的shell函数语法原文没有
[ function ] 函数名 [()]
{
命令;
[return int;]
} 29、乘法口诀 # vi 1.py #!/usr/bin/python # for i in xrange(1,10): for j in xrange(1,i1): print $s X %s %s %(iji*j), print # python 1.py 30、系统随机生成一个1-20的随机数 # vi 1.py #/usr/bin/python #coding:utf-8 print‘游戏规则系统随机生成一个1-20的数字你有6次机会猜一下吧。’ import random import sys snumrandom.randint(1,20) #print snum numint(raw_input(请输入一个数字) if num snum: print 恭喜你你猜对了。 else for i in xrange(1,7): if num snum: print 恭喜你猜对了。 sys.exit() elif num snum: print 猜的数字太大了。 elif num snum: print 猜的数字太小了。 if i 6: print 6次机会用完了 sys.exit() numint(raw_input(猜错了再猜一次吧)) # python 1.py 31、查看磁盘空间大小 #!/usr/bin/python #coding:utf-8 with open(/proc/meminfo) as fd: for line in fd: if line.startswith(MemTotal): totallinesplit()[1] contine if line.startswith(MemFree): totallinesplit()[1] break #print total.free print 总内存数%.2f %(int(total)/1024.0)M内存 print 剩余%.2f %(int(total)/1024.0)M内存 memusedint(total)-int(free) print 使用%.2f %(int(memused)/1024.0)M内存 print 占用%.2f %(int(memused)/1.0/int(total))% #python men.py 32什么时候不使用shell脚本 答 需要大规模的文件操作 需要多维数组的支持 需要直接操作系统硬件 33、test 测试表达式与[ 测试表达式 ]等价 如果flie文件存在则输出true否则||输出false。 -f #文件存在且为普通文件则表达式成立 -z #如果测试字符串的长度为0则表达式成立 、||、、等操作符可以应用于[[ ]]中但不能应用于[]中在[]中一般使用-a、-o、-gt用于整数、-lt用于整数。 例使用read传入数字等于1就打印1。如果等于2就打印2。如果不等于1也不等于2就提示错误。 34、使用read读入方式比较两个整数的大小。 35、打印选择菜单按照选择项一键安装不同的WEB服务。 代码 #!/bin/sh cat EOF 1.[install lamp] 2.[install lnmp] 3.[exit] please input the num: EOF sh_path/server/scripts [ ! -d ${sh_path} ] { mkdir -p ${sh_path} } read num expr ${num} 1 /dev/null; [ $? -ne 0 ] { echo please input the num is {1|2|3}!; exit 0; } [[ ! ${num} [1-3] ]] { echo please input the num is {1|2|3}!; exit 1; } [ ${num} -eq 1 ] { echo start installing lamp:; [ -x ${sh_path}/lamp.sh ] || { echo ${sh_path}/lamp.sh does not exist or cant be exe.; exit 2; } ${sh_path}/lamp.sh; exit $?; } [ ${num} -eq 2 ] { echo start installing lnmp:; [ -x ${sh_path}/lnmp.sh ] || { echo ${sh_path}/lnmp.sh doest exist or cant be exec.; exit 3; } ${sh_path}/lnmp.sh; exit $?; } [ ${num} -eq 3 ] { echo exit exit 4; } 执行结果 36、编写shell脚本批量生成30个密码 vi mkpasswd.sh #!/bin/bash i1 echo ########kim by 51cto.com########## /tmp/passwd.txt while [ $i -le 30 ];do /usr/bin/mkpasswd -l 14 -s 2 -c 3 -C 3 -d 4 /tmp/passwd.txt let i1 done exit; mkpasswd参数详解 -l # (length of password, default 7) 指定密码的长度默认是7位数 -d # (min # of digits, default 2) 指定密码中数字最少位数默认是2位 -c # (min # of lowercase chars, default 2) 指定密码中小写字母最少位数默认是2位 -C # (min # of uppercase chars, default 2) 指定密码中大写字母最少位数默认是2位 -s # (min # of special chars, default 1) 指定密码中特殊字符最少位数默认是1位 37、写一个shell脚本来得到当前的日期时间用户名和当前工作目录。 #!/bin/bash echo Hello, $LOGNAME echo Current date is date echo User is who i am echo Current directory pwd # chmod 755 21.sh # ./21.sh 38、比较数字大小 #!/bin/bash test $1 -gt $2 echo $1 test $1 -lt $2 echo $2 test $1 -eq $2 echo $1$2 39、 40、 参考链接 http://www.cnblogs.com/along21/p/7519710.html 五分钟搞定Bash功能与使用技巧 https://mp.weixin.qq.com/s/qxyV0Ye9yIqkUA7V8Kx0wQ 17个案例带你3分钟搞定Linux正则表达式https://mp.weixin.qq.com/s/bAc-coGwnKxvQHOkqZRJAQ Shell编程shell脚本的条件测试 : https://mp.weixin.qq.com/s?__bizMzU4MjUzNDMyOQmid2247483848idx1sn2d3165fefd1573e3f46b7133bc786982chksmfdb7941ecac01d0841a39cac28392a613d466ba88b4d7168583d5dedfddc845e4fb0254833a4scene21#wechat_redirect 资料 shell脚本常用知识 http://ju.outofmemory.cn/entry/225010 如何让执行到中途中断的程序继续自动执行? : http://www.voidcn.com/code/p-noktlbvp-p.html 重启Tomcat的shell脚本 : http://www.voidcn.com/code/p-gejgbzas-h.html shell产生随机数七种方法 http://blog.sina.com.cn/s/blog_638b7ebb0102vurp.html linux 网卡流量监控 (脚本) : http://www.voidcn.com/code/p-glpuwwga-p.html Shell 入门指南 : https://wdxtub.com/2016/08/02/shell-guide/ 《shell脚本系统监控-------邮件告警》 : http://blog.51cto.com/leoheng/1955773 编写了一个ssh管理并自动登录shell脚本 : https://www.jianshu.com/p/789287ba0e6b shell脚本加密 | shc : https://www.jianshu.com/p/7f3db04c0786 shell脚本进阶 详解及其实例一 : https://www.cnblogs.com/keerya/p/7530802.html Shell编程shell脚本的条件测试 : https://mp.weixin.qq.com/s?__bizMzU4MjUzNDMyOQmid2247483892idx1sn8490118c4babd6ff9582d80507ecee14chksmfdb79422cac01d34ac60c528dd8acd538242d857b9b51a6fea177cb402d7ed9c0f51d7a8648fscene21#wechat_redirect If条件语句-监测系统内存报警 : http://mp.weixin.qq.com/s?__bizMzU4MjUzNDMyOQmid2247483877idx1sn87eb31b447ce9c995e5e8861d9b9dfc8chksmfdb79433cac01d252b39e7c5447a999674b988b1d5b8706b3cfde8ddb38665688a84111a8b71scene21#wechat_redirect Shell学习---Shell脚本的静态检查工具shellcheck : https://www.cnblogs.com/ftl1012/p/9568635.html Linux 下Shell的学习之优秀博主推荐 : https://www.cnblogs.com/ftl1012/p/9567984.html Linux 下Shell的学习3-优秀demo : https://www.cnblogs.com/ftl1012/p/9314069.html Linux 下shell中exec解析 : https://www.cnblogs.com/ftl1012/p/9310536.html Linux 下Shell的学习2 : https://www.cnblogs.com/ftl1012/p/9310505.html Linux 下Shell的学习 : https://www.cnblogs.com/ftl1012/p/shell.html shell脚本_查看网段中的存活主机和MAC地址 : http://blog.51cto.com/11638832/1855990 shell脚本_while、if脚本语句_价格竞猜 : http://blog.51cto.com/11638832/1855989 根据字段状态删除指定目录文件的shell脚本 荐 : http://blog.51cto.com/liangey/1641878 SHELL网络爬虫实例剖析 荐 :: http://blog.51cto.com/nolinux/1552472 如何用SHELL写好网络爬虫 荐 : http://blog.51cto.com/nolinux/1550976 SHELL20篇 https://blog.csdn.net/stpeace/article/category/6952361 Shell中的循环语句for、while、until实例讲解 : https://www.jb51.net/article/50643.htm 笔记 | 史上最全的正则表达式 : https://mp.weixin.qq.com/s/SA3OnfZD-cFVi7IVfKwKnw shell去掉文件中空行(空白行)的方法详解 : https://www.jb51.net/article/42288.htm 转载于:https://my.oschina.net/u/3803405/blog/1816950