8.1shell介绍
shell是一个命令解释器,提供机器和用户的交互。
每个用户都可以有自己的shell,在/etc/passwd的最后一段显示了用户的shell。
CentOS7默认是bash(Bourne-Again SHell)。
还有zsh\ksh等各种shell。
shell还自带一些逻辑语句,例如循环,判断等。
[root@localhost ~]# yum list | grep 'zsh'
zsh.x86_64 5.0.2-28.el7 @base
autojump-zsh.noarch 22.3.0-3.el7 epel
zsh-html.x86_64 5.0.2-28.el7 base
zsh-lovers.noarch 0.9.0-1.el7 epel
[root@localhost ~]# yum list | grep 'ksh'
ksh.x86_64 20120801-137.el7 base
mksh.x86_64 46-8.el7 base
python-XStatic-Rickshaw.noarch 1.5.0.0-4.el7 epel
python-moksha-common.noarch 1.2.3-2.el7 epel
python-moksha-wsgi.noarch 1.2.2-2.el7 epel
python2-moksha-hub.noarch 1.5.6-1.el7 epel
其他的shell也可以通过yum安装,但是之后还是着重介绍bash。
8.2命令历史
我们运行过的命令其实是保存过的,我们可以通过上下方向键来查找之前用过的命令,这些命令保存在家目录下~/.bash_history文件
[root@localhost ~]# tail !$
tail ~/.bash_history
make
./configure --prefix=/usr/local/apache2
make
echo $?
make install
ls /usr/local/
ls /usr/local/apr
ls /usr/local/apr1.6/
ls /usr/local/apache2/
init 0
我们可以使用history命令来查看之前用过的命令。
[root@localhost ~]# history | tail
861 ls /usr/local/
862 ls /usr/local/apr
863 ls /usr/local/apr1.6/
864 ls /usr/local/apache2/
865 init 0
866 yum list | grep 'zsh'
867 yum list | grep 'ksh'
868 ls ~/.bash_history
869 tail ~/.bash_history
870 history | tail
可以看到目前只保存了870条命令,实际上history默认保留最近使用过的1000条命令。
有一个环境变量保存了history的最大保留数(写入~/.bash_history文件)。
[root@localhost ~]# echo $HISTSIZE
1000
history -c可以清空内存内的命令历史,但是不会清除~/.bash_history文件的命令。
当退出终端之后,内存中的命令就会保存到~/.bash_history文件中。
[root@localhost ~]# cat /etc/profile | grep -3 'HIST'
fi
HOSTNAME=`/usr/bin/hostname 2>/dev/null`
HISTSIZE=1000
if [ "$HISTCONTROL" = "ignorespace" ] ; then
export HISTCONTROL=ignoreboth
else
export HISTCONTROL=ignoredups
fi
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL
# By default, we want umask to get set. This sets it for login shell
# Current threshold for system reserved uid/gids is 200
这个默认的值可以在配置文件/etc/profile中更改。
重新赋值环境变量HISTTIMEFORMAT,可以做到保存命令的时间等信息。
HISTTIMEFORMAT="%Y/%m/%d %H:%M:%S "
[root@localhost ~]# HISTTIMEFORMAT="%Y/%m/%d %H:%M:%S "
[root@localhost ~]# history | tail
869 2018/06/29 09:52:56 tail ~/.bash_history
870 2018/06/29 09:55:54 history | tail
871 2018/06/29 09:57:36 echo $HISTSIZE
872 2018/06/29 10:00:14 cat /etc/profile | grep -A3'HIST'
873 2018/06/29 10:00:17 cat /etc/profile | grep -A3 'HIST'
874 2018/06/29 10:00:35 cat /etc/profile | grep -3 'HIST'
875 2018/06/29 10:03:19 HISTTIMEFORMAT="%Y/%m/%d %H:%M:%S"
876 2018/06/29 10:03:35 history | tail
877 2018/06/29 10:03:49 HISTTIMEFORMAT="%Y/%m/%d %H:%M:%S "
878 2018/06/29 10:03:51 history | tail
默认这个环境变量是不存在的,也可以保存在/etc/profile中,这样即使下次打开终端 也会保留这个格式。
当我们不想命令历史不被删除,永久保存,我们可以给命令历史配置文件追加一个a权限。
[root@localhost ~]# chattr +a ~/.bash_history
[root@localhost ~]# lsattr !$
lsattr ~/.bash_history
-----a---------- /root/.bash_history
##当终端意外被关闭时候,命令是不会被记录的。
在bash内,输入!!会执行最后一条被执行过的命令
[root@localhost ~]# !! lsattr ~/.bash_history -----a---------- /root/.bash_history
如果想运行某一个命令,!n执行第n条命令
[root@localhost ~]# history |tail 873 2018/06/29 10:00:17 cat /etc/profile | grep -A3 'HIST' 874 2018/06/29 10:00:35 cat /etc/profile | grep -3 'HIST' 875 2018/06/29 10:03:19 HISTTIMEFORMAT="%Y/%m/%d %H:%M:%S" 876 2018/06/29 10:03:35 history | tail 877 2018/06/29 10:03:49 HISTTIMEFORMAT="%Y/%m/%d %H:%M:%S " 878 2018/06/29 10:03:51 history | tail 879 2018/06/29 10:06:09 vim /etc/profile 880 2018/06/29 10:07:22 chattr +a ~/.bash_history 881 2018/06/29 10:07:29 lsattr ~/.bash_history 882 2018/06/29 10:11:23 history |tail [root@localhost ~]# !877 HISTTIMEFORMAT="%Y/%m/%d %H:%M:%S "
而!str会倒序寻找并执行第一条以str开头的命令
[root@localhost ~]# !lsa lsattr ~/.bash_history -----a---------- /root/.bash_history
8.3 命令补全和别名
tab键可以提供命令补全,文件路径补全等。
tab一次会补全到一个命令或者路径的相同的字符串,当tab按两次之后,会列出所有符合当前输入的所有的命令或者是路径。
[root@localhost ~]# yu
按一次tab之后
[root@localhost ~]# yum
按两次tab之后
[root@localhost ~]# yum
yum yum-complete-transaction yumdb yum-debug-restore yum-groups-manager
yum-builddep yum-config-manager yum-debug-dump yumdownloader
[root@localhost ~]# yum
yu开头的所有命令中,最开始相同的字符串是yum,所以一次tab会补全到yum,而yum开头的命令有很多,这时候两次tab就会列出所有yum开头的字符串了,如果命令太多,它会提示你时候全部列出。
[root@localhost ~]# l
Display all 102 possibilities? (y or n)
CentOS7之后提供了一个包bash-completion,它甚至可以使得tab补全命令的参数。
安装后需要重启生效。
[root@localhost ~]# systemctl re reboot reload reload-or-try-restart reset-failed reenable reload-or-restart rescue restart
alias别名命令可以让我们更方便的管理命令。
比如给命令systemctl restart network.service起一个方便的别名。
alias restartnet="systemctl restart network.service"
这样运行restartnet就可以执行命令systemctl restart network.service了。
[root@localhost ~]# 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'
如果想添加自己想要的别名,可以保存到家目录下的.bashrc文件中
[root@localhost ~]# cat ~/.bashrc | grep 'alias'
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
系统自定义的别名不仅仅在.bashrc中,在目录/etc/profile.d/下有很多定义的别名
[root@localhost ~]# find /etc/profile.d/ -type f | xargs grep 'alias'
/etc/profile.d/colorgrep.csh:alias grep 'grep --color=auto'
/etc/profile.d/colorgrep.csh:alias egrep 'egrep --color=auto'
/etc/profile.d/colorgrep.csh:alias fgrep 'fgrep --color=auto'
/etc/profile.d/colorgrep.sh:alias grep='grep --color=auto' 2>/dev/null
/etc/profile.d/colorgrep.sh:alias egrep='egrep --color=auto' 2>/dev/null
/etc/profile.d/colorgrep.sh:alias fgrep='fgrep --color=auto' 2>/dev/null
/etc/profile.d/which2.csh:# alias which 'alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
/etc/profile.d/which2.sh:alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
/etc/profile.d/colorls.csh:alias ll 'ls -l'
/etc/profile.d/colorls.csh:alias l. 'ls -d .*'
/etc/profile.d/colorls.csh:alias ll 'ls -l --color=auto'
/etc/profile.d/colorls.csh:alias l. 'ls -d .* --color=auto'
/etc/profile.d/colorls.csh:alias ls 'ls --color=auto'
/etc/profile.d/colorls.sh: alias ll='ls -l' 2>/dev/null
/etc/profile.d/colorls.sh: alias l.='ls -d .*' 2>/dev/null
/etc/profile.d/colorls.sh:alias ll='ls -l --color=auto' 2>/dev/null
/etc/profile.d/colorls.sh:alias l.='ls -d .* --color=auto' 2>/dev/null
/etc/profile.d/colorls.sh:alias ls='ls --color=auto' 2>/dev/null
/etc/profile.d/vim.csh: alias vi vim
/etc/profile.d/vim.sh: # for bash and zsh, only if no alias is already set
/etc/profile.d/vim.sh: alias vi >/dev/null 2>&1 || alias vi=vim
取消自定义的别名,使用unalias+command即可。
8.4通配符
之前使用名利的时候,参数用过*.txt的这种形式。
其实*就是一个通配符。
*表示的是任意长度的字符。
[root@localhost ~]# ls
1.txt 22.txt 2.txt 3.txt anaconda-ks.cfg xxx zsh-5.0.2-28.el7.x86_64.rpm
[root@localhost ~]# ls *.txt
1.txt 22.txt 2.txt 3.txt
[root@localhost ~]# ls *.t*
1.txt 22.txt 2.txt 3.txt
[root@localhost ~]# ls *.txt*
1.txt 22.txt 2.txt 3.txt
与之对应的是?通配符,它表示一个任意字符。
[root@localhost ~]# ls ?.txt
1.txt 2.txt 3.txt
[root@localhost ~]# ls ?.tx?
1.txt 2.txt 3.txt
[root@localhost ~]# ls ?.txt?
ls: cannot access ?.txt?: No such file or directory
[root@localhost ~]# ls ??.txt
22.txt
还有[]通配符,写在方括号内的,满足的都会匹配上。但是只匹配一个。
[root@localhost ~]# ls [0-9].txt
1.txt 2.txt 3.txt
[root@localhost ~]# ls [1-2].txt
1.txt 2.txt
[root@localhost ~]# ls 1.[a-z]xt
1.txt
[root@localhost ~]# ls [0-9a-zA-Z].[a-z]xt
1.txt 2.txt 3.txt
与之相对的是{}通配符,与list的用法类似,它匹配的也是一个。
[root@localhost ~]# ls {1..9}.txt
ls: cannot access 4.txt: No such file or directory
ls: cannot access 5.txt: No such file or directory
ls: cannot access 6.txt: No such file or directory
ls: cannot access 7.txt: No such file or directory
ls: cannot access 8.txt: No such file or directory
ls: cannot access 9.txt: No such file or directory
1.txt 2.txt 3.txt
[root@localhost ~]# ls {1,a}.txt
ls: cannot access a.txt: No such file or directory
1.txt
但是与[]不同的是,[]选一个,而{}选择所有的。[]不用分隔,而{}内的参数要用逗号隔开。
8.5输入输出重定向
>是输出重定向,表示把前面命令的输出输入到后面的文件(设备)中去。
[root@localhost ~]# ls 1.txt
1.txt
[root@localhost ~]# ls 1.txt > 2.txt
[root@localhost ~]# cat 2.txt
1.txt
以上就是从标准输出重定向到2.txt中。
>>是输出追加,它不会清除之前的数据,只是追加到文件(设备)的末尾。
[root@localhost ~]# cat 2.txt
1.txt
[root@localhost ~]# ls 3.txt > 2.txt
[root@localhost ~]# cat 2.txt
3.txt
[root@localhost ~]# ls 1.txt >> 2.txt
[root@localhost ~]# cat 2.txt
3.txt
1.txt
2>表示错误输出重定向,一个命令的错误信息会重定向到目标文件中。
[root@localhost ~]# ls 2/txt > 3.txt
ls: cannot access 2/txt: No such file or directory
[root@localhost ~]# cat 3.txt
[root@localhost ~]# ls 2/txt 2> 3.txt
[root@localhost ~]# cat 3.txt
ls: cannot access 2/txt: No such file or directory
同样2>>表示追加。
如果想要不管正确和错误的信息都要,使用&>
[root@localhost ~]# ls {1..4}.txt &> 2.txt
[root@localhost ~]# cat 2.txt
ls: cannot access 4.txt: No such file or directory
1.txt
2.txt
3.txt
当然不论是重定向正确还是错误信息,可以结合使用存到不同的文件
[root@localhost ~]# ls {1..4}.txt > 2.txt 2> 1.txt &> 3.txt
[root@localhost ~]# cat 1.txt
[root@localhost ~]# cat 2.txt
[root@localhost ~]# cat 3.txt
ls: cannot access 4.txt: No such file or directory
1.txt
2.txt
3.txt
[root@localhost ~]# ls {1..4}.txt > 2.txt 2> 1.txt
[root@localhost ~]# cat 1.txt
ls: cannot access 4.txt: No such file or directory
[root@localhost ~]# cat 2.txt
1.txt
2.txt
3.txt
但是注意,使用了多个重定向,会让之前的重定向失效,只生效最后一个。
最后,<表示输入重定向。
[root@localhost ~]# cat 2.txt
1.txt
2.txt
3.txt
[root@localhost ~]# wc -l < 2.txt
3