Shell 编程
shell的作用和历史
Shell的作用 -- 命令解释器,“翻译官” vim /etc/shells shell文件(里面有好多不同的shell)
shell 常用功能
自动补全 Tab 命令历史 history history -w 同步历史命令/写入隐藏文件 history -c 清除历史记录 !n:执行历史记录中的第n条命令 !str:执行历史记录中以“str”开头的命令 vim /etc/profile 48 HISTSIZE=1000 为使用频率较高的复杂命令行设置简短的调用名称 存放位置:~/.bashrc vim /root/.bashrc 查看命令别名 格式:alias [别名] 设置命令别名 执行:alias 别名='实际执行的命令' alias ls='ls -lha' 设置之后需要执行此文件,否则不生效 ls 取消已设置的命令别名 格式:unalias 别名 unalias ls 输入重定向 man wc wc < install.log 输出重定向 ls > bak.list ls -l >> bak.list 标准错误输出 lss 2> bak.list lss 2>> bak.list 重定向标准输出和标准错误 ls &> /dev/null 黑洞设备文件(空设备文件) lss >> a.txt 2>&1 重定向标准错误 2>&1 算是一个判断条件,如果前面正确,则无用,如果错误,就会把错误信息也输入到文件里
管道符 | netstat -an | grep ESTABLISHED | wc -l 统计与服务器的连接数量
Shell变量的应用
Shell变量的种类 用户自定义变量:由用户自己定义、修改和使用 环境变量:由系统维护,用于设置用户的Shell工作环境,只有极少数的变量用户可以修改 预定义变量:Bash预定义的特殊变量,不能直接修改 位置变量:通过命令行给程序传递执行参数 变量的赋值与引用 定义新的变量 变量名要以英文字母或下划线开头,区分大小写 格式:变量名=变量值 查看变量的值 格式:echo $变量名 查看所有变量:set 清除变量 unset 变量名 定义变量 Var=lamp echo ${var}3.0 "" '' `` 单引号 双引号 反引号 对比 DAY=xingqier echo $DAY 显示xingqier echo "$DAY" 显示xingqier echo '$DAY' 显示$DAY echo `$DAY` 执行 xingqier (必须是命令。否则报错) unset DAY DAY=ls echo `$DAY` 执行ls 环境变量赋值 设置变量的作用范围 格式:export 变量名... export 变量名=变量值 [...变量名n=变量值n] 查看环境变量 env 或 export 清除用户定义的变量 格式:unset 变量名 命令执行时查找顺序 1、以相对/绝对路径执行 2、由alias找到的执行 3、bash内部命令执行 4、按$PATH路径执行 环境变量PS1 echo $PS1 \d 日期 \t 时间(24) \T时间(12) \H 完整主机名 \h 简写主机名 \u 用户名 \v bash版本 \w 完整目录 \W 最后一个目录 \# 执行了第几个命令 \$ 提示符 PS1=‘[\u@\h \W \t #\#]\$’ 常见的环境变量: $USER 、$LOGNAME $UID 、 $SHELL 、$HOME $PWD、 $PATH $PS1、$PS2 查看环境变量 [root@localhost ~]# echo $PATH /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin 预定义变量 表示形式如下 $#:命令行中位置参数的个数 $*:所有位置参数的内容 $?:上一条命令执行后返回的状态,当返回状态值为0时表示执行正常,非0值表示执行异常或出错 $$:当前所在进程的进程号 $!:后台运行的最后一个进程号 $0:当前执行的进程/程序名 命令执行时查找顺序 1、以相对/绝对路径执行 2、由alias找到的执行 3、bash内部命令执行 4、按$PATH路径执行 [root@localhost ~]# bash [root@localhost ~]# echo $0 $$ bash 5887 [root@localhost ~]# exxit bash: exxit: command not found [root@localhost ~]# echo $? 127 [root@localhost ~]# exit exit [root@localhost ~]# echo $? 0 ; 命令顺序执行。 && 前后命令的执行存在逻辑与关系,只有&&前面的命令执行成功后,它后面的命令才被执行。 || 前后命令的执行存在逻辑或关系,只有||前面的命令执行失败后,它后面的命令才被执行。 通配符与特殊符号 通配符 * 任意多个 ? 任意一个 [] 括号内任一个 [^0-9]非数字 rm -rf * rm -rf ?.?? touch 1.txt 2.txt 3.txt rm -rf [1-9].* 特殊符号 \ 转义符 & 后台 ! 非
4.数值变量的运算 计算整数表达式的运算结果 格式:expr 变量1 运算符 变量2 ...[运算符 变量n] expr的常用运算符 加法运算:+ 减法运算: - 乘法运算: \* 除法运算: / 求模(取余)运算: % Bash程序并不适合进行强大的数学运算,例如小数或指数运算的,一般只能进行简单的整数运算 对Shell变量进行数值运算时,更多的时候是用于脚本程序的过程控制,如控制程序的循环次数 在expr命令的使用格式中,变量与运算符间是有空格的,可以同时使用多个运算符、多个变量 由于星号“*”作为Bash环境中的通配符使用,因此乘法运算符需要使用“\*”的特殊形式(转义字符) #!/bin/bash read -p "please input num1:" -t 30 test1 read -p "input num2:" -t 30 test2 declare -i sum=”$test1+$test2” echo “num1 + num2 = $sum”
shell脚本的概念
Shell脚本 1.用途:完成特定的、较复杂的系统管理任务 2.格式:集中保存多条Linux命令,普通文本文件 3.执行方式:按照预设的顺序依次解释执行 [root@localhost ~]# vi repboot.sh #!/bin/bash # To show usage of /boot directory and mode of kernel file. echo "Useage of /boot: " du -sh /boot echo "The mode of kernel file:" ls -lh /boot/vmlinuz-* [root@localhost ~]# chmod a+x repboot.sh 运行Shell脚本程序 1.直接执行具有“x”权限的脚本文件 例如:./repboot.sh 2.使用指定的解释器程序执行脚本内容 例如:bash repboot.sh 3.通过source命令(或 . )读取脚本内容执行 例如:souce repboot.sh 或 . hello.sh
shell脚本应用实例
示例1: 每周五17:30清理FTP服务器的公共共享目录 检查 /var/ftp/pub/ 目录,将其中所有子目录及文件的详细列表、当时的时间信息追加保存到 /var/log/pubdir.log 日志文件中,然后清空该目录 [root@localhost ~]# vi /opt/ftpclean.sh #!/bin/bash date >> /var/log/pubdir.log ls -lhR /var/ftp/pub >> /var/log/pubdir.log rm -rf /var/ftp/pub/* [root@localhost ~]# crontab -e 30 17 * * 5 /opt/ftpclean.sh chmod +x /opt/ftpclean.sh
示例2: 每隔3天时间3:30对数据库目录做一次完整备份 统计 /usr/local/mysql/var 目录占用的空间大小、查看当前的日期,并记录到临时文件 /tmp/dbinfo.txt 中, 将 /tmp/dbinfo.txt 文件、/usr/local/mysql/var 目录进行压缩归档,备份到/opt/dbbak/目录中, 备份后的包文件名中要包含当天的日期信息, 最后删除临时文件/tmp/dbinfo.txt [root@localhost ~]# vi /opt/dbbak.sh #!/bin/bash DAY=`date +%Y%m%d` SIZE=`du -sh /usr/local/mysql/var` echo "Date: $DAY" >> /tmp/dbinfo.txt echo "Data Size: $SIZE" >> /tmp/dbinfo.txt mkdir /opt/dbbak cd /opt/dbbak tar -zcPf mysqlbak-${DAY}.tar.gz /usr/local/mysql/var /tmp/dbinfo.txt rm -f /tmp/dbinfo.txt [root@localhost ~]# crontab -e 30 3 */3 * * /opt/dbbak.sh chmod +x /opt/dbbak.sh
shell 显示写法
从键盘输入内容为变量赋值 格式: read [-p "信息"] 变量名 结合不同的引号为变量赋值 双引号 “ ” :允许通过$符号引用其他变量值 单引号 ‘ ’ :禁止引用其他变量值,$视为普通字符 反撇号 ` ` :将命令执行的结果输出给变量 下面就是一个简单计算器的运用写法: read -p "input first num: " var1 read -p "input +-*/ : " var read -p "input second num: " var2 v=`echo " $var1 $var $var2 "|bc` echo "$var1 $var $var2 = $v"
Shell 正式编程
正则表达式
1 ^ #只匹配行首 2 $ #只匹配行尾 3 * #匹配0个或者多个单字符 4 [] #只匹配[]内字符,可以是一个单字符,也可以是字符序列,可以使用*表示[]内字符序列范围,如用[1-5]代替[12345] 5 \ #只用来屏蔽一个元字符的特殊含义 6 . #只匹配任意单字符 7 pattern\{n\} #匹配n次pattern 8 pattern\{n,\} #匹配n次以上pattern 9 pattern\{n,m\} #匹配n到m次pattern 11 ^只允许在一行的开始匹配字符或单词 ^d 筛选出以d开头的文件属性 12 ^ $ #匹配空行 13 ^.$ #匹配包含一个字符的行 14 kkk$ #匹配以kkk结尾的所有字符 15 \*\.pas #匹配以*.pas结尾的所有字符或文件 16 a\{2\}b #a出现两次,aab 17 a\{4,\}b #a至少出现4次,aaaab,aaaaab .. 18 a\{2,4\} #a出现次数范围2-4次 19 [0-9]\{3\}\.[0-9]\{3\}\.[0-9]\{3\}\.[0-9]\{3\} #匹配所有ip地址 20 cal 显示日历
shell编程中常用的命令
行提取命令 grep 选项: -v -n -i grep "[^a-z]oo" aa (文件名) oo前不是小写字母的行匹配。 注意:和开头没有关系 grep “\.$” aa 匹配以.结尾的行 grep "^[^A-Za-z]" aa 匹配不以字母开头的行 注意:所有字母不能这样写 A-z grep “^$” aa 匹配空白行 grep "oo*" aa 匹配最少一个o grep “g.*d” aa 匹配g开头,d结尾,中间任意字符 gd
列提取命令 awk '条件 {动作}' last | awk '{printf $1 "\t" $3 "\n"}' 提取last显示结果的第一和第三列 last | grep "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}"|awk '{printf $1 "\t" $3 "\n"}' 在last中提取包含ip的行,在行中提取第一和第三列 awk内置变量 FS 指定分隔符 more /etc/passwd | awk 'BEGIN {FS=":"} {printf $1 "\t" $3 "\n"}' 读取passwd文件,以":"为分隔符,截取第一和第三列 BEGIN 在截取前使分隔符生效。如果没有BEGIN,那么第一行自定义的分隔符不生效 1 last > file #把last命令结果保存在file文件中 2 awk ‘{print $0 “\n”}' file #查找出file文件中的每1列 3 awk '{print $1"\t"$7 “\n”}' file #查找出file文件中的第1列和第7列 cut cut -d “分隔符” -f 提取列 文件名 more /etc/passwd | grep "/bin/bash" | cut -d ":" -f 1,3 提取passwd文件中可以登录的用户的用户名和UID
输出命令 echo -e “输出内容” -e 识别格式化打印内容 echo -e “1\t2\t3” 打印tab键 echo -e "\e[1;31m this is red text \e[0m" 输出红色字体 \e[ 格式 1;31m 指定颜色 0m 恢复颜色(重置) 30m=黑色,31m=红色,32m=绿色,33m=黄色,34m=蓝色,35m=洋红,36m=青色,37=白色
shell条件测试操作
条件测试操作 test命令 用途:测试特定的表达式是否成立,当条件成立时,命令执行后的返回值为0,否则为其他数值 格式:test 条件表达式 [ 条件表达式 ] 常见的测试类型 测试文件状态 字符串比较 整数值比较 逻辑测试 测试文件状态 格式:[ 操作符 文件或目录 ] 常用的测试操作符 -d:测试是否为目录(Directory) -e:测试目录或文件是否存在(Exist) -f:测试是否为文件(File) -r:测试当前用户是否有权限读取(Read) -w:测试当前用户是否有权限写入(Write) -x:测试当前用户是否可执行(Excute)该文件 -L:测试是否为符号连接(Link)文件 [root@localhost ~]# [ -d /etc/vsftpd ] [root@localhost ~]# echo $? 0 [root@localhost ~]# [ -d /etc/hosts ] [root@localhost ~]# echo $? 1 [root@localhost ~]# [ -e /media/cdrom ] && echo "YES" YES [root@localhost ~]# [ -e /media/cdrom/Server ] && echo "YES” [root@localhost ~]# 整数值比较 格式:[ 整数1 操作符 整数2 ] 常用的测试操作符 -eq:等于(Equal) -ne:不等于(Not Equal) -gt:大于(Greater Than) -lt:小于(Lesser Than) -le:小于或等于(Lesser or Equal) -ge:大于或等于(Greater or Equal) [root@localhost ~]# who | wc -l 5 [root@localhost ~]# [ `who | wc -l` -le 10 ] && echo "YES" YES [root@localhost ~]# df -hT | grep "/boot" | awk '{print $6}' 18% [root@localhost ~]# BootUsage=`df -hT | grep "/boot" | awk '{print $6}' | cut -d "%" -f 1` [root@localhost ~]# echo $BootUsage 18 [root@localhost ~]# [ $BootUsage -gt 95 ] && echo "YES" 字符串比较 格式:[ 字符串1 == 字符串2 ] [ 字符串1 != 字符串2 ] [ -z 字符串 ] 常用的测试操作符 ==:字符串内容相同 !! ==两边不能有空格!!!【】两边必须有空格!!! !=:字符串内容不同,! 号表示相反的意思 -z:字符串内容为空 [root@localhost ~]# read -p "Location:" FilePath Location:/etc/inittab [root@localhost ~]# [ $FilePath == "/etc/inittab" ] && echo "YES" YES [root@localhost ~]# [ $LANG != "en.US" ] && echo $LANG zh_CN.UTF-8
逻辑测试 格式:[ 表达式1 ] 操作符 [ 表达式2 ] ... 常用的测试操作符 -a或&&:逻辑与,“而且”的意思 #前后两个表达式都成立时整个测试结果才为真,否则为假 -o或||:逻辑或,“或者”的意思 #操作符两边至少一个为真时,结果为真,否则结果为假 !:逻辑否 #当指定的条件不成立时,返回结果为真 [root@localhost ~]# echo $USER root [root@localhost ~]# [ $USER != "teacher" ] && echo "Not teacher" Not teacher [root@localhost ~]# [ $USER = "teacher" ] || echo "Not teacher" Not teacher
if 条件语句(流程控制)
if条件语句 -- 单分支 应用示例: 如果/boot分区的空间使用超过80%,输出报警信息 如果测试 / 目录的话 将 /boot 换成 /$ 就可以了 #!/bin/bash RATE=`df -hT | grep "/boot" | awk '{print $6}' | cut -d "%" -f1 ` if [ $RATE -gt 80 ] then echo "Warning,DISK is full!" fi
if条件语句 -- 双分支 应用示例: 判断mysqld是否在运行,若已运行则输出提示信息,否则重新启动mysqld服务 #!/bin/bash TEST=`/usr/bin/pgrep mysqld ` if [ “$TEST” != “” ] then echo "mysqld service is running." else /etc/init.d/mysqld restart fi
if条件语句 -- 多分支 相当于if语句嵌套,针对多个条件执行不同操作 if 条件测试命令1 ; then 命令序列1 elif 条件测试命令2 ; then 命令序列2 elif ... else 命令序列n fi
for 循环语句
应用示例1: 依次输出3条文字信息,包括一天中的“Morning”、“Noon”、“Evening”字串 [root@localhost ~]# vi showday.sh #!/bin/bash for TM in "Morning" "Noon" "Evening" do echo "The $TM of the day." done [root@localhost ~]# sh showday.sh The Morning of the day. The Noon of the day. The Evening of the day
应用示例2: 对于使用“/bin/bash”作为登录Shell的系统用户,检查他们在“/opt”目录中拥有的子目录或文件数量,如果超过100个,则列出具体个数及对应的用户帐号 #!/bin/bash DIR="/opt" LMT=100 ValidUsers=`grep "/bin/bash" /etc/passwd | cut -d ":" -f 1` for UserName in $ValidUsers do Num=`find $DIR -user $UserName | wc -l` if [ $Num -gt $LMT ] ; then echo "$UserName have $Num files." fi done
while 循环语句
重复测试指定的条件,只要条件成立则反复执行对应的命令操作 应用示例1: 批量添加20个系统用户帐号, 用户名依次为“stu1”、“stu2”、……、“stu20” 这些用户的初始密码均设置为“123456” --stdin 表示转换成键盘输入 expr 是shell计算器(bc)里的加法 #!/bin/bash i=1 while [ $i -le 20 ] do useradd stu$i echo "123456" | passwd --stdin stu$i &> /dev/null i=`expr $i + 1` done 应用示例2: 批量删除上例中添加的20个系统用户帐号 #!/bin/bash i=1 while [ $i -le 20 ] do userdel -r stu$i i=`expr $i + 1` done
case 多重分支语句
根据变量的不同取值,分别执行不同的命令操作 应用示例1: 编写脚本文件 mydb.sh,用于控制系统服务mysqld 当执行 ./mydb.sh start 时,启动mysqld服务 当执行 ./mydb.sh stop 时,关闭mysqld服务 如果输入其他脚本参数,则显示帮助信息 #!/bin/bash case $1 in start) echo "Start MySQL service." ;; stop) echo "Stop MySQL service." ;; *) echo "Usage:$0 start|stop" ;; esac 应用示例2: 提示用户从键盘输入一个字符,判断该字符是否为字母、数字或者其它字符,并输出相应的提示信息 #!/bin/bash read -p "Press some key, then press Return:“ KEY case "$KEY“ in [a-z]|[A-Z]) echo "It's a letter." ;; [0-9]) echo "It's a digit." ;; *) echo "It's function keys、Spacebar or other keys. " esac
shell 函数应用
Shell函数概述 在编写Shell脚本程序时,将一些需要重复使用的命令操作,定义为公共使用的语句块,即可称为函数 合理使用Shell函数,可以使脚本内容更加简洁,增强程序的易读性,提高执行效率 定义新的函数 function 函数名 { 命令序列 } 函数名() { 命令序列 } 调用已定义的函数 函数名 向函数内传递参数 函数名 参数1 参数2 ... 应用示例: 在脚本中定义一个加法函数,用于计算2个整数的和 调用该函数计算(12+34)、(56+789)的和 #!/bin/bash adder() { echo `expr $1 + $2` } adder 12 34 adder 56 789 [root@localhost ~]# bash adderfun.sh 46 845
额外
#传输文件的方法 yum -y install lrzsz rz #下载东西 wget 网址
监控工具 dstat和vmstat
编译安装: 工具下载地址:wget http://dstat.sourcearchive.com/downloads/0.7.2-2/dstat_0.7.2.orig.tar.gz yum安装: yum -y install dstat
写的比较详细的博客