8.1 shell介绍
8.2 命令历史
8.3 命令补全和别名
8.4 通配符
8.5 输入输出重定向
8.6 管道符和作业控制
8.7/8.8 shell变量
8.9 环境变量配置文件
8.10 shell特殊符号cut命令
8.11 sort_wc_uniq命令
8.12 tee_tr_split命令
8.13 shell特殊符号下
8.14扩展:bashrc和bash_profile的区别
8.1 shell介绍
8.2 命令历史
命令存放路径:/用户家目录下/.bash_hsitory
#只有用户退出总终端的时候才会将命令缓存保存到文件里
#默认最大存储1000条命令
系统内置环境变量HISTSIZE
echo $HISTSIZE #查看HISTSIZE大小
[root@localhost ~]# echo $HISTSIZE
1000
修改HISTSIZE的配置文件:/etc/profile
#修改过后不会立刻生效,要重登终端或者source /etc/profile
history #查看使用过的命令
histtory -c #清空使用过命令的缓存(删除不了.bash_hsitory内的命令)
将查看命令历史设置使用时间
HISTTIMEFORMAT="%Y/%m/%d %H:%M:%S"
#Y/m/d 年/月/日; H:M:S 时:分:秒 (仅在当前终端生效)
#要想永久在所以终端都生效,将该命令写进/etc/profile文件里面
#将命令历史永久保存,/用户家目录下/.bash_history添加a权限
chattr +a /用户家目录下/.bash_history
注意:如果终端没有正常退出,重登的时候会发现历史命令保存的不全
!! #执行上一条命令
[root@localhost ~]# ls
2.txt 3.txt anaconda-ks.cfg asda.txt
[root@localhost ~]# !!
ls
2.txt 3.txt anaconda-ks.cfg asda.txt
!n #n是命令历史的排序号
1026 2018/08/12 19:37:25vim /etc/profile
1027 2018/08/12 19:38:43ls
1028 2018/08/12 19:39:26history
[root@localhost ~]# !1027
ls
2.txt 3.txt anaconda-ks.cfg asda.txt
!word #或者最近使用一次命令的开头
8.3 命令补全和别名
#参数补全,需要安装bash-completion包
Tab键按一次,补全命令和参数
Tab键按两次,显示支持补全的参数
配置别名的文件路径存放:/用户家目录下/.bashrc
其它自定义别名存放:/etc/profile.d
8.4 通配符
"^" # 以什么开头 例: ^[a-z] ,表示以小写字母a-z开头的
"#" # 注释
"\" #转义字符,将特殊字符或通配符还原成一般字符
";" #命令衔接符,连续执行两条命令
"$" # 取用变量符号
"&" #工作控制,将指令变成后台运行工作
" '' " #单引号,无法引用变量
" "" " #双引号,可以引用变量
" `` " #反引号,表示指令引用,功能同 $(command)
" * " #表示通配所有字符
" ? " #表示通配一个字符
" [ ] " #可写数字,字母,范围;括号内字符都是或者的关系
" + " #前面字符至少出现一次才会过滤出来,+是特殊字符
" { } " #可写数字,字母;括号内字符都是或者的关系,但是中间需要用逗号“,”隔开
例 : echo=`pwd`
[root@xinlinux-02 ~]# echo `pwd`
/root
"2>&1" #表示正确和错误的都输出
例:ls 1.txt 2.txt 2>&1 >>3.txt #ls 1.txt 和2.txt,将正确和错误的信息都追加到3.txt
* #表示通配所有字符
? #表示通配一个字符
[root@localhost ~]# ls *.txt
1.txt 2.txt 3.txt aa.txt asda.txt a.txt bbb.txt b.txt c.txt
[root@localhost ~]# ls ?.txt
1.txt 2.txt 3.txt a.txt b.txt c.txt
#"+"号表示前面字符至少出现一次才会过滤出来,这里+是特殊字符,所以用到egrep
[root@localhost ~]# egrep "\[+" 1.txt
[1234]
[124
[ ] #可写数字,字母,范围;括号内字符都是或者的关系
[root@localhost ~]# ls [123].txt
1.txt 2.txt 3.txt
[root@localhost ~]# ls [0-2].txt
1.txt 2.txt
[root@localhost ~]# ls [a-z].txt
a.txt b.txt c.txt
[root@localhost ~]# ls [1-3a-c].txt
1.txt 2.txt 3.txt a.txt b.txt c.txt
[root@localhost ~]# ls [1-3a-cA-Z].txt
1.txt 2.txt 3.txt a.txt b.txt c.txt
{ } #可写数字,字母;括号内字符都是或者的关系,但是中间需要用逗号“,”隔开
[root@localhost ~]# ls {1,2}.txt
1.txt 2.txt
[root@localhost ~]# ls {1-2}.txt
ls: 无法访问{1-2}.txt: 没有那个文件或目录
[root@localhost ~]# ls {1,2,3,a,}.txt
1.txt 2.txt 3.txt a.txt
"\" 表示脱义字符,将特殊字符的语意去掉
[root@localhost ~]# grep "[" 1.txt #"["中括号为特殊字符,双引号识别不了,所以报错
grep: 无效的常规表达式
[root@localhost ~]# grep "\[" 1.txt #用\号脱义,就可以成功
[1234]
[124
8.5 输入输出重定向
1、输出“>”
cat 1.txt > 2.txt # 重定向,将1.txt内容删掉再重新写入2.txt的内容
cat 1.txt >> 2.txt #追加,将2.txt内容追加到1.txt的结尾处的下一行
lsaaa 2> 2.txt #错误重定向,ls命令产生的错误信息重定向到2.txt
lsaaa 2>> 2.txt #错误追加重定向,ls命令产生的错误信息追加到2.txt
>+2> == &> #即&>是重定向和错误重定向的结合
例:
1、ls [12].txt abc.txt &> 3.txt
[root@localhost ~]# ls [12].txt abc.txt &> 3.txt
[root@localhost ~]# cat 3.txt
ls: 无法访问abc.txt: 没有那个文件或目录
1.txt
2.txt
2、ls [12].txt abc.txt >3.txt 2>a.txt
[root@localhost ~]# ls [12].txt abc.txt >3.txt 2>a.txt
[root@localhost ~]# cat 3.txt
1.txt
2.txt
[root@localhost ~]# cat a.txt
ls: 无法访问abc.txt: 没有那个文件或目录
2、输入“<”
wc -l < 1.txt #输入重定向,将1.txt的内容输入重定向到wc -l
[root@localhost ~]# wc -l < 3.txt
2
[root@localhost ~]# 2.txt < 3.txt
-bash: 2.txt: 未找到命令
ps:左边只能是命令
command >1.txt 2>&1
#&1 表示标准正确输出目标。因为前面已经定义了 >1.txt 标准正确输出到了1.txt,所以&1就是1.txt
例子:cat > qq << EOF
#cat的同时往qq里面覆盖内容写入
>
>
>EOF #最后输入EOF就会结束
cat >> qq << EOF
#cat的同时往qq里面追加内容写入
巧用垃圾桶
Linux 下有一个特殊的设备 /dev/null ,所有被写入该设备的东西都会消失,所以如果有部分信息不想输出至文件,也不想输出至屏幕,那就输出至 /dev/null 吧
8.6 管道符和作业控制
cat 1.txt |wc -l #|管道符,把前面命令的结果交给后面命令执行
cat 1.txt |grep 'aaa'
#Ctrl z 暂停一个任务
jobs #查看后台任务
fg [ id] #把任务调到前台 , 不加id默认最后一次暂停的命令
bg[ id] #把任务调到后台运行,不加id默认最后一次暂停的命令
命令后面加&直接丢到后台运行
例:sleep 100 &
[root@localhost ~]# sleep 100 &
[4] 3384
[root@localhost ~]# ls
1.txt 3.txt anaconda-ks.cfg a.txt b.txt
2.txt aa.txt asda.txt bbb.txt c.txt
[root@localhost ~]# jobs
[2]+ 已停止 sleep 100
[3]- 已停止 sleep 1000
[4] 运行中 sleep 100 &
vmstat 1 #显示实时的系统状态
sleep 1000 #系统睡眠1000s
杀死进程两种方式
1、kill [signal] [进程ID]
常用signal
-
-1: 重新读取参数的配置文件(类似 reload)
-
-9: 立即强制删除一个任务
-
-15: 已正常方式结束一个任务
2、pkill 进程名
8.7/8.8 shell变量
env命令 #查看系统内置变量
set命令 #查看系统内置变量 及用户自定义的变量
自定义变量a=1111
set |grep a=1111 #通过管道符,set过滤找到a=1111的变量
[root@localhost ~]# set |grep a=1111
a=1111
1、变量名规则:首位可以字母、数字下划线,首位不能为数字
2、变量值有特殊符号时需要用单引号括起来
注意-1:如果变量值中存在空格,需要用单引号或双引号将变量值括起来
注意-2:如果变量值中有引用其他变量,需要用双引号将变量值括起来
ps:" _ "下划线是特殊字符,如果要加入变量名,输出只会将下划线后面接着的变量显示出来;下划线前面的变量会显示不出来
例:for i in `seq 1 10`;do echo "lv_$i";done
#通过for循环echo显示lv级别,
[root@localhost ~]# for i in `seq 1 10`;do echo "lv_$i";done
lv_1
lv_2
lv_3
lv_4
lv_5
lv_6
lv_7
lv_8
lv_9
lv_10
将lv定义为变量lvname的值,然后执行命令显示不出来
[root@localhost ~]# lvname=lv;for i in `seq 1 5`;do echo "$lvname_$i";done
1
2
3
4
5
将"_"下划线换成"-"横杠,变量lvname就能显示出来
[root@localhost ~]# lvname=lv;for i in `seq 1 5`;do echo "$lvname-$i";done
lv-1
lv-2
lv-3
lv-4
lv-5
3、变量的累加
[root@localhost ~]# a=1
[root@localhost ~]# b=2
[root@localhost ~]# echo $a
1
[root@localhost ~]# echo $ab
[root@localhost ~]# echo $a$b
12
[root@localhost ~]# echo a$bc
a
[root@localhost ~]# echo 'a$b'c
a$bc
[root@localhost ~]# echo "a$b"c
a2c
[root@localhost ~]# echo a"$b"c
a2c
ps:设置的变量仅在当前shell窗口bash下有效(本地变量,非全局变量)
bash #创建子shell窗口
pstree #查看当前shell所在窗口
4、全局变量export (针对当前终端)
#全局变量只是向下全局子shell,下一层的子shell定义的全局变量不会再上层显示
语法:export 变量
[root@choco-01 ~]# echo $full
Choco Lee @ China
[root@choco-01 ~]# bash
[root@choco-01 ~]# echo $full # 进入子 shell 后, 变量失效
[root@choco-01 ~]# exit
exit
[root@choco-01 ~]# export full # 声明该变量为环境变量
[root@choco-01 ~]# bash
[root@choco-01 ~]# echo $full # 进入子 shell 后, 变量仍让有效
Choco Lee @ China
5、unset 变量名 #取消掉定义的变量
常用环境变量
-
HOME: 当前用户的家目录
-
HOSTNAME: 该主机的主机名
-
USER: 当前用户的用户名
-
SHELL: 当前使用的 shell 类型
-
HISTSIZE: 可存储的历史命令条数
-
MAIL: 当前用户的邮箱
-
PATH: 可执行命令的所在目录
-
LANG: 当前语系
-
PS1: 命令提示符的格式, 可玩性较高, 但工作中不常用, 可自行 man bash 查看 PS1 的设置方法
-
PS2: 输入命令时强制换行后的提示符
-
OSTYPE: 当前操作系统类型
-
MACHTYPE: 安装的机器类型
-
HOSTTYPE: 主机的位数, x86 还是 x86_64
8.9 环境变量配置文件
启动加载文件顺序: (需要掌握)
系统层次:
/etc/profile 用户环境变量,交互,登录才执行 #用户登录时会加载到
/etc/bashrc用户不用登录,执行shell就生效 #系统执行shell时用到
用户层次:
/用户家目录/.bashrc #写用户自定义别名
/用户家目录/.bash_profile #写用户自定义变量
/用户家目录/.bash_history #用户存放历史
/用户家目录/.bash_logout #定义用户退出时需要做的操作
source 环境变量配置文件
# 修改环境变量配置文件后,必须注销重新登录才能生效,使用source 命令可以不用重新登录
source .bash_profile == . .bash_profile
[root@localhost ~]# source .bash_profile
[root@localhost ~]# . .bash_profile
/etc/bashrc
PS1=[\u@\h \W]$ (面试中可能会问到,平时不用掌握)
PS1的常用参数以及含义:
\d :代表日期,格式为weekday month date,例如:"Mon Aug 1"
\H :完整的主机名称
\h :仅取主机名中的第一个名字
\t :显示时间为24小时格式,如:HH:MM:SS
\T :显示时间为12小时格式
\A :显示时间为24小时格式:HH:MM
\u :当前用户的账号名称
\v :BASH的版本信息
\w :完整的工作目录名称
\W :利用basename取得工作目录名称,只显示最后一个目录名
\# :下达的第几个命令
\$ :提示字符,如果是root用户,提示符为 # ,普通用
PS1="[\u@\h \W]\\$ " #就是[root@localhost ~]#这种
改W为w,可以显示为绝对路径
[root@localhost ~]# echo $PS1
[\u@\h \W]\$
[root@localhost ~]#PS1='[\u@\h \w]\$'
[root@localhost ~]#cd /etc/yum.repos.d
[root@localhost /etc/yum.repos.d]#
PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;36m\]\w\[\033[00m\]\$' #改字体颜色
设定环境变量
-
PATH:根据 UID 决定PATH 变量是否要包含 sbin 目录
-
USER:根据 id 命令的结果,显示用户名
-
LOGNAME:等于 USER
-
MAIL:配置好用户的邮箱
-
HOSTNAME:根据 hostname 指令,决定该变量值
-
HISTSIZE:直接设定历史命令记录的条数为 1000
8.10 shell特殊符号cut命令
特殊符号
\ #脱义字符,将特殊字符或通配符还原成一般字符
[root@localhost ~]# a=1
[root@localhost ~]# b=2
[root@localhost ~]# echo $a
1
[root@localhost ~]# echo $b
2
[root@localhost ~]# c=$a$b
[root@localhost ~]# echo $a$b
12
[root@localhost ~]# echo '$a$b'
$a$b
[root@localhost ~]# echo \$a\$b
$a$b
| #将管道符前面内容的输出结果让后面命令执行
[root@localhost ~]# cat 1.txt |wc -l
1
几个跟管道符有关的命令
注意###cat、head、sort、uniq、grep不会对文件内容进行更改####
cut分割,-d 分隔符 -f 指定段号(例: 1; 1,2; 1-3) -c 指定第几个字符(如果使用-c时,不能同时使用-d,-f)
例:cat /etc/passwd |head -2 |cut -d ":" -f 1-3
# |head -2 表示截取etc/passwd开头前两段内容
[root@localhost ~]# cat /etc/passwd |head -2 |cut -d ":" -f 1-3
root:x:0
bin:x:1
[root@localhost ~]# cat /etc/passwd |head -2 |cut -d ":" -f 1,2
root:x
bin:x
[root@localhost ~]# cat /etc/passwd |head -2 |cut -d ":" -f 1-3 -c 1
cut: 只能指定列表中的一种类型
Try 'cut --help' for more information.
[root@localhost ~]# cat /etc/passwd |head -2 |cut -c 1
r
b
8.11 sort_wc_uniq命令
#sort默认按照ASCII排序
#sort之前要先source 文件,防止里面有一些命令对文件赵成影响(例如里面有rm命令,会删除)
1、sort排序,
-n 以数字排序(字母会认为是0,排在最前面)(默认从小到大)
[root@localhost ~]# sort -n 3.txt
>
;
ahsflhg;a
1.txt
2.txt
1234
2345
2345
24324234
-r 反序 (从大到小)
[root@localhost ~]# sort -n -r 3.txt
24324234
2345
2345
1234
2.txt
1.txt
ahsflhg;a
;
>
-t分隔符
-k(按照第几列进行排序)
[root@localhost ~]# cat 2.txt
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
[root@localhost ~]# sort -t ":" -k 1 2.txt
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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
root:x:0:0:root:/root:/bin/bash
2、wc -l 统计行数 -m 统计字符数 -w 统计词 -c(统计字节数)
[root@localhost ~]# wc -l 2.txt
5 2.txt
[root@localhost ~]# wc -m 2.txt
183 2.txt
3、uniq 去重, -c 统计行数
8.12 tee_tr_split命令
1、tee和>类似,重定向的同时还在屏幕显示
例: sort 2.txt |uniq -c |tee 1.txt #排序2.txt的结果进行去重uniq,然后结果tee到1.txt,会显示到屏幕上
[root@localhost ~]# sort 2.txt |uniq -c |tee 1.txt
3 123
1 123214
2 234
2 444
1 555
1 6543
2、tr 替换字符,tr 'a' 'b',大小写替换tr'[a-z]' '[A-Z]'
#只能针对字符串,不能单独使用
[root@localhost ~]# cat 2.txt |tr '2' 'a'
1a3a14
1a3
1a3
a34
a34
555
444
6543
444
1a3
3、split 切割,-b 大小(默认单位字节 ),-l 行数
#对大文件进行切割,均分为指定大小或者行数的小文件
例:
[root@localhost xin]#
[root@localhost xin]# split -l 500 2.txt
[root@localhost xin]# ll
总用量 28
-rw-r--r--. 1 root root 8525 8月 17 21:45 2.txt
-rw-r--r--. 1 root root 2618 8月 17 21:50 xaa
-rw-r--r--. 1 root root 2055 8月 17 21:50 xab
-rw-r--r--. 1 root root 2056 8月 17 21:50 xac
-rw-r--r--. 1 root root 1796 8月 17 21:50 xad
切割后文件命名可以自定义,在文件后面加上自定义命名即可
split -l 500 2.txt abc
[root@localhost xin]# split -l 500 2.txt abc
[root@localhost xin]# ll
总用量 28
-rw-r--r--. 1 root root 8525 8月 17 21:45 2.txt
-rw-r--r--. 1 root root 2618 8月 17 21:52 abcaa
-rw-r--r--. 1 root root 2055 8月 17 21:52 abcab
-rw-r--r--. 1 root root 2056 8月 17 21:52 abcac
-rw-r--r--. 1 root root 1796 8月 17 21:52 abcad
8.13 shell特殊符号下
$变量前缀,!$组合,正则里面表示行尾
~用户家目录,正则表达式表示匹配符
;多条命令写到一行,用分号分割
[root@localhost ~]# ls 1.txt; wc -l 3.txt
1.txt
16 3.txt
&放到命令后面,会把命令丢到后台运行
[root@localhost ~]# sleep 100 &
[1] 1471
[root@localhost ~]# jobs
[1]+ 运行中 sleep 100 &
[ ]指定字符中的一个,[0-9],[a-zA-Z],[abc]
[root@localhost ~]# ls [1-9].txt
1.txt 3.txt
[root@localhost ~]# ls [a-z].txt
a.txt b.txt c.txt
|| 和&&,用于命令之间
ll是表示或者,第一条命令执行成功,第二条命令便不执行;若第一条命令执行失败,第二条命令便会执行
[root@localhost ~]# ls 1.txt || ls 5.txt
1.txt
[root@localhost ~]# ls 5.txt || wc -l 1.txt
ls: 无法访问5.txt: 没有那个文件或目录
6 1.txt
&&表示且,只有第一条命令执行成功才会执行第二条命令
[root@localhost ~]# ls 1.txt && ls 5.txt
1.txt
ls: 无法访问5.txt: 没有那个文件或目录
[root@localhost ~]# ls 5.txt && wc -l 1.txt
ls: 无法访问5.txt: 没有那个文件或目录
| 与 || &与&& (面试可能问到)
1、| 与 || 的区别
| 管道符,用于将上条命令的结果作为第二条命令执行的参数
|| (又称短路或)表示上条命令执行失败后才会执行第二条命令
2、&与&&的区别
& 不管第一条命令执行是否成功,都执行第二条命令
&& (短路与) 第一条命如果执行失败,则不执行第二条命令
8.14扩展:bashrc和bash_profile的区别
【.bash_profile 与 .bashrc 的区别】
.bash_profile is executed for login shells, while .bashrc is executed for interactive non-login shells.
【login shell 与 non-login shell 的区别】
1、当你直接在机器login界面登陆、使用ssh登陆或者su切换用户登陆时,.bash_profile 会被调用来初始化shell环境
Note:.bash_profile文件默认调用.bashrc文件
.bash_profile中有如下内容
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
2、当你不登陆系统而使用ssh直接在远端执行命令,.bashrc 会被调用
3、当你已经登陆系统后,每打开一个新的Terminal时,.bashrc 都会被再次调用。
测试准备工作
hclient2主机hadoop用户家目录下执行
[hadoop@hclient2 ~]$ echo "invoke hclient2:~/.bashrc">>.bashrc
[hadoop@hclient2 ~]$ echo "invoke hclient2:~/.bash_profile">>.bash_profile
Login Shell
1、窗口登陆
Red Hat Enterprise Linux Server release 6.3 (Santiago)
Kernel 2.6.32-279.el6.x86_64 on an x86_64
hclient2 login: hadoop
Password:
Last login: Mon Feb 25 23:03:45 on tty1
invoke hclient2:~/.bashrc
invoke hclient2:~/.bash_profile
[hadoop@hclient2 ~]$
2、SSH 登陆
[hadoop@hserver ~]$ ssh hclient2
Last login: Mon Feb 25 22:42:19 2013 from hserver
invoke hclient2:~/.bashrc
invoke hclient2:~/.bash_profile
[hadoop@hclient2 ~]$
3、su 登陆
[root@hclient2 ~]# su - hadoop
invoke hclient2:~/.bashrc
invoke hclient2:~/.bash_profile
Non-login Shell:
Note: ssh ...[user@] hostname [command]
If command is specified, it is executed on the remote host instead of a login shell.
[hadoop@hserver ~]$ ssh hclient2 hostname
invoke hclient2:~/.bashrc
hclient2
所以,若要配置环境变量之类,最保险是写在 .bashrc 文件中。因为不管是登陆还是不登陆,该文件总会被调用!