第十章:shell基础知识
一、什么是shell
shell时系统跟计算机硬件交互时使用的中间介质,知识系统的一个工具。实际上,在shell和计算机硬件之间还有一层东西–系统内核。用户直接面对的不是计算机硬件而是shell,用户把指令告诉shell,然后shell在传输给系统内核,接着内核再去支配计算机硬件去执行各种操作。
1.记录命令历史
我们执行过的命令Linux都会记录,预设可以记录1000条历史命令。这些命令保存在用户的家目录的.bash_history文件中。(只有正常退出当前shell才会保存)
- !!:执行上一条命令;
1.txt anaconda-ks.cfg dir1 dir1.tar dira dirb test
[root@zl_cloud ~]# !!
ls
1.txt anaconda-ks.cfg dir1 dir1.tar dira dirb test
[root@zl_cloud ~]#
- !n:n是指数字,表示执行命令历史中的第n条指令;
[root@zl_cloud ~]# !50
cd .
[root@zl_cloud ~]#
- !字符串(字符串>=):执行命令历史中最后一次以这个字符串开头的命令。
[root@zl_cloud ~]# !pw
pwd
/root
[root@zl_cloud ~]#
2.命令和文件名补全
Tab键:可以补全一个指令、一个路径或者一个文件名。连续按两次该键的话系统会把所有的命令和文件都列出来。
3.别名
alias:把一个常用的并且很长的指令另取为一个简单易记的指令。
①自定义别名
格式:alias 【命令别名】=【‘具体的命令’】。
[root@zl_cloud ~]# alias aming='pwd'
[root@zl_cloud ~]# aming
/root
[root@zl_cloud ~]#
②解除别名
命令:unalias
[root@zl_cloud ~]# unalias aming
[root@zl_cloud ~]# aming
-bash: aming: 未找到命令
[root@zl_cloud ~]#
③查看别名
命令:alias
[root@zl_cloud ~]# alias
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
[root@zl_cloud ~]#
4.通配符
在bash下,可以使用*来匹配零个或多个字符,用?匹配一个字符。
[root@zl_cloud ~]# ls
1.txt anaconda-ks.cfg dir1 dir1.tar dira dirbb test
[root@zl_cloud ~]# ls -d dir*
dir1 dir1.tar dira dirbb
[root@zl_cloud ~]# ls -d dir?
dir1 dira
[root@zl_cloud ~]#
5.输入\输出重定向
输入\输出重定向用于改变命令的输入\输出。输入重定向命令是<,输出重定向命令是>。
[root@zl_cloud ~]# cat 1.txt
test
[root@zl_cloud ~]# echo "111" > 1.txt //输出重定向
[root@zl_cloud ~]# cat 1.txt
111
[root@zl_cloud ~]# echo "222" >> 1.txt //追加输出重定向
[root@zl_cloud ~]# cat 1.txt
111
222
[root@zl_cloud ~]#
6.管道符
- | :用于将前一个命令作为后一个指令的输入
[root@zl_cloud ~]# cat /etc/passwd | head -3
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@zl_cloud ~]#
7.作业控制
-
①当运行进程时,如何终止进程?使用(Ctrl+C)键终止:
-
②当运行进程时,如何暂停进程?使用(Ctrl+Z)键暂停:
... //本来上面在执行编写1.txt文件。
[1]+ 已停止 vi 1.txt
[root@zl_cloud ~]#
多个暂停的任务如何查看?使用jobs命令:
[root@zl_cloud ~]# jobs
[1]- 已停止 vi 1.txt
[2]+ 已停止 vmstat 1 > /tmp/1.log
[root@zl_cloud ~]#
暂停后如何恢复呢?使用fg命令恢复:
[root@zl_cloud ~]# fg
//如果有多个的话,在fg后空格加对于jobs前面显示的数字即可。
暂停后如何将它到后台运行呢?使用bg命令:
[root@zl_cloud ~]# bg
关闭当前的shell,再次打开另一个shell时,使用jobs命令并不会显示在后台运行或者被暂停的任务。要像关闭这些任务,则需要先知道它们的pid:
[root@zl_cloud ~]# ps aux | grep vmstat //第二列就是pid
root 6025 0.0 0.0 138804 1180 pts/0 S 00:43 0:00 vmstat 1
root 6027 0.0 0.0 112660 964 pts/0 S+ 00:44 0:00 grep --color=auto vmstat
[root@zl_cloud ~]# kill 6025
[root@zl_cloud ~]# jobs //可看到对应的已经终止关闭了
[1]+ 已停止 vi 1.txt
[2]- 已终止 vmstat 1 > /tmp/1.log
[root@zl_cloud ~]#
遇到结束不了的进程时,可加一个选项,即kill -9 【pid】。
[root@zl_cloud ~]# jobs
[1]+ 已停止 vi 1.txt
[root@zl_cloud ~]# ps aux | grep txt
root 6030 0.0 0.0 126264 1640 pts/0 T 00:50 0:00 vi 1.txt
root 6032 0.0 0.0 112660 960 pts/0 R+ 00:50 0:00 grep --color=auto txt
[root@zl_cloud ~]# kill 6030
[root@zl_cloud ~]# jobs //发现没结束
[1]+ 已停止 vi 1.txt
[root@zl_cloud ~]# kill -9 6030
[root@zl_cloud ~]# jobs
[1]+ 已杀死 vi 1.txt
[root@zl_cloud ~]#
二、变量
通常shell预设的变量都是大写的。变量就是使用一个比较简单的字符串来替代某些具有特殊意义的设定以及数据。就拿以前讲的PATH变量,它就替代了所有常用命令的绝对路径的设定。
[root@zl_cloud ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@zl_cloud ~]# echo $PWD
/root
[root@zl_cloud ~]#
1.命令env
可列出系统预设的全部系统变量:
[root@zl_cloud ~]# env
XDG_SESSION_ID=32
HOSTNAME=zl_cloud
SELINUX_ROLE_REQUESTED=
TERM=vt100
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=192.168.60.1 51890 22
SELINUX_USE_CURRENT_RANGE=
SSH_TTY=/dev/pts/0
USER=root
....
登录不同的用户,这些环境变量的值也不同。当前显示的是root账户的环境变量。下面列举一下常见的环境变量:
- HOSTNAME:表示主机的名称。
- SHELL:表示当前用户的shell类型。
- HISTSIZE:表示历史记录数。
- MAIL:表示当前用户的邮件存放目录。
- PATH:该变址决定了shell将到哪些目录中寻找命令或程序。
- PWD:表示当前目录。
- LANG:这是与语言相关的环境变量,多语存环境可以修改此环境变量。
- HOME:表示当前用户的家目录。
- LOGNAME:表示当前用户的登录名。
2.命令set
与env命令相似,也可以输出环境变量:
[root@zl_cloud ~]# set
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="4" [1]="2" [2]="46" [3]="2" [4]="release" [5]="x86_64-redhat-linux-gnu")
BASH_VERSION='4.2.46(2)-release'
...
它不仅可以显示系统预设的变量,也可以显示用户自己自定义的变量:
[root@zl_cloud ~]# myname=Aming
[root@zl_cloud ~]# echo $myname
Aming
[root@zl_cloud ~]# set | grep myname
myname=Aming
[root@zl_cloud ~]#
虽然可以自定义变量,但是该变量只能在当前shell中生效:
[root@zl_cloud ~]# bash //执行该命令,会进入一个子shell环境中
[root@zl_cloud ~]# echo $myname
[root@zl_cloud ~]#
可用pstree指令查看bash结构:
[root@zl_cloud ~]# yum install -y psmisc //没有该指令的话就安装
[root@zl_cloud ~]# pstree | grep bash
|-login---bash
|-sshd---sshd---bash-+-grep
[root@zl_cloud ~]# bash
[root@zl_cloud ~]# pstree | grep bash
|-login---bash
|-sshd---sshd---bash---bash-+-grep
[root@zl_cloud ~]#
如果想让这个变量在子shell中生效,则可以用export指令:
[root@zl_cloud ~]# abc=123
[root@zl_cloud ~]# echo $abc
123
[root@zl_cloud ~]# bash
[root@zl_cloud ~]# echo $abc
[root@zl_cloud ~]# exit
exit
[root@zl_cloud ~]# export abc
[root@zl_cloud ~]# echo $abc
123
[root@zl_cloud ~]# bash
[root@zl_cloud ~]# echo $abc
123
[root@zl_cloud ~]#
如果想让设置的环境变量一直生效:
①允许系统内所有用户登录后都能使用该变量:
在/etc/profile文件的最后一行加入export myname=zl,然后运行source /etc/profile就可以生效了。此时再运行bash命令或者切换到其他账户就可以看到效果。
[root@zl_cloud ~]# echo “export myname=Aming” >> /etc/profile
[root@zl_cloud ~]# source /etc/profile
[root@zl_cloud ~]# bash
[root@zl_cloud ~]# echo $myname
Aming
[root@zl_cloud ~]# exit
exit
[root@zl_cloud ~]# echo $myname
Aming
[root@zl_cloud ~]#
②仅允许当前用户使用该变量:
在用户主目录下的.bashrc文件的最后一行加入exprofile myname=Aming,然后运行source .bashrc就可以生效了。这时在登陆test账户myname变量则不会生效了。
Linux下设置自定义变量,规则如下:
- ①设定变量的格式为a=b,a为变量名,b为变量的内容,等号两边不能有空格。
- ②变量名只能由字母、数字以及下划线组成,且不能以数字开头。
- ③变量内容带有特殊字符(如空格)时,需要加上单引号。
[root@zl_cloud ~]# myname='Aming Li' //如果本身就带有单引号,则需要用双引号
[root@zl_cloud ~]# echo $myname
Aming Li
[root@zl_cloud ~]#
- ④变量内容需要用到其他命令,运行结果则可以使用反引号。
[root@zl_cloud ~]# myname=`pwd`
[root@zl_cloud ~]# echo $myname
/root
[root@zl_cloud ~]#
- ⑤变量内容可以累加其他变量的内容,但需要加双引号。
[root@zl_cloud ~]# myname="$LOGNAME"Aming
[root@zl_cloud ~]# echo $myname
rootAming
[root@zl_cloud ~]#
- ⑥取消某个变量,只需要输入unset 变量名即可。
[root@zl_cloud ~]# unset abc
[root@zl_cloud ~]# echo $abc
[root@zl_cloud ~]#
三、系统环境变量与个人环境变量的配置文件
- /etc/profile:这个文件预设了儿个重要的变量,例如PATH、USER、LOGNAME、MAIL、INPUTRC、HOSTNAME . HISTSIZE, umask等。
- /etc4/bashrc:这个文件主要预设mask以及PS1。这个PS1就是我们在输入命令时前面的那串字符。
不妨看一下PS1的值,如下所示:
[root@zl_cloud ~]# echo $PS1
[\u@\h \W]\$
[root@zl_cloud ~]#
其中,\u指用户,\h指主机名,\W指当前目录,$指字符# (如果是普通用户.则显示为$)。
除了以上两个系统级别的配置文件外,每个用户的主目录下还有以下几个隐藏文件。
- .bash_profile:该文件定义了用户的个人化路径与环境变量的文件名称。每个用户都可使用该文件输入专属于自己的shell信息,当用户登录时,该文件仅仅执行一次。
- -bashrc:该文件包含专属于自己的shell的bash信息,当登录或每次打开新的shell时,该文件会被读取。例如,你可以将用户自定义的別名或者自定义变量写到这个文件中。
- .bash_history:该文件用于记录命令历史。
- .bash_logout:当退出shell时,会执行该文件。你可以将一些淸理的工作放到这个文件中。
四、Linux shell中的特殊符号
1.*代表零个或多个任意字符
[root@zl_cloud ~]# ls
1.txt anaconda-ks.cfg dir1 dir1.tar dira dirbb test
[root@zl_cloud ~]# ls -d dir*
dir1 dir1.tar dira dirbb
2.?只代表一个任意的字符
[root@zl_cloud ~]# ls
1.txt anaconda-ks.cfg dir1 dir1.tar dira dirbb test
[root@zl_cloud ~]# ls -d dir?
dir1 dira
[root@zl_cloud ~]#
3.注释符号#
[root@zl_cloud ~]# abc=123 #zhushineirong
[root@zl_cloud ~]# echo $abc
123
[root@zl_cloud ~]#
4.脱义字符\
这个字符会将后面的特殊符号(如*)还原为普通字符:
[root@zl_cloud ~]# ls -d test\*
ls: 无法访问test*: 没有那个文件或目录
[root@zl_cloud ~]#
5.管道符|
==将前面命令的输出作为后面命令的输入。==这里体到的后面的命令并不是所有命令都可以用的,一般针对文档操作的命令比较常用。例如cat、less、head、tail、grep、cut、sort、wc、uniq、tee、tr、split、sed、awk等。
[root@zl_cloud ~]# cat 1.txt //先演示一下里面的内容
111
222
[root@zl_cloud ~]# cat 1.txt |wc -l //wc -l表示一个文档有多少行
2
[root@zl_cloud ~]#
6.命令cut
cut命令用来截取摸一个字段,格式:cut -d ‘分隔字符’ 【-cf】n,n是指数字。
- -d:后面跟分隔字符,分隔字符要用单引号括起来;
- -c:后面接的是第几个字符;
- -f:后面接的是第几个区块。
[root@zl_cloud ~]# cat /etc/passwd | head -3 //先看一下原来的格式
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@zl_cloud ~]# cat /etc/passwd | cut -d ':' -f7 | head -3 //我截取的是第七个区块
/bin/bash
/sbin/nologin
/sbin/nologin
[root@zl_cloud ~]# head -2 /etc/passwd | cut -c2 //截取第2个字符
o
i
[root@zl_cloud ~]#
[root@zl_cloud ~]# head -2 /etc/passwd | cut -c1-10 //截取第1到第10个字符
root:x:0:0
bin:x:1:1:
[root@zl_cloud ~]#
[root@zl_cloud ~]# head -2 /etc/passwd | cut -c1,3,10 //截取第1,3,10字符
ro0
bn:
[root@zl_cloud ~]#
7.命令sort
该命令做排序,格式为sort 【-t 分隔符】 【-kn1,n2】 【-nru】。n1,n2指的是数字。
- -t:后面跟分隔字符,作用跟cut的-d选项一样;
- -n:表示使用纯数字排序;
- -r:表示反向排序;
- -u:表示去重复;
- -kn1,n2:表示由n1区间排序到n2区间,可以只写-kn1,即对n1字段排序。
[root@zl_cloud ~]# head -4 /etc/passwd | sort //不加任何选项的话只对首字母一次按字母顺序比较,最后按升序顺序输出
adm:x:3:4:adm:/var/adm:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
root:x:0:0:root:/root:/bin/bash
[root@zl_cloud ~]#
[root@zl_cloud ~]# head -4 /etc/passwd | sort -t ':' -k3 -n //只对第3区间排序,用纯数字排序
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
[root@zl_cloud ~]#
[root@zl_cloud ~]# head -4 /etc/passwd | sort -t ':' -k3,5 -r //只对3-5区间排序,用反向顺序
adm:x:3:4:adm:/var/adm:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
root:x:0:0:root:/root:/bin/bash
[root@zl_cloud ~]#
8.命令wc
用户统计文档的行数(-l)、字符数(-m)或词数(-w)。
[root@zl_cloud ~]# wc /etc/passwd
25 47 1231 /etc/passwd
[root@zl_cloud ~]# cat /etc/passwd | wc -l
25
[root@zl_cloud ~]# cat /etc/passwd | wc -m
1231
[root@zl_cloud ~]# cat /etc/passwd | wc -w
47
[root@zl_cloud ~]#
9.命令uniq
该命令用来删除重复的行。
- -c:表示统计重复的行数,并把行数写在前面。
[root@zl_cloud ~]# cat 1.txt
111
222
111
333
[root@zl_cloud ~]# sort 1.txt | uniq -c
2 111
1 222
1 333
[root@zl_cloud ~]#
10.命令tee
tee后面跟文件名,作用类似于重定向,但它比重定向多一个功能,即返回的时候会将内容显示出来。该命令通常用于管道符后。
[root@zl_cloud ~]# echo "aaaaaaa" | tee 1.txt
aaaaaaa
[root@zl_cloud ~]# cat 1.txt
aaaaaaa
[root@zl_cloud ~]#
11.命令tr
用来替换字符,常用来处理文档中出现的特殊符号。
- -d:表示删除某个字符,后面跟要删除的字符;
- -s:表示删除重复的字符。
把小写字母变成大写字母:
[root@zl_cloud ~]# head -2 /etc/passwd | tr '[a-z]' '[A-Z]'
ROOT:X:0:0:ROOT:/ROOT:/BIN/BASH
BIN:X:1:1:BIN:/BIN:/SBIN/NOLOGIN
[root@zl_cloud ~]#
替换字符:
[root@zl_cloud ~]# grep 'root' /etc/passwd | tr 'r' 'R'
Root:x:0:0:Root:/Root:/bin/bash
opeRatoR:x:11:0:opeRatoR:/Root:/sbin/nologin
[root@zl_cloud ~]#
12.命令split
该命令用于切割文档。
- -b:表示依据大小来分割文档,单位为byte;
[root@zl_cloud ~]# cd dira
[root@zl_cloud dira]# cp /etc/passwd ./
[root@zl_cloud dira]# split -b 500 passwd
[root@zl_cloud dira]# ls
passwd xaa xab xac
[root@zl_cloud dira]#
如果split不指定目标文件名,则会以xaa,xab…这样的文件名来存取切割后的文件,当然我们也可以指定目标文件名:
[root@zl_cloud dira]# rm -f xa* //先把前面的给删除了
[root@zl_cloud dira]# split -b 500 passwd 123
[root@zl_cloud dira]# ls
123aa 123ab 123ac passwd
[root@zl_cloud dira]#
- -l:表示依据行数来分割文档。
[root@zl_cloud dira]# rm -f 123a*
[root@zl_cloud dira]# split -l 10 passwd
[root@zl_cloud dira]# wc -l *
25 passwd
10 xaa
10 xab
5 xac
50 总用量
[root@zl_cloud dira]#
13.特殊符号$
[root@zl_cloud dira]# cd ..
[root@zl_cloud ~]# ls 1.txt
1.txt
[root@zl_cloud ~]# ls !$ //我个人理解就是!$代指上一个目录或者文件名
ls 1.txt
1.txt
[root@zl_cloud ~]#
14.特殊符号;
[root@zl_cloud ~]# mkdir testdir ; touch test1.txt ; ls -d test* //其实就是运行多个命令
test test1.txt testdir
[root@zl_cloud ~]#
15.特殊符号~
[root@zl_cloud ~]# cd ~ //~代表用户的家目录
[root@zl_cloud ~]# pwd
/root
[root@zl_cloud ~]# su zl
[zl@zl_cloud root]$ cd ~ //这是普通用户的家目录
[zl@zl_cloud ~]$ pwd
/home/zl
[zl@zl_cloud ~]$
16.特殊符号&
如果想把一条命令放在后台执行,则需要加上符号&
[root@zl_cloud ~]# sleep 30 & //30是代表时间间隔
[1] 25376
[root@zl_cloud ~]# jobs
[1]+ 运行中 sleep 30 &
[root@zl_cloud ~]#
17.重定向符号>、>>、2>和2>>
[root@zl_cloud ~]# ls aaa
ls: 无法访问aaa: 没有那个文件或目录
[root@zl_cloud ~]# ls aaa 2> /tmp/error //2>表示错误重定向
[root@zl_cloud ~]# cat /tmp/error
ls: 无法访问aaa: 没有那个文件或目录
[root@zl_cloud ~]# ls aaa 2>> /tmp/error //2>>表示错误追加重定向
[root@zl_cloud ~]# cat /tmp/error
ls: 无法访问aaa: 没有那个文件或目录
ls: 无法访问aaa: 没有那个文件或目录
[root@zl_cloud ~]#
18.中括号【】
中括号内为字符组合,代表字符组合中的任意一个,可以是一个范围:
[root@zl_cloud dirtest]# ls -d test*
test1.txt test2.txt testb.txt testdir
[root@zl_cloud dirtest]# ls -d test[1-3].txt //1-3这个范围
test1.txt test2.txt
[root@zl_cloud dirtest]# ls -d test[12b].txt //1,2,b任意一个
test1.txt test2.txt testb.txt
[root@zl_cloud dirtest]# ls -d test[1-9].txt //1-9这个范围
test1.txt test2.txt
[root@zl_cloud dirtest]# ls -d test[1-9a-z].txt //1-9,a-z这个范围
test1.txt test2.txt testb.txt
[root@zl_cloud dirtest]#
19.特殊符号&&和||
前面提到了分号可作为多条命令间的分隔符,其实这个两个也可以。
- ①command1 ; command2
不管command1是否执行成功,都会执行command2。 - ②command1 && command2
只有command1执行成功后,command2才会执行。
[root@zl_cloud dirtest]# ls
test1 test3
[root@zl_cloud dirtest]# ls test2 && touch test2
ls: 无法访问test2: 没有那个文件或目录
[root@zl_cloud dirtest]# ls test2
ls: 无法访问test2: 没有那个文件或目录
[root@zl_cloud dirtest]#
- ③command1 || command2
command1执行成功后则command2不执行,否则执行command2.即command1和command2中总有一条命令会执行。
[root@zl_cloud dirtest]# ls test2 || touch test2
ls: 无法访问test2: 没有那个文件或目录
[root@zl_cloud dirtest]# ls test*
test1 test2 test3
[root@zl_cloud dirtest]#