Bash介绍: man bash
Bash(GNU Bourne-Again SHell)是许多Linux平台的内定Shell,事实上,还有许多传统UNIX上用的Shell,像tcsh、csh、ash、bsh、ksh等 等,Shell Script大致都类同,当您学会一种Shell以后,其它的Shell会很快就上手,大多数的时候,一个Shell Script通常可以在很多种Shell上使用
BASH的正确缩写:
BASH = GNU Bourne-Again SHell,BASH 是 GNU 组织开发和推广的一个项目。
BASH的作者和产生:
Bourne shell 的作者是 Steven Bourne,它是 UNIX 最初使用的 Shell 并且在每种 UNIX 上都可以使用。
而BASH 与 Bourne shell 完全向后兼容,是Bourne shell的扩展。
shell:外壳
程序:进程
进程:在每个进程看来,当前主机上只存在内核和当前进程;进程是程序的副本,进程是程序的执行实例
bash 内置特性
一命令历史、命令补全
二管道和重定向
三别名
四命令行编辑
五命令行展开
六文件名通配
七变量
八编程
命令行编辑(快捷键)
ctrl+a:光标移动到行首
ctrl+e:光标移动到行尾
ctrl+u:清除光标前至行首的所有内容
ctrl+k:清除光标后至行尾的内容
ctrl+l:清屏
Ctrl+f光标向后移动一个字符
ctrl+b:光标向前移动一个字符
ctrl+h:删除光标前的一个字符
ctrl+d:从当前shell登出(和exit很像) "EOF"(文件结束符)
ctrl+i:就是一个tab键
ctrl+j:新行
ctrl+m:回车
esc b:左移一个单词
esc f:右移一个单词
一 命令历史
Bash可以保存过去曾经执行过的命令列表(即history 命令产生的列表),当前shell进程引用过的命令都会保存在缓冲区中,如果有退出操作时,缓冲区中的命令会在shell退出时将以前运行过的命令保存至文件中(即用户家目录下的.bash_histor)
history 快捷方式:
!#:为命令历史列表中的命令编号,可用执行第#条命令
!!:执行上一命令;
!- #:执行命令历史列表中的倒数第#命令;
!string :执行命令历史列表中的最近一次以string开头的命令;
1
2
3
4
5
|
[root@localhost etc]
# echo "$PATH"
/usr/lib64/qt-3
.3
/bin
:
/usr/local/sbin
:
/usr/local/bin
:
/sbin
:
/bin
:
/usr/sbin
:
/usr/bin
:
/usr/local/axel/bin
:
/usr/local/nginx/sbin
:
/root/bin
:
/usr/local/apache/bin
:
/usr/local/apache/bin
:
/usr/local/axel/bin
:
/usr/local/nginx/sbin
[root@localhost etc]
# !e
echo
"$PATH"
/usr/lib64/qt-3
.3
/bin
:
/usr/local/sbin
:
/usr/local/bin
:
/sbin
:
/bin
:
/usr/sbin
:
/usr/bin
:
/usr/local/axel/bin
:
/usr/local/nginx/sbin
:
/root/bin
:
/usr/local/apache/bin
:
/usr/local/apache/bin
:
/usr/local/axel/bin
:
/usr/local/nginx/sbin
|
!$:引用上一个命令的最后一个参数;(也可以使用按下esc,之后按一下.)
history
-c: 清空列表
1
2
3
4
5
6
7
8
9
|
[root@localhost etc]
# history |tail -5
119
history
-d 199
120
history
-d 119
121
history
|
tail
-5
122
history
-d 118
123
history
|
tail
-5
[root@localhost etc]
# history -c
[root@localhost etc]
# history
1
history
|
-d #: 删除指定的历史命令
-d OFFSET [n]:
#history -d 500 删第500个
#history -d 500 10 从500往后删10个
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[root@localhost etc]
# history |tail -5
118
history
119
history
|
tail
-5
120
history
-d 199
121
history
-d 119
122
history
|
tail
-5
[root@localhost etc]
# history -d 118
[root@localhost etc]
# history |tail -5
119
history
-d 199
120
history
-d 119
121
history
|
tail
-5
122
history
-d 118
123
history
|
tail
-5
|
-w:保存命令历史至历史文件中 家目录中(~)#ls -a 会看到有一个.bash_history文件
-a: 追加当前会话的命令历史至历史文件中去;
环境变量: 任何一个变量都可以echo $ 加变量名来获取
PATH:命令搜索路径
命令历史相关的环境变量:
HISTSIZE:命令历史中可以保存的命令的个数;( echo $HISTSIZE,默认1000条) 命令历史缓冲区大小
HISTFILE: 命令历史文件;(echo $HISTFILE,用户的历史文件存放的位置)
HISTFILESIZE:命令历史文件可以保存的命令的个数;(echo "$HISTFILESIZE"默认1000条)
HISTCONTROL: 控制命令历史的生成;
ignoredups: 忽略记录重复的命令;连续的相同命令才为重复;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
[root@localhost ~]
# echo "$HISTCONTROL"
ignoredups
[root@localhost ~]
# echo "$HISTCONTROL"
ignoredups
[root@localhost ~]
# echo "$HISTCONTROL"
ignoredups
[root@localhost ~]
# echo "$HISTCONTROL"
ignoredups
[root@localhost ~]
# echo "$HISTCONTROL"
ignoredups
[root@localhost ~]
# history |tail -5
15
echo
"$HISTCONTRAL"
16
echo
"$HISTCONTROL"
17
history
18
echo
"$HISTCONTROL"
19
history
|
tail
-5
|
ignorespace: 不记录以空白字符开头的命令;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
[root@localhost ~]
# history |tail -5
31
history
32
echo
"$HISTCONTROL"
33 HISTCONTROL=ignorespace
34
ls
/var
35
history
[root@localhost ~]
# ls /
bin etc lib64 misc opt sbin sys var
boot home lost+found mnt proc selinux tmp
dev lib media net root srv usr
[root@localhost ~]
# history |tail -5
31
history
32
echo
"$HISTCONTROL"
33 HISTCONTROL=ignorespace
34
ls
/var
35
history
|
ignoreboth: 同时具有上面两种特性;
命令历史的使用技巧
!n:执行命令历史中的第n条命令
!-n:执行命令历史中的倒数第n条命令
!!:执行上一条命令
!string:执行命令历史中最近一个以指定字符串开头的命令
!$:引用前一个命令的最后一个参数 ;ESC松开. ( 热点 ) 即 ESC,. 和!$一样的功能
命令补全、路径补全
Bash中的命令分为两种,一种是bash自带的内部命令,一种是通过环境变量读取的可执行文件,这个变量就是PATH,以冒号间隔的多个路径,命令补全则是通过PATH的多路径查找到可执行的文件所在位置
为 了简化打字工作,bash shell 提供了几种可以对输入不完整的文本进行自动补全的方法,如果想对输入进行补全,只需输入初始的几个字符,然后按“Tab”键,系统会自动匹配所需要的其余 输入,当有多种匹配时,系统会结出提示,按"ESC+?"组合键或按两次"Tab"键,可以列出所有可能的匹配,自动补全可以应用于下面的4类输入工作之 中。
环境变量名补全
如果输入的文本以"$"开始,shell就以当前shell的环境变量补全文本
用户名补全
命令、别名或函数的名字补全
如果文本以常规字符开始,shell将利用命令、别名或函数名来补全文本
主机名补全
如果输入的文本以“@”符号开始,系统会利用/etc/hosts文件中的主机名来补全文本
自动补全快捷键(此快捷键在远程终端无法使用)
Alt+~ 以一个用户名补全此处文本
Alt+$ 用变量补全此处的文本
Alt+@以一个主机名补全此处文本
一、命令补全
相信大家在操作linux系统时都会发现linux有一个非常棒的体验,这就是linux的命令补全功能,拥有了这个功能我们就不必花费更多的心思去死记硬背下各个命令行的操作命令了,单相信大家也仅仅只是知道有这么一个好用的功能,却并不是很清楚具体的这个命令到底是如何实现的,那么接下来我就简单的说一下命令补全的实现原理
命令补全是一个统称,仔细划分为:命令补全和路径补全两种。
命令补全:搜索PATH环境变量所指定的每个路径下以我们给出的字符串开头的可执行文件,如果多于一个,两次tab,可以给出列表;否则直接补全。也就是说在我们使用的linux环境变量中不存在我们想要补全的这个命令,那么补全这个命令就无从谈起了。
路径补全:搜索我们给出的起始路径下的每个文件名,并试图补全;在打头路径下查找补全。路径补全同样支持两次tab,给出列表。
路径补全
而路径补全是在给出打头路补全,如果没有打头的路径,则视为以当前路径开始补全。
命令别名
alias, 假名,别名,bash的一个内建命令,用来给常用的较长的命令定义个简短的名称。
alias 命令的基本格式为alias [word[='command']], []内为可选项。定义word为command的别名。若=’command’部分省略,则输出word之前的定义,未定义则报错。单独的alias列出 当前环境中所有可用的别名。通常来讲,关于alias,知道这么多就行了。但在使用alias的过程中还有一些问题需要注意。alias CMDALIAS=`COMMAND [option] [arguments]` 在shell中定义的别名仅在当前shell声明周期中有效,别名的有效范围仅为当前shell进程;
如果bash 的expand_aliases选项没有被设置,那么在非交互式shell中alias不会被执行展开。也就是说,在shell脚本中,使用alias会 导致”command not found”的错误。使用shopt命令来设置expand_aliases选项:
1
2
|
#设置别名扩展(启用别名)
#shopt -s expand_aliases
|
#alias 显示当前系统定义的所有别名
#type alias
#help alias
#unalias CMDALIAS
三、命令别名
操作系统之间有一下命令是有细微差别的,或者一些常用命令过于繁琐,我们想将之简化为我们各自能够熟练使用或者记忆的简短命令,这里就用的到命令别名了。
命令别名:(只在当前shell的生命周期有效,别名的有效范围仅为当前shell)
alias CMDALIAS='COMMAND [options] [arguments]' 使用格式
alias cls=clear 设置别名cls=clear
ualias cls 撤销别名cls
也可以将别名保存到配置文件中,以保证下次还能正常使用
~/.bashrc 这个文件便是别名保存文件
命令替换
$(COMMAND),或仅`(反引号,~上的那个):`command`
把命令中的某个子命令替换为其执行结果的过程
#echo “The Current directory is $(pwd)”
#echo "Dir is `pwd`"
#touch ./file-$(date+%F-%H-%M-%S).txt
./ 当前目录
二、命令替换
在实际的生产环境中我们都会遇到将某个命令中的子命令替换为其执行结果的经历,这其中最典型的就应该属日志保存文件了。
把命令中某个子命令替换为其执行结果的过程
$(要执行的结果) ``(反引号)
例:mv test- test-$(date +%F-%H-%M-%S) 或mv test- test-`date +%F-%H-%M-%S`
将test- 重命名为test-年-月-日-时-分-秒 这里的年月日时分秒便是一个命令的执行结果,是一个即时信息。
bash 支持的引号:
``:命令替换(反引号)
"":弱引用,可以用来实现变量替换
'':强引用,不完成变量替换
文件名通配:globbing
四、文件通配
在使用命令操作时,一下命令对象就连我们自己也不是很清楚,这里就需要一个通配对象来描述我们需要键入的命令对象了,这个用来描述的键入对象的字符我们就称之为通配符。
文件名通配, globbing
* 通配符 任意长度的任意字符
?匹配任意单个字符
[] 匹配指定范围内的任意单个字符
[^]匹配指定范围之外的任意单个字符
[abc] [a-m] [A-Z] [a-zA-Z] [0-9a-zA-Z]
用[]中间::中间一个单词表示某一类字符,然后用[]引用匹配,所以也支持取反[^] #man 7 glob
[[:space:]]空白字符
[:punct:]标点符号
[[:punct:]]小写字母
[[:upper:]]大写字母
[[:alpha:]]大小写字母
[[:digit:]]数字
[[:alnum:]]数字和大小写字母
[[:alpha:]]*[[:space:]]*[[:alpha:]] 以字母开头字母结尾中间有空白的
输入、输出重定向、管道
INPUT设备 passwd --stdin
OUTPUT设备
系统设定
默认输出设备:标准输出,STDOUT,1
默认输入设备:标准输入,STDIN,0
标准错误输出:STDERR,2
标准输入:键盘
标准输出和错误输出:显示器
在 linux系统中,数据流可分为3类:数据输入,数据输出和错误输出,相对的,每一个进程也都有3个特殊的文件描述:标准输入(stdin,文件描述指针 为0),标准输出(stdout,文件描述指针为1)和标准错误输出(stderr,文件描述指针为2),这3个特殊文件描述指针使进程在通常情况下接收 标准输入设备的输入,由标准输出设备显示输出.
而在输入通常指传给一个命令的键盘输入。通常标准输出是被定向到显示器,如果在执行过程中发 生错误,可能会发生错误,可能会存在一条错误消息,这是标准错误数据流,通常也会被定向到显示器。有两种基本的方法可以用来重定向标准输入 (stdin)、标准输出和标准错误(stderr),可以利用管道把这些数据流之一输送组另一个命令,也可以利用I/O重定向把这些数据流之一重定向一 个文件.所谓管道是指将某一个命令的输出结果传送到另一个命令,当成另一外命令的输入,其代表符号是"|".所谓I/O重定向是指命令执行的结果重新导出 到其他设备或文件(以">"或“>>”来表示)或是重新导入到其他设备或文件(以"<"或"<<"来表示)
分类:
输入重定向:<, <<
<: 输入重定向
<< EOF: 此处创建文件, Here Document
常用于在脚本中创建文件或生成菜单;
1
2
3
4
5
6
7
8
9
10
11
12
|
[root@localhost script]
# cat echo.sh
cat
<
cpu) print cpu information
mem) print memory information
disk) print disk information
quit) quit
EOF
[root@localhost script]
# bash echo.sh
cpu) print cpu information
mem) print memory information
disk) print disk information
quit) quit
|
输出重定向:>, >>
>: 覆盖输出
>>: 追加输出
set -C:禁止使用覆盖重定向至已经存在的文件;
set +C: 关闭上述特性;
>|:在-C特性下,强制使用覆盖重定向;
错误重定向:2>, 2>>
2>: 覆盖
将错误的信息输出到指定的文本中(会覆盖原文本的内容)
2>>: 追加
将错误输出到文本的的最后一行(不会覆盖原文本的内容)
管道
命令1|命令2|命令3|...
在linux系统中,管道的主要功能是将其他程序的输出结果直接导出到另一个程序作为输入数据,即将前一个程序的输出作为后一个程序的输入
并不是所有的命令都可以用管道接收
1
2
3
|
#pwd
/var/log
#ls /var/log | file
|
此命令将无法执行。(由于file在此时引用的是相对路径,如果想正确使用必须要使用如下方法)
1
|
#file `ls /var/log`|cut -d: -f2 |tr -d ' '|sort|uniq
|
(查看var/log下的文件类型,并取出第二段,除去前端的空格,排序,并去掉重复的.)
tee:
将第一个命令的结果保存到文件并同时输出到显示器。
1
|
#ls /etc |tee /tmp/etc.out |tr 'a-z' 'A-Z'|tr -d '0-9'
|
此命令就是将/etc下的所有目录或文件,全输出到/tmp/etc.out并在显示器显示时,去掉'0-9'的数字(/tmp/etc.out中的数据并不会因此而发生变化。)
Bash本身没有正则表达式的功能,在脚本里,使用正则表达式的是命令和软件包
例如sed和awk,它们可以解释正则表达式.
Bash 所做的是展开文件名扩展 -- 这就是所谓的通配(globbing) -- 但它不是使用标准的正则表达式. 而是使用通配符. 通配解释标准的通配符:*和?, 方括号括起来的字符,还有其他的一些特殊的字符(比如说^用来表示取反匹配).然而通配机制的通配符有很大的局限性. 包含有*号的字符串将不会匹配以点开头的文件,例如.bashrc. 另外,通配机制的? 字符和正则表达式中表示的意思不一样.
看图说话:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#在script创建了五个文件
[root@localhost script]
# touch a.1 b.c c.c t2.sh test.txt
[root@localhost script]
# ls
a.1 b.c c.c
fdisk
.sh
local
.sh t2.sh
test
.txt tss.sh
[root@localhost script]
# ls -l
total 12
-rw-r--r--. 1 root root 0 Feb 22 08:18 a.1
-rw-r--r--. 1 root root 0 Feb 22 08:18 b.c
-rw-r--r--. 1 root root 0 Feb 22 08:18 c.c
-rw-r--r--. 1 root root 3126 Feb 22 00:44
fdisk
.sh
-rw-r--r--. 1 root root 28 Feb 22 07:25
local
.sh
-rw-r--r--. 1 root root 0 Feb 22 08:18 t2.sh
-rw-r--r--. 1 root root 0 Feb 22 08:18
test
.txt
-rw-r--r--. 1 root root 10 Feb 22 01:39 tss.sh
|
1
2
3
|
#查看一下script以t开头的中间跟任一字符,以.sh结尾的文件
[root@localhost script]
# ls -l t?.sh
-rw-r--r--. 1 root root 0 Feb 22 08:18 t2.sh
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#查看以[ab]任意一个字母开头的文件
[root@localhost script]
# ls -l
total 12
-rw-r--r--. 1 root root 0 Feb 22 08:18 a.1
-rw-r--r--. 1 root root 0 Feb 22 08:30 abc.ddl
-rw-r--r--. 1 root root 0 Feb 22 08:31 anb.ppt
-rw-r--r--. 1 root root 0 Feb 22 08:18 b.c
-rw-r--r--. 1 root root 0 Feb 22 08:18 c.c
-rw-r--r--. 1 root root 0 Feb 22 08:30 cvb.doc
-rw-r--r--. 1 root root 3126 Feb 22 00:44
fdisk
.sh
-rw-r--r--. 1 root root 28 Feb 22 07:25
local
.sh
-rw-r--r--. 1 root root 0 Feb 22 08:18 t2.sh
-rw-r--r--. 1 root root 0 Feb 22 08:18
test
.txt
-rw-r--r--. 1 root root 10 Feb 22 01:39 tss.sh
[root@localhost script]
# ls -l [ab]*
-rw-r--r--. 1 root root 0 Feb 22 08:18 a.1
-rw-r--r--. 1 root root 0 Feb 22 08:30 abc.ddl
-rw-r--r--. 1 root root 0 Feb 22 08:31 anb.ppt
-rw-r--r--. 1 root root 0 Feb 22 08:18 b.c
|
1
2
3
4
5
6
7
8
9
|
#非字母a或b开头的文件
[root@localhost script]
# ls -l [^ab]*
-rw-r--r--. 1 root root 0 Feb 22 08:18 c.c
-rw-r--r--. 1 root root 0 Feb 22 08:30 cvb.doc
-rw-r--r--. 1 root root 3126 Feb 22 00:44
fdisk
.sh
-rw-r--r--. 1 root root 28 Feb 22 07:25
local
.sh
-rw-r--r--. 1 root root 0 Feb 22 08:18 t2.sh
-rw-r--r--. 1 root root 0 Feb 22 08:18
test
.txt
-rw-r--r--. 1 root root 10 Feb 22 01:39 tss.sh
|
1
2
3
4
5
|
[root@localhost script]
# ls -l {b*,c*,*st*}
-rw-r--r--. 1 root root 0 Feb 22 08:18 b.c
-rw-r--r--. 1 root root 0 Feb 22 08:18 c.c
-rw-r--r--. 1 root root 0 Feb 22 08:30 cvb.doc
-rw-r--r--. 1 root root 0 Feb 22 08:18
test
.txt
|
注:Bash会对命令行中没有引号引起来的字符尝试文件名扩展
1
2
|
[root@localhost script]
# echo *
a.1 abc.ddl anb.ppt b.c c.c cvb.doc
fdisk
.sh
local
.sh t2.sh
test
.txt tss.sh
|
文件名扩展能匹配点开头的文件,但仅在模式字串明确地包含字面意思的点(.)时才扩展.
1
2
3
4
5
6
|
[root@localhost ~]
# ls -a .bash_*
.bash_history .bash_logout .bash_profile
[root@localhost ~]
# ls -al [?]bash_*
ls
: cannot access [?]bash_*: No such
file
or directory
[root@localhost ~]
# ls -al [.]bash_*
ls
: cannot access [.]bash_*: No such
file
or directory
|
这样还是可以的
1
2
3
4
|
[root@localhost ~]
# ls -al .[b]?sh_profile
-rw-r--r--. 1 root root 176 May 20 2009 .bash_profile
[root@localhost ~]
# ls -al .[b]?shr*
-rw-r--r--. 1 root root 176 Sep 22 2004 .bashrc
|
可以改变Bash对通配字符进行解释的行为.
set -f 命令或set -o noglob可以禁止通配机制, 并且shopt的选项nocaseglob和nullglob 能改变通配的行为.
1
2
3
4
5
|
[root@localhost script]
# ls a*
a.1 abc.ddl anb.ppt
[root@localhost script]
# set -f
[root@localhost script]
# ls a*
ls
: cannot access a*: No such
file
or directory
|
这时表明通配功能己经关闭,如果要开启,可以使用
set +o noglob
bash的配置文件:
全局配置:
/etc/profile,/etc/profile.d/*.sh,/etc/bashrc
个人配置:
~/.bash_profile,~/.bashrc
profile类的文件:
设定环境变量
运行命令或者脚本
bashrc类的文件:
设定本地变量
定义命令别名
bash的分类:
用户的登陆-打开一个shell shell是一个可执行程序-->配置属性在配置文件中
站在用户登陆的角度来说,shell的类型分两种:
登陆式shell:
正常通过某终端登陆 su - USERNAME su -l USERNAME
非登陆式shell:
su USERNAME
图形终端下打开命令窗口 自动执行的shell脚本
登陆式shell如何读取配置文件?
/etc/profile-->/etc/profile.d/*.sh-->~/.bash_profile-->~/.bashrc-->/etc/bahsrc
非登陆式shell如何读取配置文件?
~/.bashrc-->/etc/bashrc-->/etc/profile.d/*.sh
eg
nano .bashrc(家目录下的~)
alias cls='clear'
nano .bashprofile
echo "Hello,hive.Welcome to our system. It is `date`"
nano .bashprofile
umask 027
umask:遮罩码
# umask
创建文件及文件夹的默认权限
(文件默认是不能够获得执行权限)如果文件创建时获得的结果中有执行权限,则将其权限加1;
文件666 - (root 002) (普通用户 022)
目录-文件夹 777 - (root 002) (普通用户 022)
#umask 022
Bash shell 编程
一、Bash shell是什么
shell是什么,Bash与shell又有什么关系。(以前我也不是特别清楚~~~~)
shell 是一个交互性命令解释器。shell独立于操作系统,这种设计让用户可以灵活选择适合自己的shell。shell让你在命令行键入命令,经过shell解释后传送给操作系统(内核)执行。
shell 是一个命令处理器(command processor)--是一个读入并解释你输入的命令的程序。除了是一个命令中断器以外,shell还是一个程序设计语言。你可以编写shell可以解 释的程序(被称为源程序),这些源程序可以包含shell程序设计命令等等。shell除了解释命令以外,还有其他工作,它也可以配置和编程。
shell拥有自己的语言允许用户编写程序并以一种复杂方式运行。shell编程语言具有许多常用的编程语言的特征,例如:循环和控制结构等。用户可以生成像其他应用程序一样复杂的shell程序。
以下是shell功能的一个汇总:
查找命令的位置并且执行相关联的程序;
为shell变量赋新值;
执行命令替代;
处理 I/O重定向和管道功能;
提供一个解释性的编程语言界面,包括tests、branches和loops等语句。
bash是borne again shell的缩写,它是shell的一种,Linux上默认采用的是bash。当然还有sh,dash,tcsh和ksh等
1、读入变量(read)
read命令是用于从终端或者文件中读取输入的内建命令,read命令读取整行输入,每行末尾的换行符不被读入。在read命令后面,如果没有指定变量名,读取的数据将被自动赋值给特定的变量REPLY。下面的列表给出了read命令的常用方式:
read | 从标准输入中读取一行并赋值给特定的变量ERPLY(没有指定变量名的话) |
read one | 从标准输入读取并赋值给变量one |
read first last | 从标准输入读取输入到第一个空格或者回车,将输入的第一个单词放到变量first中,并将该行其他的输入放在变量last中。 |
read -p | 打印提示信息,等待输入,并赋值给默认的变量REPLY |
read -t | 设置超时时间(单位:秒) |
read -a arry_name |
将输入在清单存入到"arry_name"数组中 |
read示例:
1
2
3
4
5
|
#无变量,默认存于特定变量REPLY中
[root@localhost apache]
# read #等待控制台输入,并将结果赋值给特定内置变量REPLY。
hello
#控制台输入Hello
[root@localhost apache]
# echo $REPLY #打印变量
hello
|
1
2
3
4
5
|
[root@localhost apache]
# read one two three
3 9 8
#输入1 2 3,它们之间用空格隔开。
[root@localhost apache]
# echo "one is:$one,two is:$two three is:$three"
#打印结果
one is:3,two is:9 three is:8
|
1
2
3
4
5
|
[root@localhost apache]
# read -p "Please input your name:" name
#输出"Please input your name"文本提示,同时等待输入,并将结果赋值给name
Please input your name:scott
[root@localhost apache]
# echo "$name"
scott
|
1
2
3
4
|
[root@localhost apache]
# read -t 4 -p "Enter your nmber:"
#限时4秒输入,如果过了4秒,将退出不再输入
Enter your nmber:[root@localhost apache]
# echo $REPLY
#结果为空
|
2. 状态判断:
test是Shell中提供的内置命令,主要用于状态的检验,如果结果为0,表示成功,否则表示失败。
1
2
3
4
|
[root@localhost apache]
# name=scott
[root@localhost apache]
# test $name != scoot
[root@localhost apache]
# echo $? #测试上一条命令执行状态的返回值,0表示功
0
|
注意的是test命令不支持Shell中提供的各种通配符
1
2
3
4
|
[root@localhost apache]
# name=tom
[root@localhost apache]
# test $name = [Tt]om
[root@localhost apache]
# echo $?
1
|
test命令还可以中括号予以替换,其语义保持不变
1
2
3
4
|
[root@localhost apache]
# name=tom
[root@localhost apache]
# [ "$name" = tom ]
[root@localhost apache]
# echo $?
0
|
在Shell中还提供了另外一种用于状态判断的方式:` expr `,和test不同的是,该方式中的表达式支持通配符
1
2
3
|
[root@localhost apache]# [[ $name==[tT]om ]]
[root@localhost apache]# echo $?
0
|
在` expression `中,expression可以包含&&(逻辑与)和||(逻辑或)。
1
2
3
4
|
[root@localhost apache]
# friend=Jack
[root@localhost apache]
# [[ $name==[tT]om && $friend == "Jack" ]]
[root@localhost apache]
# echo $?
0
|
在Shell中还提供了let命令的判断方式: (( expr ))
1
2
3
4
5
6
7
8
|
[root@localhost apache]
# a=45
[root@localhost apache]
# b=34
[root@localhost apache]
# (( a > b ))
[root@localhost apache]
# echo $?
0
[root@localhost apache]
# (( a == 45 && b == 34 ))
[root@localhost apache]
# echo $?
0
|
下面的表格是test命令支持的操作符:
表达式 | 判断为真的条件 |
字符串判断 | 结果 |
[ StringA=String ] | StringA等于StringB |
[ StringA==StringB ] | StringA等于StringB |
[ StringA!=StringB ] | StringA不等于StringB |
[ String ] | String不为空 |
[ -z String ] | String长度为0 |
[ -n String ] | String长度不为0 |
逻辑判断 | |
[ StringA -a StringB ] | StringA和StringB都是真 |
[ StringA -o StringB ] | StringA或StringB是真 |
[ !String ] | String不为真 |
逻辑判断(复合判断) | |
[[ pattern1 && pattern2 ]] | pattern1和pattern2都是真 |
[[ pattern1 || pattern2 ]] | pattern1或pattern2是真 |
[[ !pattern ]] | pattern不为真 |
整数判断 | |
[ intA -eq intB ] | intA等于intB |
[ intA -ne intB ] | intA不等于intB |
[ intA -ge intB ] | intA大于等于intB |
[ intA -lt intB ] | intA小于intB |
[ intA -le intB ] | intA小于等于intB |
[ intA -gt intB ] | intA大于intB |
文件判断中的二进制操作 | |
[ fileA -ot fileB ] | fileA比fileB旧 |
[ fileA -ef fileB ] | fileA和fileB有相同的设备或者inode值 |
[ fileA -nt fileB ] | fileA比fileB新 |
文件检验 | |
[ -d $file ] or [[ -d $file ]] | file为目录且存在时为真 |
[ -e $file ] or [[ -e $file ]] | file为文件且存在时为真 |
[ -f $file ] or [[ -f $file ]] | file为非目录普通文件存在时为真 |
[ -s $file ] or [[ -s $file ]] | file文件存在, 且长度不为0时为真 |
[ -L $file ] or [[ -L $file ]] | file为链接符且存在时为真 |
[ -r $file ] or [[ -r $file ]] | file文件存在且可读时为真 |
[ -w $file ] or [[ -w $file ]] | file文件存在且可写时为真 |
[ -x $file ] or [[ -x $file ]] | file文件存在且可执行时为真 |
[ -S $file ] or [[ -S $file ]] | 测试文件是否存在在并且是否是一个套接字文件 |
[ -h $file ] or [[ -h $file ]] | file为链接符且存在时为真 |
[ -p $file ] or [[ -p $file ]] | 测试文件是否存在并且是否是一个管道文件 |
注:在逻辑判断(复合判断中),pattern可以包含元字符,在字符串的判断中,pattern2必须被包含在引号中。
3.流程控制语句:
if语句格式如下:
if语句的后面是Shell命令,如果该命令执行成功返回0,则执行then后面的命令。
if command;then
command
command
fi
用test命令测试其后面expression的结果,如果为真,则执行then后面的命令。
if test expression
then
command
fi
下面的格式和test expression等同
if [ string/numeric expression ]
then
command
fi
下面的两种格式也可以用于判断语句的条件表达式,而且它们也是目前比较常用的两种。
if ` string expression `
then
command
.........
fi
if (( numeric expression ))
then
command
.......
fi
示例:
1
2
3
4
5
6
7
8
9
10
11
|
[root@localhost tmp]
# cat test2.sh
#!/bin/bash
read
-p
"Are you OK(y/n)?"
answer
#这里的$answer变量必须要用双引号扩住,否则判断将失败
if
[
"$answer"
= y -o
"$answer"
= Y ]
then
echo
"Glad to see it."
fi
[root@localhost tmp]
# bash test2.sh
Are you OK(y
/n
)?y
Glad to see it.
|
上面的判断还可以替换为:
1
2
3
4
5
6
7
8
9
10
|
[root@localhost tmp]
# cat test2.sh
#!/bin/bash
read
-p
"Are you OK(y/n or Maybe)?"
answer
#` `复合命令操作符允许其中的表达式包含元字符,这里输入以y或Y开头的任意单词,或Maybe都执行then后面的echo。
if
[[ $answer == [yY]* || $answer = Maybe ]];
then
echo
"Glad to hear it."
fi
[root@localhost tmp]
# bash test2.sh
Are you OK(y
/n
or Maybe)?yadfadsf
Glad to hear it.
|
1
2
3
4
5
6
7
8
9
10
11
|
[root@localhost tmp]
# cat test3.sh
#!/bin/bash
answer=
"not really"
if
[[ $answer = [Nn]o?( way |t really) ]]
then
echo
"I am sorry."
fi
[root@localhost tmp]
# bash -n test3.sh
[root@localhost tmp]
# bash test3.sh
I am sorry.
# 对于本示例中的扩展通配符,这里需要给出一个具体的解释。[Nn]o匹配No或no,?( way|t really)则表示0个或1个( way或t really),因此answer变量匹配的字符串为No、no、Not really、not really、No way、no way。
|
if/elif/else语句的使用方式和if语句极为相似,其格式如下:
if command
then
command
elif command
then
command
else
command
fi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
[root@localhost tmp]
# cat test4.sh
read
-p
"How old are you?"
age
if
[ $age -lt 0 -o $age -gt 120 ]
#(( age < 0 || age > 120 ))
then
echo
"You are so old."
elif
[ $age -
ge
0 -a $age -
le
12 ]
#(( age >= 0 && age <= 12 ))
then
echo
"You are child."
elif
[ $age -
ge
13 -a $age -
le
19 ]
# (( age >= 13 && age <= 19 ))
then
echo
"You are 13--19 years old."
elif
[ $age -
ge
20 -a $age -
le
29 ]
# ((age >= 20 && age <= 29 ))
then
echo
"You are 20--29 years old."
elif
[ $age -
ge
30 -a $age -
le
39 ]
# (( age >= 30 && age <= 39 ))
then
echo
"You are 30--39 years old."
else
echo
"You are above 40."
fi
[root@localhost tmp]
# bash test4.sh
How old are you?60
You are above 40.
|
=======================================完================================================
五、用户、组
在linux系统的管理当中有一个非常关键的地方,这就是用户和组的管理
用户:UID, /etc/passwd
/etc/passwd字段的意思:
account:登录名
passwd:密码(占位符)-->/etc/shadow
UID: 用户ID
GID: 基本组ID
GECOS:用户的注释信息
HOME DIR:家目录
SHELL:用户的默认shell
组:GID, /etc/group
用户和组都会具有个自的密码,而密码便存在于影子口令当中
影子口令:
用户:/etc/shadow
各个字段的含义
account:登录名
加密算法
杂质
encrypted password:加密的密码
最近一个修改密码的时间:(从1970年到最近修改密码的天数)
最短使用期限
最长使用期限
警告时间
非活动时间
用户账户过期时间
保留区域
用户类别:
管理员ID号:0
普通用户ID号:1-65535
系统用户:1-499 不允许其登陆系统
一般用户:500-60000
用户组类别:
管理员组:
普通组:
系统组:
一般组:
用户组类别:
私有组:创建用户时,如果没有为其指定所属的组,系统会自动为其创建一个与用户名相同的组
基本组,默认组
附加组,额外组;默认组以外的其他组
/etc/group:
组名:密码:GID:以此组为其附加组的用户列表
加密方法:
对此加密:加密和解密使用同一个密码
公钥加密:每个密码都成对儿出现,一个为私钥(secret key),一个为公钥(public key)
单项加密,散列加密:提取数据特征码,常用于数据完整性校验
1、雪崩效应(蝴蝶效应) 原始数据的微小改变将引起结果的巨大变化
2、定长输出
MD5:Message Digest, 128位定长输出
SHA1:Secure Hash Algorithm 160位定长输出
useradd [options] USERNAME
-u UID
-g GID (基本组)
-G GID,... (附加组)
-c "COMMENT" (注释信息)
-d /X/Y/Z 指定其家目录路径
-s 指定shell路径
-m -k 强制给用户创建家目录并将环境变量转移
-M 不给用户创建家目录
-r 创建一个系统用户
/etc/login.defs 默认创建用户的配置文件
环境变量:
PATH
HISTSIZE
SHELL 保存当前用户的默认shell
/etc/shell: 指定了当前系统可用的安全shell
userdel [option] USERNAME
-r:同时删除用户的家目录
id:查看用户的账号属性信息
-u 显示用户UID
-g 显示GID
-G 显示所有ID
-n 显示组名称 组合其他选项使用
finger:查看用户的账号信息
finger USERNAME
修改用户账号属性:
usermod
-u 修改用户UID
-g 修改用户GID(基本组)
-a -G GID:不使用-a选项,会覆盖此前的附加组
-c 修改注释信息
-d -m 修改家目录并移动此前的文件到新的家目录中去
-s 修改用户的默认shell
-l 修改用户名
-e 指定用户过期时间
-f 指定非活动时间
-L 锁定用户账号
-U 解锁用户账号
chsh:修改用户默认shell
chfn:修改用户的注释信息
密码管理:
passwd [USERNAME]
--stdin 从标准输入
-l 锁定用户账号
-u 解锁用户账号
-n 密码最短使用期限
-d 删除用户密码
pwck:检查用户的账户完整性
组管理:
创建组:
groupadd
-g 指定GID
-r 添加为系统组
groupmod
-g 修改GID
-n 修改组名
groupdel 删除组
gpasswd:为组设定密码
newgrp 组 临时登录一个新用户组
exit 退出新组
chage:改变用户密码过期信息
-d 指定密码的最后一次修改时间
-E 更改过期时间
-I 更改非活动时间
-m 更改最短使用期限
-M 更改最长使用期限
-w 更改警告时间
六、权限
每个用户在系统中都会拥有不同的权限,那我们是如何定义权限呢?我们将权限划分为三种:r,读 w写, x执行。而针对于r,w,x这三种权限对于文件和目录的解释还是有一些区分的。
文件:
r: 可读,可以使用类似cat等命令查看文件内容;
w: 可写,可以编辑或删除此文件;
x:可执行,exacutabls, 可以命令提示符下当作命令提交给内核运行;
目录:
r: 可以对此目录执行ls以列出内部的所有文件;
w: 可以在此目录创建文件;
x: 可以使用cd切换进此目录,也可以使用ls -l查看内部文件的详细信息;
rwx:r--: 只读 r-x: 读和执行 ---:无权限
0 000 ---:无权限
1 001 --x: 执行
2 010 -w-: 写
3 011 -wx: 写和执行
4 100 r--: 只读
5 101 r-x: 读和执行
6 110 rw-: 读写
7 111 rwx: 读写执行
除此之外,我们使用ls -l命令时就会发现每个用户拥有三位一组的权限划分三组。
三类用户:u:属主 g:属组 o:其它用户 a:所有类别
chown:改变文件目录属主(只有root可以使用此命令)
# chown 属主 文件
-R 递归修改,修改目录及其内部文件的属主
--reference=某文件 file,... 设定file文件的属性和某文件属性一样
# chown 属主:属组 文件
# chown 属主.属组 文件
# chown :属组 文件
chgrp: 改变文件目录属组
# chgrp:组名 文件
-R 递归修改
--reference=某文件 file,...
chmod:修改文件的权限
修改三类用户的权限:
chmod MODE file,...
-R 递归修改
--reference=xx 修改权限等于某些文件
修改某类用户或某些类权限:
修改某类用户的某位或某些位权限:
openssl passwd -1 -salt '1234567' (创建一个以md5加密的杂质为123456的密文)