Bash shell的基本操作与概念
特殊的shell变量
除了用户自定义的变量以外,在linux系统和bash shell环境中还有一些特殊的变量-环境变量,位置变量,预定义变量。下面分别进行介绍
环境变量
环境变量指的是出于运行需要而由linux系统提前创建的一类变量,主要用于设置用户的工作环境,包括用户的宿主目录,命令查找路径,用户当前目录,登录终端等。环境变量的值由linux系统自动维护,会随着用户状态的改变而改变。
使用env命令可以查看到当前工作环境下的环境变量,对于一些常见的环境变量应了解其各自的用途。例如变量USER表示用户名称,HOME表示用户宿主目录,LANG表示语言和字符集,PWD表示当前所在的工作目录,PATH表示命令搜索路径。
[root@Centos01 ~]# env
HOSTNAME=Centos01.test.com
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=192.168.1.100 4053 22
QTDIR=/usr/lib64/qt-3.3
QTINC=/usr/lib64/qt-3.3/include
SSH_TTY=/dev/pts/1
USER=root
PATH变量用于设置可执行程序的默认搜索路径,当仅指定文件名称来执行命令程序时,linux系统将PATH变量指定的目录搜索范围查找对应的可执行文件,如果找不到则会提示command not found.
[root@Centos01 ~]# mkdir /root/scripts
[root@Centos01 ~]# cd /root/scripts
[root@Centos01 scripts]# vi first.sh
[root@Centos01 scripts]# chmod +x first.sh
[root@Centos01 scripts]# ls -lh /root/scripts/first.sh
-rwxr-xr-x 1 root root 44 Jun 4 23:16 /root/scripts/first.sh
[root@Centos01 scripts]# echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@Centos01 scripts]# cd
[root@Centos01 ~]# first.sh
-bash: first.sh: command not found
[root@Centos01 ~]# PATH="$PATH:/root/scripts"
[root@Centos01 ~]# echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/root/scripts
[root@Centos01 ~]# first.sh
#
# /etc/fstab
# Created by anaconda on Thu Jun 2 19:35:06 2016
#
# Accessible filesystems, by reference, are maintained under ‘/dev/disk‘
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/vg_centos01-lv_root / ext4 defaults 1 1
UUID=3bb70b22-a906-43ea-97d1-ca28485afec7 /boot ext4 defaults 1 2
/dev/mapper/vg_centos01-lv_home /home ext4 defaults 1 2
/dev/mapper/vg_centos01-lv_swap swap swap defaults 0 0
tmpfs /dev/shm tmpfs defaults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
sysfs /sys sysfs defaults 0 0
proc /proc proc defaults 0 0
16 /etc/fstab
[root@Centos01 ~]#
在linux系统中,环境变量的全局配置文件为/etc/profile,在此文件中定义的变量作用域所有用户。除此之外,每个用户还有自己的独立配置文件(./bash_profile)。若要长期变更或设置某个环境变量,应在上述文件中进行设置。例如,执行以下操作可以将记录的历史命令条数改为200条,默认为1000条,只针对root用户
[root@Centos01 ~]# vi /root/.bash_profile
export HISTSIZE=200
上述修改只有当root用户下次登录时才会生效,若希望立即生效,应手动修改环境变量或者加载配置文件执行。
[root@Centos01 ~]# source /root/.bash_profile
位置变量
为了在使用shell脚本程序时,方便通过命令行为程序提供操作参数,bash引入了位置变量的概念。当执行命令行操作时,第一个字段表示命令名或脚本程序名,其余的字符串参数按照从左到右的顺序依次赋值给位置变量。
位置变量也成为位置参数,使用$1,$2,$3,$4.....表示,例如当执行命令行“ls -ls /boot/”时,其中第一个位置变量为“-lh”以$1表示,第二个位置变量为/boot/ ,使用$2表示,命令或脚本本身的名称使用$0表示。虽然$0与位置变量的格式,但是$0属于预定义变量而不是位置变量。
为了说明位置变量的作用,下面编写一个加法运算的脚本adder2num.sh,用来计算两个整数的合,需要计算的两个整数在执行脚本时以位置变量的形式提供。
[root@Centos01 ~]# vi adder2num.sh
#!/bin/bash
sum=`expr $1 + $2`
echo "$1 + $2 = $sum"
预定义变量是有bash程序预先定义好的一类特殊变量,用户只能使用预定义变量,而不能创建新的预定义变量,也不能直接为预定义变量赋值。预定义变量使用$符号和另一个符号组合表示,较常用的预定义变量的含义如下:
$#:表示命令行中位置参数的个数
$*: 表示所有位置参数的内容
$?: 表示前一条命令执行后的返回状态,返回值为0表示执行正确,返回任何非0值均表示执行出现异常。
$0: 表示当前执行的脚本或程序的名称
GNU的date提供+%s(小写s), 能打印出自1970-01-01 00:00:00到当前时间的秒数.
编写一个备份操作的脚本,用来打包命令行指定的多个文件或目录,并输出相关信息,其中,新建的压缩包文件名称中嵌入秒数。
#!/bin/bash
tarfile=beifen-`date +%s`.tgz
tar zcf $tarfile $* &> /dev/null
echo "已执行 $0 脚本"
echo "共完成 $# 个对象的备份"
echo "具体内容包括: $* "
执行结果是:
[root@Centos01 ~]# ./mybak.sh /etc/passwd /etc/shadow
已执行 ./mybak.sh 脚本
共完成 2 个对象的备份
具体内容包括: /etc/passwd /etc/shadow
shell条件测试
如果一个表达式自身不足以做条件测试的话,可以使用 test [测试表达式] 或者 [ 测试表达式 ]
I/O重定向
标准输出重定向
> :覆盖重定向,目标文件中的原有内容会被消除
>> :追加重定向,新内容会追加至目标文件尾部
set -C :禁止将内容覆盖输出到已有的文件中 <只在当前shell中有效>
若要强制覆盖可以使用 >| 例如 cat /etc/fstab >| /tmp/aa.txt
set +C:关闭以上功能
[root@Centos01 ~]# ls /var > /tmp/etc.out
[root@Centos01 ~]# ls /var/log/ >> /tmp/etc.out
标准错误重定向
[root@Centos01 ~]# cat /etc/issuee 2> /tmp/issue.txt
[root@Centos01 ~]# cat /tmp/issue.txt
cat: /etc/issuee: No such file or directory
[root@Centos01 ~]# cat /etc/issue 2> /tmp/issue.txt
CentOS release 6.5 (Final)
Kernel \r on an \m
[root@Centos01 ~]# cat /tmp/issue.txt 发现文件是空的,因为没有错误输出,所以2>只能重定向错误输出
2> :覆盖从定向错误输出
2>> :追加重定向错误输出
将标准输出和错误输出各自定向到不同位置:
[root@Centos01 ~]# tail -100 /etc/rc.d/rc.sysinit > /tmp/sysinit.out 2> /tmp/sysinit.err
[root@Centos01 ~]# cat /tmp/sysinit.err 这个文件是空的
[root@Centos01 ~]# cat /tmp/sysinit.out 这个文件是标准输出
[root@Centos01 ~]# tail -100 /etc/rc.d/rc.sysinidddt > /tmp/sysinit.out 2> /tmp/sysinit.err
[root@Centos01 ~]# cat /tmp/sysinit.err
tail: cannot open `/etc/rc.d/rc.sysinidddt‘ for reading: No such file or directory
可以合并标准输出和错误输出为同一个数据流进行重定向
&> 覆盖重定向
&>> 追加重定向
[root@Centos01 ~]# echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
You have new mail in /var/spool/mail/root
[root@Centos01 ~]# echo $PATH &> /tmp/path.out
[root@Centos01 ~]# cat /tmp/path.out
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@Centos01 ~]#
[root@Centos01 ~]# echoooo $PATH &> /tmp/path.out
[root@Centos01 ~]# cat /tmp/path.out
-bash: echoooo: command not found
特殊写法:将标准输出和错误输出写到同一个文件可以使用2>&1
[root@Centos01 ~]# echo "$PATH" > /tmp/path.out 2>&1
[root@Centos01 ~]# echoddd "$PATH" >> /tmp/path.out 2>&1
[root@Centos01 ~]# cat /tmp/path.out
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
-bash: echoddd: command not found
输入重定向:将原本需要有键盘输入的数据,同过文件来读入。 <
[root@Centos01 ~]# useradd jerry
[root@Centos01 ~]# vi pass.txt
[root@Centos01 ~]# passwd --stdin jerry < pass.txt
[root@Centos01 ~]# cat aa.txt
test stdin
使用cat命令在键盘上输入一些数据,然后写入catfile文件中
[root@Centos01 ~]# cat > catfile
testing
cat file tset
输入crtl+d结束
此时就会有catfile文件产生,而且该文件的内容就是刚刚输入的内容,那么是否可以使用其他文件来替换键盘输入呢
[root@Centos01 ~]# cat > catfile < aa.txt
[root@Centos01 ~]# cat catfile
test stdin
[root@Centos01 ~]#
我们可以用cat直接将输入的消息输出到catfile中,并且当输入EOF时,该次输入就结束,可以这样做
[root@Centos01 ~]# cat > catfile <<EOF
> this is a test testing
> ok now stop
> EOF
You have new mail in /var/spool/mail/root
[root@Centos01 ~]# cat catfile
this is a test testing
ok now stop
[root@Centos01 ~]#
[root@Centos01 ~]# tr abc ABC < /etc/fstab
#
# /etC/fstAB
# CreAted By AnACondA on Thu Jun 2 19:35:06 2016
#
# ACCessiBle filesystems, By referenCe, Are mAintAined under ‘/dev/disk‘
# See mAn pAges fstAB(5), findfs(8), mount(8) And/or Blkid(8) for more info
#
/dev/mApper/vg_Centos01-lv_root / ext4 defAults 1 1
UUID=3BB70B22-A906-43eA-97d1-CA28485AfeC7 /Boot ext4 defAults 1 2
/dev/mApper/vg_Centos01-lv_home /home ext4 defAults 1 2
/dev/mApper/vg_Centos01-lv_swAp swAp swAp defAults 0 0
tmpfs /dev/shm tmpfs defAults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
sysfs /sys sysfs defAults 0 0
proC /proC proC defAults 0 0
[root@Centos01 ~]# tr ‘a-z‘ ‘A-Z‘ < /etc/fstab
#
# /ETC/FSTAB
# CREATED BY ANACONDA ON THU JUN 2 19:35:06 2016
#
# ACCESSIBLE FILESYSTEMS, BY REFERENCE, ARE MAINTAINED UNDER ‘/DEV/DISK‘
# SEE MAN PAGES FSTAB(5), FINDFS(8), MOUNT(8) AND/OR BLKID(8) FOR MORE INFO
#
/DEV/MAPPER/VG_CENTOS01-LV_ROOT / EXT4 DEFAULTS 1 1
UUID=3BB70B22-A906-43EA-97D1-CA28485AFEC7 /BOOT EXT4 DEFAULTS 1 2
/DEV/MAPPER/VG_CENTOS01-LV_HOME /HOME EXT4 DEFAULTS 1 2
/DEV/MAPPER/VG_CENTOS01-LV_SWAP SWAP SWAP DEFAULTS 0 0
TMPFS /DEV/SHM TMPFS DEFAULTS 0 0
DEVPTS /DEV/PTS DEVPTS GID=5,MODE=620 0 0
SYSFS /SYS SYSFS DEFAULTS 0 0
PROC /PROC PROC DEFAULTS 0 0
[root@Centos01 ~]# tr -d abc
alpha
lph
amnbak
mnk
此处生成文档
[root@Centos01 ~]# cat << EOF
> how are you?
> how old are you?
> EOF
how are you?
how old are you?
[root@Centos01 ~]# cat >> /tmp/test.out << EOF
> how are you?
> how old are you?
> EOF
[root@Centos01 ~]# cat /tmp/test.out
how are you?
how old are you?
利用<<右侧的控制符,可以终止一次输入,而不必输入ctrl+d来结束。这对程序的编写很有帮助。那么为什么要使用命令输出重定向呢?如果没有接触过脚本,这个问题一定会很难理解,下面是一些命令输出重定向的场合:
1. 当屏幕输出的信息很重要,而且我们需要将它存下来的时候
2. 后台执行的程序,不希望它干扰屏幕正常的输出结果
3. 一些系统的例行命令的执行结果,希望它可以存下来
4. 一些执行命令,我们已经知道它可能的错误消息,所以想以2>/dev/null将它丢掉
5. 错误消息与正确消息需要分别输出
大家都知道每个命令都有输入和输出,我们可不可以把前一个命令的输出当做后面命令的输入,大家都知道一个命令的输入可以从一个文件中读取,能不能从前一个命令中读取呢,这种机制就叫做管道,管道即把第一个命令的输出送给第二个命令当输入
[root@Centos01 ~]# echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@Centos01 ~]# echo $PATH | tr ‘a-z‘ ‘A-Z‘
/USR/LIB64/QT-3.3/BIN:/USR/LOCAL/SBIN:/USR/LOCAL/BIN:/SBIN:/BIN:/USR/SBIN:/USR/BIN:/ROOT/BIN
[root@Centos01 ~]# echo $PATH | tr ‘a-z‘ ‘A-Z‘| tr -d ‘U‘
/SR/LIB64/QT-3.3/BIN:/SR/LOCAL/SBIN:/SR/LOCAL/BIN:/SBIN:/BIN:/SR/SBIN:/SR/BIN:/ROOT/BINYou have
[root@Centos01 ~]# ls -al /etc | less 使用ls命令输出后的内容,就能够被less读取,并且利用less的功能,我们就能够前后翻动相关的信息,很方便
将登陆到系统上的用户信息中的后3行的信息转换为大写字母后保存至/tmp/who.out文件中
[root@Centos01 ~]# who | tail -n 3 | tr ‘a-z‘ ‘A-Z‘ > /tmp/who.out
将/etc/passwd/文件中的前5行内容转换为大写后保存至/tmp/passwd.out文件中
[root@Centos01 ~]# cat /etc/passwd | head -n 5 | tr ‘a-z‘ ‘A-Z‘ > /tmp/passwd.out
[root@Centos01 ~]# cat /tmp/passwd.out
ROOT:X:0:0:ROOT:/ROOT:/BIN/BASH
BIN:X:1:1:BIN:/BIN:/SBIN/NOLOGIN
DAEMON:X:2:2:DAEMON:/SBIN:/SBIN/NOLOGIN
ADM:X:3:4:ADM:/VAR/ADM:/SBIN/NOLOGIN
LP:X:4:7:LP:/VAR/SPOOL/LPD:/SBIN/NOLOGIN
脚本示例
1. 创建一个组newgroup,id号为4000
2. 创建一个用户test,id号为3001,附加组为newgroup
3. 创建目录/tmp/hellod
4. 复制/etc/fstab至上面的目录中
5. 改变目录及内部文件的属主和属组为test
6. 让目录及内部文件的其他用户没有任何权限
[root@Centos01 ~]# cat aa.sh
#!/bin/bash
groupadd -g 4000 newgroup
useradd -u 3001 -G newgroup test
mkdir /tmp/hellod
cp /etc/fstab /tmp/hellod
chown -R test:test /tmp/hellod
chmod -R o= /tmp/hellod
或者
#!/bin/bash
myGroup="newgroup"
myUser="test"
myDir="/tmp/hellod"
myID=3001
groupadd -g 4000 $myGroup
useradd -u $myID -G $myGroup $myUser
mkdir $myDir
cp /etc/fstab $myDir
chown -R $myUser:$myUser $myUser
chmod -R o= $myDir
变量的命名要求
只能使用数字、字母、下划线组成
不能以数字开头
不能使用程序中关键字
要做到见名之意
awk可以处理后续文件,也可以读取来自前一个命令的标准输出。awk主要是处理“每一行字段内的数据”,而默认的字段分隔符为空格键或tab键,举例来说,用last可以将登录者的数据取出来,结果如图所示:
若想取出账号与登录者的IP地址,且账号与IP地址之间以tab键隔开,则会变成这样:
[root@Centos01 ~]# last | awk ‘{print $1 "\t" $3}‘
root192.168.1.100
root192.168.1.100
rebootboot
root:0.0
root:0
awk是以行尾处理单位,而以字段为最小的处理单位
awk举例:
[root@Centos01 ~]# ifconfig eth0 | grep "HWaddr"
eth0 Link encap:Ethernet HWaddr 00:0C:29:1A:E3:AA
[root@Centos01 ~]# ifconfig eth0 | grep "HWaddr" | awk ‘{print $5}‘
00:0C:29:1A:E3:AA
[root@Centos01 ~]# hwaddr=$(ifconfig eth0 | grep "HWaddr" | awk ‘{print $5}‘)
[root@Centos01 ~]# echo hwaddr
hwaddr
[root@Centos01 ~]# echo $hwaddr
00:0C:29:1A:E3:AA
[root@Centos01 ~]# grep "bash$" /etc/passwd
root:x:0:0:root:/root:/bin/bash
mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash
cacti:x:500:500::/home/cacti:/bin/bash
[root@Centos01 ~]# grep "bash$" /etc/passwd | awk -F: ‘{print $1,$7}‘
root /bin/bash
mysql /bin/bash
cacti /bin/bash
[root@Centos01 ~]#
特殊变量:
$0;脚本名称自身
$?: 上一条命令的执行状态,状态用数字来表示:0-255 0表示成功,1-255表示失败
命令执行成功了,成功的标记叫状态返回值,而正常的命令执行后的结果叫返回值。
环境变量:用来定义bash的工作特性,用于保存当前会话的属性信息。
显示所有环境变量:export,env,printenv
env是environment(环境)的缩写。
执行env命令即可获得当前shell环境下所有环境变量及其内容
[root@Centos6 ~]# env
定义环境变量:
export Var_Name="Value"
例如:
[root@Centos6 ~]# echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@Centos6 ~]# mkdir /root/sbin
[root@Centos6 ~]# export PATH=/root/sbin/
[root@Centos6 ~]# cat /etc/fstab
-bash: cat: command not found
重新登录该终端就又可以访问了
[root@Centos6 ~]# cat /etc/fstab
#
# /etc/fstab
# Created by anaconda on Thu Jun 2 21:38:10 2016
#
# Accessible filesystems, by reference, are maintained under ‘/dev/disk‘
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/vg_centos6-lv_root / ext4 defaults 1 1
UUID=f8f486f4-8f58-4619-92f9-0fdde943166c /boot ext4 defaults 1 2
/dev/mapper/vg_centos6-lv_home /home ext4 defaults 1 2
/dev/mapper/vg_centos6-lv_swap swap swap defaults 0 0
tmpfs /dev/shm tmpfs defaults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
sysfs /sys sysfs defaults 0 0
proc /proc proc defaults 0 0
不重新登录该终端也可以,[root@Centos6 ~]# export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
若要在PATH环境变量中增加/root/sbin
[root@Centos6 ~]# echo $PATH
/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
[root@Centos6 ~]# export PATH=$PATH:/root/sbin
[root@Centos6 ~]# echo $PATH
/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/root/sbin
[root@Centos6 ~]# export PATH=/root/sbin:$PATH
[root@Centos6 ~]# echo $PATH
/root/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/root/sbin
改过来
[root@Centos6 ~]# export PATH=$PATH:/root/sbin
bash的配置文件:持久保存用户配置
profile:为交互式登录用户提供配置
/etc/profile --->全局的,对所有用户有效
/etc/profile.d/*.sh --->全局的,对所有用户有效
每个用户家目录下的~/.bash_profile --->个人的,仅对当前用户有效,
profile的功能:
设定环境变量
运行命令或脚本时
[root@Centos6 ~]# cat .bash_profile 由于只配置了root用户的.bash_profile,只对root用户生效。
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin
export PATH
echo "welcome here...." --->添加此行
重新登录的时候就会显示
Last login: Tue Jun 14 16:21:44 2016 from 192.168.1.100
welcome here....
bashrc:为非交互式登录用户提供配置
.bashrc功能:
可以设定本地变量,让脚本运行时有变量可以使用
可以定义命令别名
[root@Centos6 ~]# cat .bashrc
# .bashrc
# User specific aliases and functions
alias rm=‘rm -i‘
alias cp=‘cp -i‘
alias mv=‘mv -i‘
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
登录类型:
交互式登录:
直接通过终端输入用户名密码登录系统
其实su - 用户名 或者 su -l 用户名方式登录也算是交互式登录
对于交互式用户来讲是读取配置文件的顺序
首先会读取/etc/profile,/etc/profile.d/*.sh,接着读~/.bash_profile,~/.bashrc,在读/etc/bashrc
/etc/profile--->/etc/profile.d/*.sh--->~/.bash_profile--->~/.bashrc--->/etc/bashrc 如有冲突,最后被source的生效
非交互式:
su 用户名
图形界面的终端也是非交互式登录
执行脚本的时候需要使用解释器来解释执行,解释器在解释脚本时会读取配置文件先设置解释环境的
/etc/bashrc:全局
~/.bashrc:个人配置
对于非交互式用户来讲是读取配置文件的顺序
~/.bashrc---> /etc/bashrc--->/etc/profile.d/*.sh
通知shell重读配置文件的命令:source .bashrc或者 . .bashrc
bash的编程
程序有3中执行流程:
1. 顺序执行:如果有很多命令的时候,自上而下逐条被执行,
2. 选择执行: 选择执行肯定会有n个分支,事先有个条件判断,符合条件的分支将被执行,不符合分支的条件将不被执行
3. 循环执行:对于计算机而言拉磨式的执行。即对同一段代码反复执行有限次,所以必须要有退出条件,否则会进入无限循环
若想实现以上流程的定义需要用到所谓的编程控制语句,此前声明变量,为变量赋值的我们称之为赋值语句
所以一个程序代码是由语句和表达式组成的。为了实现定义以上的流程就会用到控制语句
控制语句:
bash的循环控制语句:for while until
for 循环是一种事先就知道循环次数的,遍历指定列表的方式来实现的循环。
for 变量名 in 列表; do
语句1
语句2
done
for 语句中变量名是用来变量赋值而非引用变量,不能使用$,切记
使用for循环添加三个用户
分析:使用useradd添加用户,执行3遍,这三遍当中如果那个用户,每一遍都使用同一个变量来引用,而每一遍执行的时候都把变量的值改一下就可以实现了
for usreName in shuguang liming huanghun;do
useradd $userName
done
当程序执行这段代码的时候,首先会把shuguang的这个字符串赋值给userName这个变量,而后执行useradd $userName这条语句,执行完就done结束了,然后进入下一次循环,将liming这个字符串赋值给userName这个变量,而后执行useradd $userName这个语句,执行完就done结束了,然后进入下一次循环,直到遍历完整个列表。所以列表中存储的元素的个数决定循环的次数。
[root@Centos6 ~]# cat autouseradd.sh
#!/bin/bash
for userName in shuguang liming huanghun;do
useradd $userName
done
检测脚本是否有语法错误
[root@Centos6 ~]# bash -n autouseradd.sh
执行脚本
[root@Centos6 ~]# bash autouseradd.sh
验证三个用户是否添加成功
[root@Centos6 ~]# tail -3 /etc/passwd
shuguang:x:500:500::/home/shuguang:/bin/bash
liming:x:501:501::/home/liming:/bin/bash
huanghun:x:502:502::/home/huanghun:/bin/bash
使用for循环添加10个用户,分别为user101-user110
分析:for循环的列表中有10个用户,写起来也很繁琐
列表生成的方法:只要能够实现在命令行中展开的功能都可以生成列表
生成数字序列:
可以使用花括号 {start..end} {1..10}
可以使用seq start end
[root@Centos6 ~]# seq 1 10
1
2
3
4
5
6
7
8
9
10
[root@Centos6 ~]#
很显然seq命令既然执行后生成序列,我们做个命令的引用就可以生成列表
[root@Centos6 ~]# seq 1 2 10 其中2为步长
1
3
5
7
9
[root@Centos6 ~]# for userName in $(seq 101 110);do echo $userName;done
101
102
103
104
105
106
107
108
109
110
[root@Centos6 ~]# for userName in $(seq 101 110);do echo user$userName;done
user101
user102
user103
user104
user105
user106
user107
user108
user109
user110
直接把echo换成useradd就循环添加10个user101-user110的用户了
[root@Centos6 ~]# for userName in $(seq 101 110);do useradd user$userName;done
[root@Centos6 ~]# tail -10 /etc/passwd
user101:x:503:503::/home/user101:/bin/bash
user102:x:504:504::/home/user102:/bin/bash
user103:x:505:505::/home/user103:/bin/bash
user104:x:506:506::/home/user104:/bin/bash
user105:x:507:507::/home/user105:/bin/bash
user106:x:508:508::/home/user106:/bin/bash
user107:x:509:509::/home/user107:/bin/bash
user108:x:510:510::/home/user108:/bin/bash
user109:x:511:511::/home/user109:/bin/bash
user110:x:512:512::/home/user110:/bin/bash
或者
[root@Centos6 ~]# cat useradd.sh
#!/bin/bash
for userName in `seq 101 110`;do
useradd user$userName
echo "Add user$userName successfully."
done
文本处理类命令:wc
[root@Centos6 ~]# wc /etc/issue
3 9 47 /etc/issue 3行,9个单词,47个字节
wc [option] [file]...
-l:统计行数
-c:统计字节数
-w:统计单词数
写一个脚本,用for循环实现
1.显示/etc/init.d/functions,/etc/rc.d/rc.sysinit和/etc/fstab各有多上行
#!/bin/bash
for wcline in /etc/init.d/functions /etc/rc.d/rc.sysinit /etc/fstab;do
echo "$wcline的行数为:" `cat $wcline | wc -l`
done
或者
[root@Centos6 ~]# cat wcline.sh
#!/bin/bash
for wcline in /etc/init.d/functions /etc/rc.d/rc.sysinit /etc/fstab;do
echo "$wcline: `wc -l $wcline | cut -d‘ ‘ -f1` lines;"
done
或者
[root@Centos6 ~]# cat wcline.sh
#!/bin/bash
for wcline in /etc/init.d/functions /etc/rc.d/rc.sysinit /etc/fstab;do
lineCount=`wc -l $wcline | cut -d‘ ‘ -f1`
echo "$wcline: $lineCount lines;"
done
2.将上题中三个文件复制到/tmp目录中,分别将每个文件的最近一次修改时间改为2016年3月15日13点27分
for fileName in /etc/init.d/functions /etc/rc.d/rc.sysinit /etc/fstab;do
cp - $fileName /tmp
touch -m -t 201603151327 /tmp/`basename $fileName`
done
[root@Centos6 tmp]# ll functions rc.sysinit fstab
-rw-r--r-- 1 root root 866 Mar 15 13:27 fstab
-rw-r--r-- 1 root root 18586 Mar 15 13:27 functions
-rwxr-xr-x 1 root root 19688 Mar 15 13:27 rc.sysinit
3.显示/etc/passwd中第3,7,11个用户的用户名和用户id
[root@Centos6 tmp]# cat uid.sh
#!/bin/bash
for lineNo in 3 7 11;do
head -n $lineNo /etc/passwd | tail -1 | cut -d: -f1,3
done
[root@Centos6 tmp]# bash uid.sh
daemon:2
shutdown:6
operator:11
4.用file命令显示/var/log目录下的每个文件的内容类型
[root@Centos6 ~]# cat file.sh
#!/bin/bash
dirName=/var/log
for fileName in $dirName/*;do
file $fileName
done
执行脚本,验证结果
[root@Centos6 ~]# bash file.sh
/var/log/anaconda.ifcfg.log: ASCII text
/var/log/anaconda.log: ASCII English text
/var/log/anaconda.program.log: ASCII English text, with very long lines, with overstriking
/var/log/anaconda.storage.log: ASCII C++ program text, with very long lines
/var/log/anaconda.syslog: ASCII English text, with very long lines
/var/log/anaconda.xlog: ASCII English text
/var/log/anaconda.yum.log: ASCII text
/var/log/audit: directory
/var/log/boot.log: ASCII English text, with CRLF, CR line terminators, with escape sequences
/var/log/btmp: empty
/var/log/ConsoleKit: directory
for总结:
通过使用一个变量去遍历给定列表中的每个元素,在每次变量赋值时执行一次循环体,直至赋值完成所有元素退出循环
生成列表的总结:
1. 直接给出列表
2. 使用文件名通配的方式生成序列
3. 可以使用{}或seq命令生成数字序列
4. 使用命令生成 cat、ls
bash中的算数运算
在bash中无需事先声明变量,bash是一种弱类型的语言,无需区分变量类型,既然不用区分类型,变量中数据存储的默认格式是字符串,所以字符串是不能进行数值运算的,
[root@Centos6 ~]# num1=1
[root@Centos6 ~]# num2=3
[root@Centos6 ~]# $num1+$num2
-bash: 1+3: command not found
[root@Centos6 ~]# sum=$num1+$num2
[root@Centos6 ~]# echo $sum
1+3
[root@Centos6 ~]#
若想进行数值运算:
declare
-i: 整形
-x: 环境变量
let varName=算数表达式
varName=$[算数表达式]
varName=$((算数表达式))
varName=`expr $num1 + $num2`
[root@Centos6 ~]# aa=$[$num1*$num2]
[root@Centos6 ~]# echo $aa
3
[root@Centos6 ~]# let sum=$num1+$num2
[root@Centos6 ~]# echo $sum
4
[root@Centos6 ~]# aa=$(($num1*$num2))
[root@Centos6 ~]# echo $aa
3
[root@Centos6 ~]# expr $num1 + $num2
4
操作符:+ - * / %
bash不能进行浮点计算
[root@Centos6 ~]# let er=$num1/$num2
[root@Centos6 ~]# echo $er
0
自加运算
total=$[$total+1]
let total+=1
let total++
[root@Centos6 ~]# a=40
[root@Centos6 ~]# a=$[$a+2]
[root@Centos6 ~]# echo $a
42
[root@Centos6 ~]# a=40
[root@Centos6 ~]# echo $a
40
[root@Centos6 ~]# let a+=2
[root@Centos6 ~]# echo $a
42
[root@Centos6 ~]#
练习
1. 计算100以内所有正整数之和
每次都是sum自身的基础上加i
[root@Centos6 ~]# cat sum.sh
#!/bin/bash
declare -i sum=0
for i in {1..100};do
let sum=$sum+$i
done
echo "the sum is: $sum"
执行脚本
[root@Centos6 ~]# bash sum.sh
the sum is: 5050
可以单步执行时加-x参数
[root@Centos6 ~]# bash -x sum.sh
+ declare -i sum=0
+ for i in ‘{1..100}‘
+ let sum=0+1
+ for i in ‘{1..100}‘
+ let sum=1+2
+ for i in ‘{1..100}‘
+ let sum=3+3
2. 分别计算100以内所有偶数之和和奇数之和
[root@Centos6 ~]# cat oddsum.sh
#!/bin/bash
declare -i oddsum=0,evensum=0
for i in `seq 2 2 100`;do
oddsum=$[$oddsum+$i]
done
for j in `seq 1 2 100`;do
evensum=$[$evensum+$j]
done
echo "the evensum is $evensum,the odd sum is: $oddsum"
3. 计算当前系统所有用户的ID之和
[root@Centos6 ~]# cat useridsum.sh
#!/bin/bash
declare -i uidSum=0
for i in `cut -d: -f3 /etc/passwd`; do
uidSum=$[$uidSum+$i]
done
echo "the UIDSum is: $uidSum"
执行脚本结果如下:
[root@Centos6 ~]# bash useridsum.sh
the UIDSum is: 70943
4. 计算/etc/init.d/functions /etc/rc.d/rc.sysinit /etc/issue三个文件的字符数之和
[root@Centos6 ~]# cat bytecount.sh
#!/bin/bash
declare -i bytesCount=0
for file in /etc/init.d/functions /etc/rc.d/rc.sysinit /etc/issue; do
let bytesCount=$bytesCount+`wc -c $file | cut -d‘ ‘ -f1`
done
echo $bytesCount
执行脚本的结果
[root@Centos6 ~]# bash bytecount.sh
38321
5. 新建用户user1-user10,并计算用户的id之和
[root@Centos6 ~]# cat userid.sh
#!/bin/bash
declare -i uidSum=0
for i in `seq 1 10`; do
useradd user$i
let uidSum=$uidSum+`id -u user$i`
done
echo $uidSum
执行脚本
[root@Centos6 ~]# bash userid.sh
5195
位置参数:
$0:脚本自身
$1:脚本的第一个参数
$2:
[root@Centos6 ~]# cat pos.sh
#!/bin/bash
echo $1
echo $2
echo $0
[root@Centos6 ~]# chmod +x pos.sh
[root@Centos6 ~]# ./pos.sh 5 9
5
9
./pos.sh
[root@Centos6 ~]# cat pos.sh
#!/bin/bash
echo "the sum is: $[$1+$2]."
[root@Centos6 ~]# ./pos.sh 10 20
the sum is: 30.
$# 引用位置参数的个数
[root@Centos6 ~]# cat pos.sh
#!/bin/bash
echo "the sum is: $[$1+$2]."
echo "the mul is: $[$1*$2]."
echo $#
[root@Centos6 ~]# ./pos.sh 10 20 3 8
the sum is: 30.
the mul is: 200.
4
$* 引用所有的位置参数
[root@Centos6 ~]# cat ./pos.sh
#!/bin/bash
echo "the sum is: $[$1+$2]."
echo "the mul is: $[$1*$2]."
echo $#
echo $*
[root@Centos6 ~]# ./pos.sh 4 5 7 7
the sum is: 9.
the mul is: 20.
4
4 5 7 7
交互式脚本
给变量默认值
varName=${varName:-value}
如果varName不空,则返回varName的值,否则返回value的值
如果varName不空,则其值不变;否则,varName会使用value作为其值
[root@Centos6 ~]# echo $a
42
[root@Centos6 ~]# a=${a:-45}
[root@Centos6 ~]# echo $a
42
[root@Centos6 ~]# unset a
[root@Centos6 ~]# a=${a:-45}
[root@Centos6 ~]# echo $a
45
举例:
[root@Centos6 ~]# cat read1.sh
#!/bin/bash
read -t 5 -p "Enter a number:" num1
num1=${num1:-0}
echo $num1
[root@Centos6 ~]# bash read1.sh
Enter a number:6
6
过5秒钟不输入任何数字,num1的值为0
[root@Centos6 ~]# bash read1.sh
Enter a number:0
[root@Centos6 ~]# read a b
50 100
[root@Centos6 ~]# echo $a
50
[root@Centos6 ~]# echo $b
100
[root@Centos6 ~]# read c d
30
[root@Centos6 ~]# echo $c
30
[root@Centos6 ~]# echo $d
[root@Centos6 ~]#
[root@Centos6 ~]# read e f
2 4 5 6 7
[root@Centos6 ~]# echo $e
2
[root@Centos6 ~]# echo $f
4 5 6 7
[root@Centos6 ~]#
练习:
1. 通过键盘给定一个文件路径,来判断文件内容类型:
[root@Centos6 ~]# cat yyy.sh
#!/bin/bash
read -p "Enter a file path: " filename
file $filename
[root@Centos6 ~]# bash yyy.sh
Enter a file path: /etc/fstab
/etc/fstab: ASCII text
bash编程之条件判断
条件判断的目的是:判定后续操作的前提条件是否满足
条件判断的常用类型:
整数测试:
字符测试:
文件测试:
布尔值:
真,假
逻辑运算:
与运算:
真 && 真 = 真
真 && 假 = 假
假 && 真 = 假
假 && 假 = 假
或运算
真 || 真 = 真
真 || 假 = 真
假 || 真 = 真
假 || 假 = 假
非运算
!真 = 假
!假 = 真
bash如何做测试
1 test 表达式
2 [ 表达式 ] 表达式两端必须要有空格
在什么样的场景中使用bash条件测试
bash中条件判断使用if
单分支
if 条件; then
分支1;
fi
双分支
if 条件; then
分支1;
else
分支2;
fi
多分支
if 条件1;then
分支1;
elif 条件2; then
分支2;
elif 条件3; then
分支3;
...
else
分支n;
fi
只要命令用作条件,就表示引用的是其状态结果(即执行成功与否),而非命令的输出结果,因此,不能使用命令替换符(``,$()),只有将命令执行的结果保存到变量当中,或引用命令执行结果时需要使用反撇号$()
练习:
1. 让用户指定一个文件,判定如果文件有空白行,就显示空白行数
[root@Centos6 ~]# cat yin.sh
#!/bin/bash
#
read -p "Enter a file path: " filename
if grep "^$" $filename &> /dev/null; then
linesCount=`grep "^$" $filename | wc -l`
echo "$filename has $linesCount space lines."
fi
执行结果
[root@Centos6 ~]# bash yin.sh
Enter a file path: /etc/rc.d/rc.sysinit
/etc/rc.d/rc.sysinit has 96 space lines.
如果输入/etc/passwd,由于没有空格,分支语句将不会被执行。
[root@Centos6 ~]# bash yin.sh
Enter a file path: /etc/passwd
[root@Centos6 ~]#
2. 让用户指定一个文件,判定如果文件有空白行,就显示空白行数,如果没有空白行,就显示没有空白行
#!/bin/bash
#
read -p "Enter a file path: " filename
if grep "^$" $filename &> /dev/null; then
linesCount=`grep "^$" $filename | wc -l`
echo "$filename has $linesCount space lines."
else
echo "$filename hava no space line."
fi
执行结果
[root@Centos6 ~]# bash yin.sh
Enter a file path: /etc/passwd
/etc/passwd hava no space line.
3. bash整数测试
二元测试
-gt:大于 [ $num1 -gt $num2 ]
-lt:小于
-ge:大于等于
-le:小于等于
-ne:不等于
-eq:等于
练习:
1. 用户通过命令行输入两个数字,比较大小,整数是通过命令行参数传递而来的
[root@Centos6 ~]# cat euu.sh
#!/bin/bash
#
if [ $1 -gt $2 ]; then
echo "the max num is $1."
else
echo "the max num is $2."
fi
[root@Centos6 ~]# chmod +x euu.sh
[root@Centos6 ~]# ./euu.sh 67 98
the max num is 98.
[root@Centos6 ~]# ./euu.sh 12 30
the max num is 30.
脚本自定义退出:
[root@Centos6 ~]# cat exit.sh
#!/bin/bash
echo "hello"
exit 6
echo "world"
执行脚本
[root@Centos6 ~]# bash exit.sh
hello
[root@Centos6 ~]# echo $?
6
如果注释exit 6
[root@Centos6 ~]# cat exit.sh
#!/bin/bash
echo "hello"
#exit 6
echo "world"
执行脚本
[root@Centos6 ~]# bash exit.sh
hello
world
[root@Centos6 ~]# echo $?
0
修改脚本为
[root@Centos6 ~]# cat exit.sh
#!/bin/bash
ls /etcccc
echo "hello"
#exit 6
echo "world"
执行脚本
[root@Centos6 ~]# bash exit.sh
ls: cannot access /etcccc: No such file or directory
hello
world
[root@Centos6 ~]# echo $?
0
判断两个数字的大小,如果用户只输入1个数字,没有办法判断,所以还可以补充一下上面的脚本
[root@Centos6 ~]# cat euu.sh
#!/bin/bash
#
if [ $# -lt 2 ]; then
echo "stupid..."
echo "`basename $0` argu1 argu2"
exit 4
fi
if [ $1 -gt $2 ]; then
echo "the max num is $1."
else
echo "the max num is $2."
fi
执行脚本的的结果如下
[root@Centos6 ~]# ./euu.sh 20
stupid...
euu.sh argu1 argu2
[root@Centos6 ~]# ./euu.sh 20 10
the max num is 20.
练习:
1. 写一个脚本,实现如下功能
让用户通过键盘输入一个用户名,如果用户存在,就显示其用户名和uid否则就显示用户名不存在
[root@Centos6 ~]# cat aa2.sh
#!/bin/bash
read -t 10 -p "Enter a username:" username
# username-${username:-root}
if id $username &> /dev/null; then
userid=`id -u $username`
echo "$username: $userid"
else
echo "$username not exist."
fi
执行脚本
[root@Centos6 ~]# bash aa2.sh
Enter a username:huarong
huarong not exist.
[root@Centos6 ~]# bash aa2.sh
Enter a username:user1
user1: 515
2. 让用户通过键盘输入一个用户名,如果用户不存在就退出,如果用户的uid大于等于500,就说明他是普通用户,否则就说明是管理员或系统用户
[root@Centos6 ~]# cat aa3.sh
#!/bin/bash
read -p "Enter a username:" username
if ! id $username &> /dev/null; then
echo "$usernam not exist."
exit 6
fi
userid=`id -u $username`
if [ $userid -ge 500 ]; then
echo "A common user;"
else
echo "Admin or system user;"
fi
执行脚本
[root@Centos6 ~]# bash aa3.sh
Enter a username:root
Admin or system user;
[root@Centos6 ~]# bash aa3.sh
Enter a username:user1
A common user;
3. 让用户通过键盘输入一个用户名,如果用户不存在就退出,如果其UID等于GID,就说他是一个"good guy",否则就说他是个"bad guy"
[root@Centos6 ~]# cat aa4.sh
#!/bin/bash
read -p "Enter a username:" username
if ! id $username &> /dev/null; then
echo "$usernam not exist."
exit 6
fi
if [ `id -u $username` -eq `id -g $username` ]; then
echo "good guy"
else
echo "bad guy"
fi
执行脚本
4. 判断当前系统上的所有用户是good guy还是bad by
for username in `cut -d: -f1 /etc/passwd`; do
if [ `id -u $username` -eq `id -g $username` ]; then
echo "good guy"
else
echo "bad guy"
fi
done
5. 写一个脚本,实现如下功能:
添加10个用户stu1-stu10,但要先判断用户是否存在,如果存在,就显示其已经存在,否则就添加此用户,,最后显示一共添加了几个用户
[root@Centos6 ~]# cat aa5.sh
#!/bin/bash
declare -i usercount=0
for i in {1..10}; do
if id stu$i &> /dev/null; then
echo "stu$i exists."
else
useradd stu$i && echo "stu$i add finished."
let usercount++
fi
done
echo "add $usercount users;"
6. 求200以内所有3的整数倍的正整数之和
[root@Centos6 ~]# cat sum1.sh
#!/bin/bash
declare -i sum=0
for i in {1..200}; do
if [ $[$i%3] -eq 0 ]; then
let sum+=$i
fi
done
echo "the sum is: $sum."
[root@Centos6 ~]# bash sum1.sh
the sum is: 6633.
组合条件测试,对条件做逻辑运算
与运算的短路操作
与:
条件1 && 条件2
条件1为假,则最终结果一定为假,因此条件2将不被执行
条件1为真,则最终结果取决于后面条件,因此条件2必须被执行
[root@Centos6 ~]# username=root
[root@Centos6 ~]# id $username && echo "$username exist"
uid=0(root) gid=0(root) groups=0(root)
root exist
[root@Centos6 ~]# username=roooot
[root@Centos6 ~]# id $username && echo "$username exist"
id: roooot: No such user
[root@Centos6 ~]#
或:
条件1 || 条件2
条件1为真,则最终结果一定为真,因此条件2将不被执行。
ot@Centos6 ~]# username=root
[root@Centos6 ~]# id $username &> /dev/null || echo "$username not exist"
[root@Centos6 ~]#
条件2为假,则最终结果取决于后面条件,因此条件2必须被执行
[root@Centos6 ~]# username=roooot
[root@Centos6 ~]# id $username &> /dev/null || echo "$username not exist"
roooot not exist
[root@Centos6 ~]# id $username &> /dev/null && echo "$username exist." || echo "$username not exist"
root exist.
[root@Centos6 ~]# username=rootttt
[root@Centos6 ~]# id $username &> /dev/null && echo "$username exist." || echo "$username not exist"
rootttt not exist
非:! 条件
bash编程之字符测试
双目:
>
<
==等于,等值比较
~~:左侧是字符串,右侧是一个模式,判定左侧的字符串能否右侧的模式所匹配,通常只在[[]中使用,模式中可以使用行首,行尾锚定符,但模式不要叫引号
单目:
-n $stringvar:字符串是否不空,不空为真,空则为假
-z $stringvar:字符串是否为空,空则为真,不空则假
stringA="root"
stringB="hello"
[ "stringA" == "stringB" ]
echo $?
1
stringB="root"
双引号不能被省略
[root@centos01 ~]# clear
[root@centos01 ~]# stringA="root"
[root@centos01 ~]# [ -n "$stringA" ]
[root@centos01 ~]# echo $?
0
[root@centos01 ~]#
[root@centos01 ~]# [ -z "$stringA" ]
[root@centos01 ~]# echo $?
1
[root@centos01 ~]# [ -z "$stringB" ]
[root@centos01 ~]# echo $?
0
[root@centos01 ~]# [[ "$stringA"] =~ ot ]]
[root@centos01 ~]# echo $?
0
[root@centos01 ~]# [[ "$stringA"] =~ to ]]
[root@centos01 ~]# echo $?
1
[root@centos01 ~]#
判定某用户的默认shell是以sh结尾的
[root@centos01 ~]# [[ `grep "^$username\>" /etc/passwd | cut -d: -f7` =~ sh$ ]]
[root@centos01 ~]# echo $?
0
判定所有用户是否拥有可登陆shell
[root@centos01 ~]# cat aa1.sh
#!/bin/bash
for username in `cut -d: -f1 /etc/passwd`; do
if [[ `grep "^$username\>" /etc/passwd | cut -d: -f7` =~ sh$ ]]; then
echo "login user: $username"
else
echo "nologin user: $username"
fi
done
bash编程之文件测试
单目测试
-e file:
-a file: 测试文件是否存在
-f file /path/to/file:测试是否为普通文件
-d file /path/to/somefile:测试是否为目录文件
-b file /path/to/somefile:测试文件是否为块设备文件
-c file /path/to/somefile:测试文件是否为字符设备文件
-h file /path/to/somefile:测试文件是否为符号链接文件
-p file /path/to/somefile:测试文件是否为管道文件
-r /path/to/somefile 测试其有效用户是否对此文件有读取权限
-w /path/to/somefile 测试其有效用户是否对此文件有写入权限
-x /path/to/somefile 测试其有效用户是否对此文件有执行权限
双目测试
file1 -nt file2:测试file1是否为file2更 新一些
[root@Centos6 tmp]# filename=/tmp/hellodir
[root@Centos6 tmp]# [ -e $filename ] || mkdir $filename
[root@Centos6 tmp]# ls
让用户交互式输入一个用户名,先判定用户是否存在,不存在,则以7为退出码;
判断用户的shell是否为/bin/bash;如果是,则显示为"bash user",退出码为0,否则显示为not bash user,退出码为1;
[root@Centos6 ~]# cat aa1.sh
#!/bin/bash
#
read -p "Enter a user name: " username
if ! id $username &> /dev/null; then
echo "No such user."
exit 7
fi
usershell=`grep "^$username\>" /etc/passwd | cut -d: -f7`
if [[ "$usershell" == "/bin/bash" ]]; then
echo "bash user."
returnValue=0
else
echo "Not bash usre."
returnValue=1
fi
exit $returnValue
执行脚本
[root@Centos6 ~]# bash aa1.sh
Enter a user name: bin
Not bash usre.
[root@Centos6 ~]# echo $?
1
[root@Centos6 ~]# bash aa1.sh
Enter a user name: binnn
No such user.
[root@Centos6 ~]# echo $?
7
[root@Centos6 ~]# bash aa1.sh
Enter a user name: root
bash user.
编写一下脚本:
显示如下菜单:
cpu) show cpu info;
mem) show memory info;
quit) quit
enter your option:
如果用户选择cpu,则显示文件/proc/cpuinfo的信息
如果用户选择mem,则显示文件/proc/meminfo的信息
如果用户选择quit,则退出,且退出码为5
如果用户键入其他字符,则显示未知选项,请重新执行脚本,退出码为6;
[root@Centos6 ~]# bash aa6.sh
cpu) print cpu information
mem) print memory information
quit) Quit
Enter your option: quit
quit
[root@Centos6 ~]# cat aa6.sh
#!/bin/bash
#
returnValue=0
cat <<EOF
cpu) print cpu information
mem) print memory information
quit) Quit
EOF
read -p "Enter your option: " useroption
useroption=`echo $useroption | tr ‘A-Z‘ ‘a-z‘`
if [[ "$useroption" == "cpu" ]];then
cat /proc/cpuinfo
elif [[ "$useroption" == "mem" ]];then
cat /proc/meminfo
elif [[ "$useroption" == "quit" ]];then
echo "quit"
returnValue=6
else
echo "unkown option"
returnValue=7
fi
exit $returnValue
本文出自 “apache” 博客,请务必保留此出处http://xiaorenwutest.blog.51cto.com/12754924/1913280
原文地址:http://xiaorenwutest.blog.51cto.com/12754924/1913280