shell01
类似于widnows下批处理文件
bash的特性
gnu bash
自动补全 –多用tab键
历史记录 history
–!$ –代表上一条命令后面的部分
–!984 –重复运行第984条命令
–!useradd –从下往上匹配,第一个以useradd开头的
–CTRL+R键 –进入匹配模式
~ –代表家目录
别名功能 alias unalias
管道
重定向
作业管理 jobs管理
shell编程
变量:
变量的用途
1,例$PATH,为了搜索方便
2,脚本里,使用变量可以引用方便
环境变量:
env –列举所有的环境变量
set –环境变量之外的自定义的变量也会列举出来
PS1=\'[\\u@\\h \\W]\\$ \’
\\t 24小时格式时间
\\H 完整的主机名
\\v bash版本
PS1=\'[\\u@\\h \\W\\t]\\$ \’ –可以修改加上时间
PS1=\’my server–>\’ –也可以直接换成一段字符串
如果要永久支持,可以放到环境变量的文件
全局
/etc/profile
/etc/bashrc
每个用户的家目录下
~/.bashrc
~/.bash_profile
[root@server4 ~]# locale –语言有关的变量
LANG=en_US.UTF-8 –主语言的环境
LC_CTYPE=\”en_US.UTF-8\”
LC_NUMERIC=\”en_US.UTF-8\”
LC_TIME=\”en_US.UTF-8\”
LC_COLLATE=\”en_US.UTF-8\”
LC_MONETARY=\”en_US.UTF-8\”
LC_MESSAGES=\”en_US.UTF-8\”
LC_PAPER=\”en_US.UTF-8\”
LC_NAME=\”en_US.UTF-8\”
LC_ADDRESS=\”en_US.UTF-8\”
LC_TELEPHONE=\”en_US.UTF-8\”
LC_MEASUREMENT=\”en_US.UTF-8\”
LC_IDENTIFICATION=\”en_US.UTF-8\”
LC_ALL=
上面的变量一般不要去改,如果要改变语言集,可以改下面的文件
vim /etc/sysconfig/i18n
下面是临时修改的方法
[root@server4 ~]# export LANG=en_US.UTF-8
[root@server4 ~]# export LANG=zh_CN.UTF-8
如果电脑允许注销或者重启,直接在登录的界面选语言集就好了
shell脚本常识:
#!/bin/sh #!/bin/bash #!/bin/env bash
#! 两个字节的魔法字符,在Linux里用来定义文件类型,表示用哪个程序来解释下面的语句
这是一个不成文的要求
# <comment>
注释
<< 可用来多行注释
chmod +x <>.sh
sh <>.sh bash <>.sh # 这种情况下, 脚本的#!不再生效
一个优秀的脚本, 除了要优秀地完成任务, 还要有漂亮的代码, 以及有用的帮助, 必要的参数!
shell的变量
不需要申明,弱类型
export定义变量,把自定义变量转化为环境变量
[root@server4 ~]# a=1 –把1赋值给变量a
[root@server4 ~]# echo $a –看变量的值
1
[root@server4 ~]# bash –进入子bash环境
[root@server4 ~]# echo $a –发现查不到变量a
[root@server4 ~]# exit –退出到父bash
exit
[root@server4 ~]# export a=1 –使用export
[root@server4 ~]# echo $a
1
[root@server4 ~]# bash
[root@server4 ~]# echo $a –再次进入子bash,就可以查看到变量a的值
1
declare typeset –这两个也是定义变量的,都是内部命令
[root@server4 ~]# b=1+1
[root@server4 ~]# echo $b
1+1
[root@server4 ~]# declare -i b=1+1
[root@server4 ~]# echo $b
2
变量定义的规则:
1,区分大小写
2,定义时的格式,等号两边不能有空格,对于有空格的字符串,要用引号引起来
[root@server4 ~]# B=\’ 3fds afsa\’
[root@server4 ~]# echo $B
3fds afsa
3,单引号与双引号的,单引的变量或者特殊字符就是为一般字符;但双引内的变量或者特殊字符可以保持它的变量特性
[root@server4 ~]# echo $a
1
[root@server4 ~]# echo \’$a\’
$a
[root@server4 ~]# echo \”$a\”
1
4,变量名可以是字母和数字, _ , 但不能以数字开头
[root@server4 ~]# a1=2
[root@server4 ~]# echo $a1
2
[root@server4 ~]# 1a=3
bash: 1a=3: command not found
5,变量的获取方式 $变量名 ${变量名}
[root@server4 ~]# echo ${a}
1
[root@server4 ~]# echo $a
1
6,取消变量的定义
[root@server4 ~]# unset a
[root@server4 ~]# echo $a
7,比较特殊的变量定义方式
[root@server4 ~]# a=`which mount`
[root@server4 ~]# rpm -qf $a
util-linux-2.13-0.52.el5
[root@server4 ~]# a=$(which vi) –小括号
[root@server4 ~]# rpm -qf $a
vim-minimal-7.0.109-6.el5
[root@server4 ~]# read a –这样主要是由运行脚本的用户去定义变量的值
hello world
[root@server4 ~]# echo $a
hello world
例一:
echo -n \’input your name:\’ –echo使用-n参数代表输出之后不换行
read name
echo \”welcome, $name\”
read -p \”input your name:\” name –read使用-p参数同上一样的效果
echo \”welcome, $name\”
read -p \”input your major:\” -t 5 major –t参数指定输入值的时间只有五秒
echo \”$name\’s major is $major\”
read -s -p \”input your password:\” password –s参数代表隐藏输入
echo
echo \”$name\’s password is $password\”
read -d \’;\’ abc
read -e abc # readline
read -e -i \’/var/log/audit/audit.log\’ abc # 给readline指定一个默认值
read -n 2 abc #只允许输入几个字符
# read -t 3 abc
# echo $abc
# read -e -i \’7788\’ -t 3 abc
7788#
#
# echo $abc
# read -e -i \’7788\’ -t 3 abc
7788
# echo $abc
7788
#
例二:使用普通用户在文本终端模拟root用户登录,并保存root用户的密码
#!/bin/bash
hostnamehead=`hostname |cut -d \’.\’ -f1`
#hostnamehead=`hostname -s`
clear
echo -n \”Red Hat Enterprise Linux Server release 5.6 (Tikanga)\”
#echo -n `cat /etc/redhat-release`
echo
echo -n \”Kernel `uname -r` on an `uname -m`\”
echo
echo
read -p \”$hostnamehead login:\” username
read -s -p \”Password:\” password
sleep 3
echo
echo \”Login incorrect\”
echo \”$username\’s password is $password\” >> /pub/classNote/ule-scripts/shell/shell01/rootpassword.txt
echo
echo
sh $0
———————————–
echo $$ 返回程序的PID
echo $0 代表运行的脚本的名字
echo $1 代表运行脚本后接的第一个参数
echo $2 代表运行脚本后接的第二个参数
…………………………
echo ${10}
echo $*
echo $@ 代表所有参数
echo $? 执行成功则返回0 ,执行失败则返回非0值
例三:
[root@server4 shell01]# cat example01.sh
#!/bin/bash
echo $$
echo $0
echo $1
echo $2
echo $(($1+$2))
echo $*
echo $@
echo $?
[root@server4 shell01]# sh example01.sh 1 2 –用sh命令去执行
[root@server4 shell01]# ./example01.sh 1 2 –./也可以执行,但要执行权限
小练习:
<#>:
要求用户输入两个数字,然后打印出这两个数的和与差。
结果类似:
Input the 1st number: 2
Input the 2nd number: 7
Result:
2+7=9
2-7=-5
ps.
`bc<<<2+7`
echo \’2+7\’ | bc
echo $[2+7]
echo $((2+7))
例四,
以一个日志文件为例比如说是/var/log/aaa.log
每天备份/var/log/aaa.log并移到专门的备份目录下/backup,并改名有时间标记
#!/bin/bash
#
#backup /var/log/rsyncd.log
#
# copy the log to /work/backup, and rename to \’rsync-`data +%F`.log\’
cp /var/log/rsyncd.log /work/backup/rsyncd-$(date +%F).log
# empty the log
:> /var/log/rsyncd.log
之后就是把这个脚本放到计划任务里去执行
01 3 * * * sh /path/shell.sh
例五,日志切割脚本
改进上面的例子
每天备份/var/log/aaa.log并移到专门的备份目录下/backup的年目录/月目录,并改名有时间标记 ;比如说是2010-09-06号把昨天的日志给移到/backup/2010/09/2010-09-05.aaa.log
提示:[root@server4 shell01]# date -d \’yesterday\’ +\’%Y-%m-%d\’
2010-09-05
下面是没有变量的情况,看起来非常难受
#!/bin/bash
mkdir /backup/`date -d \’yesterday\’ +\’%Y\’`/`date -d \’yesterday\’ +\’%m\’` -p
mv /var/log/aaa.log /backup/`date -d \’yesterday\’ +\’%Y\’`/`date -d \’yesterday\’ +\’%m\’`/`date -d \’yesterday\’ +\’%Y-%m-%d\’`.aaa.log
touch /var/log/aaa.log
例六
改为变量的情况
#!/bin/bash
year=`date -d \’yesterday\’ +\’%Y\’`
month=`date -d \’yesterday\’ +\’%m\’`
day=`date -d \’yesterday\’ +\’%Y-%m-%d\’`
logpath=\”/backup\” –这里有一点要注意,定义的目录后面有没有/,在引用时最好都加一个/,多个/是没有问题的,少/就有问题了
mkdir -p /backup/$year/$month –如果目录存在,再建立会报错,加-p参数时可以避免这个报错信息
mv /var/log/aaa.log $logpath/$year/$month/$day.aaa.log
touch /var/log/aaa.log
eg:
#!/bin/bash
#
#backup /var/log/rsyncd.log
#
oldfile=\’/var/log/rsyncd.log\’
filename=\”rsyncd-`date -d \’yesterday\’ +%F`.log\”
year=`date -d \’yesterday\’ +%Y`
month=`date -d \’yesterday\’ +%m`
bakpath=\”/work/backup/$year/$month\”
mkdir -p $bakpath
cp $oldfile $bakpath/$filename -rf
:> $oldfile
1 0 * * * bash /work/shell01/backup01.sh
———————————————————–
重定向
1,标准输入(stdin);代码为0, 使用<或者<< –默认设备是键盘
2,标准输出(stdout);代码为1, 使用>或者>>或者1>或者1>> –默认设备是屏幕
3,错误输出(stderr);代码为2, 使用2> 或者 2>> –默认设备是屏幕
cat > abc.log <<EOF
…
EOF
标准输入 ----> 命令 ---->标准输出 -->设备/文件
|
|
|
错误输出
|
|
设备/文件
[a@server4 ~]$ find /home/ -name a
/home/a –标准输出
find: /home/aa: Permission denied –下面全是错误输出
find: /home/user2/.ssh: Permission denied
find: /home/d: Permission denied
find: /home/b: Permission denied
find: /home/c: Permission denied
find: /home/user1: Permission denied
find: /home/smb2: Permission denied
find: /home/g: Permission denied
find: /home/f: Permission denied
find: /home/e: Permission denied
find: /home/bb: Permission denied
find: /home/smb: Permission denied
[a@server4 ~]$ find /home/ -name a > /home/a/find.log –把标准输出重定向到一个文件,所以屏幕显示的是错误输出
find: /home/aa: Permission denied
find: /home/user2/.ssh: Permission denied
find: /home/d: Permission denied
find: /home/b: Permission denied
find: /home/c: Permission denied
find: /home/user1: Permission denied
find: /home/smb2: Permission denied
find: /home/g: Permission denied
find: /home/f: Permission denied
find: /home/e: Permission denied
find: /home/bb: Permission denied
find: /home/smb: Permission denied
[a@server4 ~]$ cat /home/a/find.log
[a@server4 ~]$ find /home/ -name a > /home/a/find.log 2> /home/a/finderr.log
–标准输出和错误输出都重定向到不同的文件
[a@server4 ~]$ find /home/ -name a > /home/a/findunion.log 2>> /home/a/findunion.log–标准输出和错误输出都重定向到相同的文件
[a@server4 ~]$ find /home/ -name a > /home/a/findunion.log 2>&1
–标准输出和错误输出都重定向到相同的文件,这种写法比较特殊,最好用这种
[a@server4 ~]$ find /home/ -name a > /dev/null 2>&1 –如果不需要脚本运行过程中的信息,可以扔到/dev/null
双重重定向
[root@server4 ~]# last |tee /home/a/last.txt –又显示到屏幕,同时还重定向到一个文件
[root@server4 ~]# cat > cat.txt <<EOF
> sdfsagweqtg
> dfgdgfdgdse
> dfgsgdfs
ctrl+d –结束,写脚本时用EOF代替
here document
例七;使用EOF实现非shell环境下的命令执行
#!/bin/bash
passwd <<EOF
newpasswd
newpasswd
EOF
——————————————————-
管道
grep cut
[root@server4 shell01]# cat /etc/passwd |grep root
[root@server4 shell01]# cat /etc/syslog.conf |grep -v \’^#\’|grep -v \’^;\’|grep -v ^$
cut –多用于日志截取,对多个空格的处理比较吃力,那种情况就可以使用awk等别的工具
-d 接分隔符
-f 指定分隔后第几列
[root@server4 shell01]# cat /etc/passwd |cut -d : -f7 –显示/etc/passwd文件里以:号分隔的第七列
截取本机的IP
[root@server4 shell01]# ifconfig eth0| grep Bcast |cut -d \” \” -f2 –发现没有得到结果,因为前面有多个空格
[root@server4 shell01]# ifconfig eth0| grep Bcast |cut -d \” \” -f12 |cut -d \”:\” -f2 –但是可以试出来多个空格,这里是-f12
10.1.1.45
[root@server4 shell01]# ifconfig eth0| grep Bcast |cut -d \”:\” -f2 |cut -d \” \” -f1 –可以先以:号分隔,再以空格分隔
10.1.1.45
——————————————–
排序统计有关的命令: wc sort uniq
wc
-l 显示行数
-w 显示单词数
-m 显示字符数
默认不加任何参数,就表示相当是上面三个参数都加
[root@server4 shell01]# cat /root/cat.txt |wc
3 6 39
[root@server4 shell01]# cat /root/cat.txt |wc -l –这个用得比较广泛
3
[root@server4 shell01]# cat /root/cat.txt |wc -w
6
[root@server4 shell01]# cat /root/cat.txt |wc -m
39
sort 排序
-r 反向排序
-n 以数字来排
-f 大小写不敏感
-t 分隔符 类似cut里的-d
-k 第几列 类似cut里的-f
[root@server4 shell01]# cat /etc/passwd |sort–默认以字母来排序,a-z
[root@server4 shell01]# cat /etc/passwd |sort -r–以字母反向排序
[root@server4 shell01]# cat /etc/passwd |sort -t \”:\” -k 3 –以:分隔的第三列也就是uid来排序,但是发现不是以数字大小来排,比如说这里 86排到了9的前面
[root@server4 shell01]# cat /etc/passwd |sort -t \”:\” -k 3 -n –要加上-n参数,来以数字大小排序
uniq 唯一 (unique)
注意的是:只在连续的范围内去掉重复值,只留一下
[root@server4 shell01]# cat /etc/passwd | cut -d \”:\” -f 7 |uniq
[root@server4 shell01]# cat /etc/passwd | cut -d \”:\” -f 7 |sort |uniq
从下面两个看出,顺序的不同,对结果是有很大影响的
[root@server4 shell01]# cat /etc/passwd | cut -d \”:\” -f 7 |grep bash |uniq
/bin/bash
[root@server4 shell01]# cat /etc/passwd | cut -d \”:\” -f 7 |uniq |grep bash
/bin/bash
/bin/bash
/bin/bash
/bin/bash
-c参数是count计算统计的意思
[root@server4 shell01]# cat /etc/passwd | cut -d \”:\” -f 7 |uniq -c
1 /bin/bash
4 /sbin/nologin
1 /bin/sync
1 /sbin/shutdown
1 /sbin/halt
1 /sbin/nologin
1
28 /sbin/nologin –表示一共连续28个/sbin/nologin
2 /bin/bash
1 /sbin/nologin
6 /bin/bash
1 /sbin/nologin
6 /bin/bash
———————————————————————
命令执行的判断顺序
;
&&
||
[root@server4 shell01]# ./configure ;make ;make install
[root@server4 shell01]# ./configure && make && make install –这两句结果一样,都是执行前面OK后,再执行后面
注意下面两个符号意义相反
[root@server4 shell01]# ls /test/ && touch /test/1 –前面执行成功,则执行后面
[root@server4 shell01]# ls /test/ || touch /test/2 –前面执行失败,才执行后面
当&&和||混用时,可以替换条件判断语句,但要注意的是逻辑上不要搞乱了
下面要使用&&和||混用来实现
如果/test存在,则输出existed
如果/test不存在,则输出not existed
注意要使用&&再使用||
正常写法:
[root@server4 shell01]# ls /test/ && echo \’existed\’ || echo \’not existed\’
existed
[root@server4 shell01]# ls /testsdfsafa/ && echo \’existed\’ || echo \’not existed\’
ls: /testsdfsafa/: No such file or directory
not existd
错误写法:
[root@server4 shell01]# ls /test/ || echo \’existed\’ && echo \’not existed\’
[root@server4 shell01]# ls /testgsdgsa/ || echo \’existed\’ && echo \’not existed\’
ls: /testgsdgsa/: No such file or directory
existed
not existed
—————————————————————-
例八:
条件判断:
if 命令 ; then
动作
fi
if 命令 ; then
动作
else
动作
fi
if 命令 ; then
动作
elif 命令;then
动作
else
动作
fi
man test 可以查看很多判断的条件的帮助
文件存在与否和类型的判断
-e 是否存在
-f 是否为文件
-d 是否为目录
-L 是否为链接文件
-p 是否为管道文件
-b block
-c character
-S socket
-s 是否为非空文件
文件权限的判断
-r 是否可读
-w 是否可写
-x 是否可执行
-u 是否有suid,就是前三位是否有s位
-g 是否有sgid
-k 是否有t位
两个文件的比较判断
-nt: file1 -nt file2 比较file1是否比file2新
-ot: file1 -ot file2 比较file1是否比file2旧
-ef: 比较是否为同一个文件,用于判断硬链接,指向的是同一个innode号
整数之间的判断
-eq 相等
-ne 不等
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于
字符串之间的判断和比较
-z 是否为空字符串
-n 是否为非空字符串
string1 = string2 是否相等
string1 != string2 是否不等
多重条件判断
-a 条件1 -a 条件2 两个条件都满足,才为true
-o 条件1 -o 条件2 两个条件满足其一,就为true
#!/bin/bash
#判断/etc/inittab是否存在
if [ -e /etc/inittab ];then #注意中括号内的两边要有空格
echo \’/etc/inittab existed\’
else
echo \’/etc/inittab not existed\’
fi
echo \’=========================================\’
#判断/etc是否为目录
if [ -d /etc ];then
echo \’/etc/ is a directory\’
else
echo \’/etc/ is not a directory\’
fi
echo \’=========================================\’
#判断/test/1是否为非空文件
if [ -s \”/test/1\” ];then
echo \’/test/1 is not a empty file\’
else
echo \’/test/1 is a empty file\’
fi
echo \’=========================================\’
#判断/tmp目录是否有t位
if [ -k /tmp ];then
echo \’/tmp has a sticky bit set\’
else
echo \’/tmp has not a sticky bit set\’
fi
echo \’=========================================\’
#判断两个文件的新旧
if [ \’/test/1\’ -nt \’/test/2\’ ];then
echo \’1 is newer than 2\’
else
echo \’1 is older than 2\’
fi
echo \’=========================================\’
#判断硬连接
if [ /var/spool/mail -ef /var/mail ];then
echo \’they are hard links\’
else
echo \’they are not hard links\’
fi
echo \’=========================================\’
#比较两个数值的大小
if [ 100 -ne 200 ];then
echo \’the two numbers are not equal\’
else
echo \’the two numbers are equal\’
fi
echo \’=========================================\’
#判断是否为空字符串
if [ -z \’\’ ];then #空格也是为非空,所以空字符串是引号内什么都没有
echo \’the lenth of string is zero\’
else
echo \’the lenth of string is not zero\’
fi
echo \’=========================================\’
#字符串间的比较
if [ \’aBc\’ != \’abc\’ ];then
echo \’the string are not equal\’
else
echo \’the string are equal\’
fi
echo \’=========================================\’
#多重条件判断
if [ -d /etc -o -e \’/test/1\’ ] ;then
echo \’/etc is a directory and /test/1 existed\’
else
echo \’/etc/ is not a directory or /test/1 not existed\’
fi
———————————————————–
题目:
1,交互模式输入一个年份,判断是否为闰年 (被4整除,但不能被100整除,或者能被400整除的就是闰年);熟悉if 结构和 && ||混合使用结构;最好能使用这两种方法写出来
read -p \”input the year:\” year
if [ $((year%4)) -eq 0 -a $((year%100)) -ne 0 -o $((year%400)) -eq 0 ];then
echo \’this is a leap year\’
else
echo \’this is not a leap year\’
fi
[[ $((year%4)) -eq 0 && $((year%100)) -ne 0 || $((year%400)) -eq 0 ]] && echo OK || echo KO
2,交互模式输入一个IP,判断是否能ping通这个IP
echo -n \”input a ip address:\”
read ip
ping -c 1 $ip >/dev/null 2>&1
if [ \”$?\” -eq 0 ];then
echo \’this ip is up!\’
else
echo \’this ip is down!\’
fi
3,交互模式输入一个文件,判断它的类型和权限,输出结果
read -e -p \”input a file name:\” file
if [ ! -e \”$file\” ];then
echo \”$file is not existed or it is not regular file\”
exit 1
fi
if [ -r \”$file\” ];then
echo \”read=yes\”
else
echo \”read=no\”
fi
if [ -w \”$file\” ];then
echo \”write=yes\”
else
echo \”write=no\”
fi
if [ -x \”$file\” ];then
echo \”execution=yes\”
else
echo \”execution=no\”
fi
4, 猜数字的游戏, 输入一个0-99的数字, 判断是否正确(与程序得到的随机数1-99比较)
提示: $RANDOM 可以取个随机数
5. 成绩判断
让运行脚本的用户输入一个名字和他的成绩,成绩必须是0-100. 否则退出程序,并显示错误信息
判断用户输入的成绩:
0-59: 显示\”差\”
60-79:显示\”良\”
80-100:显示\”优\”
显示结果类似:
用户: 小李飞刀
成绩: 98
等级: 优
6,sort,uniq练习
shell01笔记目录下有一个sortuniq.txt
排成下面的形式
一:
2 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
4 news:x:9:13:news:/etc/news:
6 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
1 apache:x:48:48:Apache:/var/www:/sbin/nologin
1 ftp:x:14:50:FTP User:/www:/sbin/nologin
cat sortuniq.txt |sort|uniq -c |sort -t \”:\” -k 4 -n
二:
6 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
4 news:x:9:13:news:/etc/news:
2 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
1 ftp:x:14:50:FTP User:/www:/sbin/nologin
1 apache:x:48:48:Apache:/var/www:/sbin/nologin
cat sortuniq.txt |sort|uniq -c|sort -n -r
转载于:Shell/3251865