初识Shell——bashmysql
Linux中的shell有点相似Windows下的cmd.exe或者.bat。管理整个计算机硬件的实际上是操做系统的内核(Kernel),用户没法与内核直接交互,因此经过shell来跟内核通讯。即shell介于操做系统(Kernel)和用户之间,它是用户与内核的翻译官,是一个命令解释器。linux
常见的shell种类有:Bsh、Csh、Ksh、Bash、Zshgit
Bsh和Csh出现的较早,Ksh继承了它两的功能,Bash继承了Bsh和Ksh的升级版,并且是Linux系统中默认的shell,Zsh则兼具了各类shell的程序有点,交互式操做效率更高,但仍不及bash应用普遍。sql
Shell环境的切换:shell
登陆Shell:指用户每次登陆系统后自动加载的Shell程序,大多数Linux系统采用 /bin/bash 做为默认登陆Shell;/etc/shells 文件记录了系统支持的有效登陆Shell编程
[root@localhost ~]# cat /etc/shells ==>使用chsh -l命令也可查看 /bin/sh /bin/bash /sbin/nologin /bin/tcsh /bin/csh /bin/ksh [root@localhost ~]#
默认的shell是bash,那么如何切换shell环境呢?分为两种,一种是临时切换,即当此终端关闭时,下次启动仍然是bash,方法很简单,直接在终端输入shell名称;第二种则是更改用户登陆Shell,须要修改/etc/passwd文件中用户记录的最后一个字段,或者像前面讲到的使用修改用户的命令:usermod -s shell程序路径 用户名,也可使用chsh命令,下次登陆有效。安全
查看当前shell能够经过/etc/passwd来查看,要查看系统默认使用的shell,可使用echo $SHELL。bash
bash的经常使用功能:函数
类型学习 |
设备文件 |
文件描述编号 |
默认设备 |
标准输入 |
/dev/stdin |
0 |
键盘 |
标准输出 |
/dev/stdout |
1 |
显示器 |
标准错误输出 |
/dev/stderr |
2 |
显示器 |
(备注:/dev/stdin、/dev/stdout、/dev/stderr这三个文件是一个符号连接,输入输出与重定向关系紧密)
类型 |
操做符 |
用途 |
重定向标准输入 |
< |
将命令中接收输入的途径由默认的键盘更改成指定的文件 |
重定向标准输出 |
> |
将命令的执行结果输出到指定的文件中,而不是直接显示在屏幕上 |
>> |
将命令执行的结果追加输出到指定文件 |
|
重定向标准错误 |
2> |
清空指定文件的内容,并将标准错误信息保存到该文件中 |
2>> |
将标准错误信息追加输出到指定的文件中 |
|
重定向标准输出和 标准错误 |
&> |
将标准输出、标准错误的内容所有保存到指定的文件中,而不是直接显示在屏幕上 |
管道操做符号是“|”,链接左右两个命令,将左侧的命令输出的结果,做为右侧命令的输入(处理对象)。管道是脚本语言的特点,它能够讲多个功能链接起来造成一个大的功能,这点与面向对象有很大的不一样。
例如我如今要查看历史记录命令的第4行:则可先将前4条命令显示出来,在显示前4条命令的最后一条:history | head -4 | tail -1 这样即取出了第四条命令。
Shell变量
Shell变量和其余语言的变量含义大同小异,就是能够存放不一样的内容,它也为灵活管理Linux系统提供特定参数。通常有两层意思:变量名:使用固定的名称,由系统预设或用户定义;变量值:可以根据用户设置、系统环境变化而变化。
Shell变量的种类:
变量的赋值与引用:
定义新的变量名要以英文字母或下划线开头,区分大小写,格式为:变量名=变量值
查看变量的值:echo $变量名
[root@localhost ~]# DAY=Sunday [root@localhost ~]# echo $DAY ==>经过$符号引用指定名称的变量值 Sunday [root@localhost ~]#
(注意:在查看变量时,若是变量名容易和后边的字符串连在一块儿致使混淆,则应该使用大括号将变量名括起来,使用形式为:${变量名} ,例如: 若已知变量Var的值为Benet,则执行“echo $Var3.0”命令后将显示结果“.0”而不是“Benet3.0”,由于在该命令中,会将“Var3”当成变量名(默认未定义此变量)。若但愿正确显示“Benet3.0”的输出结果,则须要执行“echo ${Var}3.0”)
[root@localhost ~]# Var =Benet [root@localhost ~]# echo $Var Benet [root@localhost ~]# echo $Var3.0 .0 [root@localhost ~]# echo ${Var}3.0 Benet3.0 [root@localhost ~]#
从键盘输入内容为变量赋值,格式为:read [-p "输入信息"] 变量名
[root@localhost ~]#read var haha ==>这里等待输入 [root@localhost ~]#echo $var haha [root@localhost ~]#
在给变量赋值时,使用不一样的引号操做的区别:
[root@localhost ~]#name=linuxidc [root@localhost ~]#echo $name linuxidc [root@localhost ~]#myname="$name is me" ==>这里使用的是双引号 [root@localhost ~]#echo $myname linuxidc is me ==>将$name这个变量执行出来了 [root@localhost ~]#myname='$name is me' ==>这里使用的是单引号 [root@localhost ~]#echo $myname $name is me ==>原样显示出来了,$name没有执行 [root@localhost ~]#
[linuxidc@localhost ~]$ locate crontab /etc/anacrontab /etc/crontab /usr/bin/crontab /usr/share/man/man1/crontab.1.gz ..... [linuxidc@localhost ~]$ ls -l `locate crontab` ==>先执行locate crontab,再执行ls -l -rw-r--r-- 1 root root 298 2006-12-18 /etc/anacrontab -rw-r--r-- 1 root root 255 2006-07-15 /etc/crontab -rwsr-sr-x 1 root root 315416 2008-07-15 /usr/bin/crontab -rw-r--r-- 1 root root 1846 2008-07-15 /usr/share/man/man1/crontab.1.gz ..... [linuxidc@localhost ~]$
设置变量的做用范围,格式:export 变量名
通常状况下,父进程的自定义变量是没法在子进程中使用的,可是经过export将变量变成环境变量后,就可以在子进程下使用了。
[root@localhost ~]#name=linuxidc [root@localhost ~]#echo $name linuxidc [root@localhost ~]# export name ==>输出为全局变量 [root@localhost ~]# zsh [root@localhost]~# echo $name linuxidc [root@localhost]~# exit [root@localhost root]# unset name==>消除变量内容 [root@localhost root]# echo $name [root@localhost ~]#
变量还有一个好处,当您常常访问一个目录时,并且这个目录比较长,能够将它付给一个简单的变量,这样进入这个目录时候只需cd 变量就好了。如work="~/temp/2013/test/",则进入这个目录只需cd work。
数值变量的运算:
以前讲到过可使用命令bc来打开一个计算器,其实Bash程序并不适合进行强大的数学运算,例如小数或指数运算的,通常只能进行简单的整数运算,若不使用bc,则也可使用下列格式来进行简单数值计算:
格式:expr 变量1 运算符 变量2 [..运算符 变量n...]
expr命令经常使用的运算符有:+、-、\*(注意要有\)、/、%
[linuxidc@localhost ~]$ expr 10 * 2 expr :语法错误 [linuxidc@localhost ~]$ expr 10 \* 2 20 [linuxidc@localhost ~]$expr 10 + 2 12 [linuxidc@localhost ~]$
环境变量
环境变量配置文件:全局配置文件:/etec/profile
用户配置文件:~/.bash_profile
查看环境变量:env
set (set命令能够查看全部的Shell变量,其中包括环境变量)
常见的环境变量:
位置变量:
表示为$n,n为1~9之间的数字,$n的做用就是为脚本文件传递执行参数。
[linuxidc@localhost ~]ls -a -l -l ==>a就是第1个位置变量,依次类推,其实这个命令就是ls -al
预约义变量:
[root@localhost ~]# bash [root@localhost ~]# echo $0 $$ ==>查看当前所执行进程的名称、PID号 -bash 32484 [root@localhost ~]# exxit ==>执行一条错误的命令 bash: exxit: command not found [root@localhost ~]# echo $? 127 ==>返回非0值,表示上一条命令异常 [root@localhost ~]# exit exit [root@localhost ~]# echo $? 0 ==>返回0,说明上一条命令正常
灵活使用这些变量,将大大加强Shell脚本程序的功能,$0做为预约义变量,表示当前执行的程序名,须要与$1~$9的位置变量区分开。
引入shell脚本
shell脚本:
[root@localhost ~]# vi repboot.sh #!/bin/bash ==>声明使用的shell环境,根据执行的方式不一样可加可不加 # 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脚本的简单语法
提到编程,条件、分支、循环等语法确定少不了。shell脚本编程亦是如此,下面只是结合最近学习的一些简单语法作的笔记,若有错误,欢迎指正。
if条件语句
条件测试操做
test命令:
用途:测试特定的表达式是否成立,当条件成立时,命令执行后的返回值为0,不然为其它值
格式:test 条件表达式 或者
[ 条件表达式 ](注意:方括号[]和条件表达式语句之间至少须要一个空格)
常见的测试类型:测试文件状态;字符串比较;整数值比较;逻辑测试
测试文件状态:[ 操做符 文件或目录 ]
如何判断当前所在的工做目录是否为 /usr/src? [ $PWD = “/usr/src” ] && echo “YES” || echo “NO”
[root@localhost ~]# [ -d /etc/vsftpd ] [root@localhost ~]# echo $? 0 ==>返回值为0,表示上一步测试的条件成立 [root@localhost ~]# [ -d /etc/hosts ] [root@localhost ~]# echo $? 1 [root@localhost ~]# [ -e /media/cdrom ] && echo "YES" ==>若是测试的条件成立则输出“YES” YES [root@localhost ~]# [ -e /media/cdrom/Server ] && echo "YES“ [root@localhost ~]#
上述&&是“与”的意思,“… && echo YES”表示若是没有输出,则表示前面执行的测试条件不成立或命令出错。(备注:l测试文件是否可写(-w)时,不要以root用户(特权用户)的身份执行测试,不然可能会没法准确判断)
整数值比较:[ 整数1 操做符 整数2 ]
[root@localhost ~]# who | wc -l 5 [root@localhost ~]# [ `who | wc -l` -le 10 ] && echo "YES" ==>若是登陆用户数小于或等于10则输出YES YES [root@localhost ~]# df -hT | grep "/boot" | awk '{print $6}' 12% [root@localhost ~]# BootUsage=`df -hT | grep "/boot" | awk '{print $6}' | cut -d "%" -f 1`
[root@localhost ~]# echo $BootUsage 12 [root@localhost ~]# [ $BootUsage -gt 95 ] && echo "YES" ==>若是/boot分区的磁盘使用率超过95%则输出YES
条件测试操做:[ 字符串1 = 字符串2 ]
[root@localhost ~]# read -p "Location:" FilePath Location:/etc/inittab [root@localhost ~]# [ $FilePath = "/etc/inittab" ] && echo "YES" ==>若是键入路径与指定的目录一致则输出YES YES [root@localhost ~]# [ $LANG != "en.US" ] && echo $LANG ==>若是当前的语言环境不是en_US,则输出LANG变量的值 zh_CN.UTF-8
(字符串比较能够用于检查用户输入,例如在提供交互式操做时,判断用户输入的选择项是否与指定的变量内容相匹配)
逻辑测试:[ 表达式1 ] 操做符 [ 表达式2 ]
[root@localhost ~]# echo $USER root [root@localhost ~]# [ $USER != "teacher" ] && echo "Not teacher" ==>若是发现用户不是teacher,则提示“Not teacher” Not teacher [root@localhost ~]# [ $USER = "teacher" ] || echo "Not teacher" Not teacher
if语句结构——当“条件成立”时执行相应的操做
单分支:
if 条件测试命令
then 命令序列
fi
if语句简单应用示例
#!/bin/bash temp=2 if [ $temp -eq 2 ] then echo 'temp is 2' fi
保存为test文件,并将它设置为可执行(+x)
[jzhou@localhost ~]# chmod 775 test
[jzhou@localhost ~]# bash test
temp is 2
(备注:lthen能够写到与if一行,但要用分号隔开,例如: if [ $RATE -gt 80 ] ; then)
单分支:
if 条件测试命令
then 命令序列1
else 命令序列2
fi
#!/bin/bash service mysqld status &> /dev/null if [ $? -eq 0 ] ==>判断上句是否执行成功 then echo "mysqld service is running." else /etc/init.d/mysqld restart fi
提示用户输入一个整数,如何判断该值是否小于100? read “Input an integer:” NUM ; if [ $NUM -lt 100 ] ; then echo “小于100” else echo “大于或等于100” fi
多分支:
if 条件测试命令1 ; then
命令序列1
elif 条件测试命令2 ; then
命令序列2
elif ...
else
命令序列n
fi
for循环语句——根据变量的不一样取值,重复执行一组命令操做
for语句的结构
for 变量名 in 取值列表
do
命令序列
done
for语句简单应用示例
依次输出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 DIR="/opt" LMT=100 ValidUsers=`grep "/bin/bash" /etc/passwd | cut -d ":" -f 1` ==>得到使用bash做为登陆shell的用户名列表 for UserName in $ValidUsers do Num=`find $DIR -user $UserName | wc -l` if [ $Num -gt $LMT ] ; then echo "$UserName have $Num files." fi done
[root@localhost ~]# sh chkfileown.sh root have 6737 files. teacher have 344 files.
while循环语句——重复测试指定的条件,只要条件成立则反复执行对应的命令操做
while语句的结构
while 命令或表达式
do
命令列表
done
while语句简单应用示例
批量添加20个系统用户账号, 用户名依次为“stu1”、“stu2”、……、“stu20” #!/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
批量删除上述添加的20个系统用户账号 #!/bin/bash i=1 while [ $i -le 20 ] do userdel -r stu$i i=`expr $i + 1` done
分支控制语句
case语句——根据变量的不一样取值,分别执行不一样的命令操做
case 变量值 in
模式1)
命令序列1
;;
模式2)
命令序列2
;;
……
* )
默认执行的命令序列
esac
(当遇到双分号“;;”后跳转至esac表示结束分支。若是一直找不到相匹配的值,则执行最后一个模式“*)”后的默认命令序列,直到遇到esac后结束分支)
#!/bin/bash case $1 in start) echo "Start MySQL service." ;; stop) echo "Stop MySQL service." ;; *) echo "Usage:$0 start|stop" ;; esac
(/etc/init.d/ 目录下的各种脚本中,大量使用了case分支语句结构)
#!/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
(匹配模式中可使用方括号表示一个连续的范围,例如“[0-9]”;使用竖杠符号“|”表示或,例如“A|B”(A或者B))
unitl语句——根据条件执行重复操做
until 条件测试命令
do
命令序列
done
(•until 循环的结构与while命令相似,“until经过检测其后接命令的返回值“$?”来判断是否退出循环
•until:直到”测试条件“成立时终止循环,而while是:当”测试条件“成立时进行循环
•即:until在测试条件为假(非0)时执行循环,条件为真时(0)退出循环,正好与while循环相反)
shift语句——用于迁移位置变量,将 $1~$9 依次向左传递(不经常使用)
经过命令行参数传递多个整数值,并计算总和 [root@localhost ~]# vi showday.sh #!/bin/bash Result=0 while [ $# -gt 0 ] ==> $# 为预约义变量,表示位置参数的个数
do
Result=`expr $Result + $1` shift done echo "The sum is : $Result"
[root@localhost ~]# ./sumer.sh 12 34 56 The sum is : 102
循环控制语句
break:在for、while、until等循环语句和case中用于跳出当前的循环体,执行循环体后的语句;并不退出程序。执行break命令后将跳到done语句以后。
continue:在for、while、until等循环语句中,用于跳过循环体内余下的语句,从新判断条件以便执行下一次循环
shell函数应用
定义新的函数:
调用已定义的函数: 函数名
向函数内传递参数:函数名 参数1 参数2 ......
#!/bin/bash adder() { echo `expr $1 + $2` } adder 12 34 adder 56 789
[root@localhost ~]# sh adderfun.sh 46 845