0. 总结
-
由于核心在内存中是受保护的区块,因此我们必须要通过“ Shell ”将我们输入的指令与 Kernel 沟通,好让 Kernel 可以控制硬件来正确无误的工作
-
学习 shell 的原因主要有:命令行的 shell 在各大 distribution 都一样;远端管理时命令行 速度较快; shell 是管理 Linux 系统非常重要的一环,因为 Linux 内很多控制都是以 shell 撰写的。
-
系统合法的 shell 均写在 /etc/shells 文件中;
-
使用者默认登陆取得的 shell 记录于
/etc/passwd
的最后一个字段; -
bash
的功能主要有:命令编修能力;命令与文件补全功能;命令别名设置功能;工作控 制、前景背景控制;程序化脚本;万用字符 -
type
可以用来找到执行指令为何种类型,亦可用于与which
相同的功能; -
变量就是以一组文字或符号等,来取代一些设置或者是一串保留的数据
-
变量主要有环境变量与自订变量,或称为全域变量与区域变量
-
使用
env
与export
可观察环境变量,其中export
可以将自订变量转成环境变量; -
set
可以观察目前 bash 环境下的所有变量; -
$?
亦为变量,是前一个指令执行完毕后的回传值。在 Linux 回传值为 0 代表执行成功; -
locale
可用于观察语系数据; -
可用
read
让使用者由键盘输入变量的值 -
ulimit
可用以限制使用者使用系统的资源情况 bash 的配置文件主要分为 login shell 与 non-login shell。login shell 主要读取 /etc/profile 与 ~/.bash_profile, non-login shell 则仅读取 ~/.bashrc -
在使用 vim 时,若不小心按了
[crtl]+s
则画面会被冻结。你可以使用[ctrl]+q
来解除冻结 -
万用字符主要有:
*
,?
,[]
等等 -
数据流重导向通过
>
,2>
,<
之类的符号将输出的信息转到其他文件或设备去; -
连续命令的下达可通过
;
&&
||
等符号来处理 -
管线命令的重点是:“管线命令仅会处理 standard output,对于 standard error output 会予以忽略”
-“管线命令必须要能够接受来自前一个指令的数据成为 standard input 继续处理 才行。”
- 本章介绍的管线命令主要有:
cut
,grep
,sort
,wc
,uniq
,tee
,tr
,col
,join
,paste
,expand
,split
,xargs
等。
1. 认识BASH
狭义的壳程序指的是命令行方面的软件,包括本章要介绍的bash等,基于命令行的shell不好学,有很多命令行要记,但是学好了shell好处多多:
-
linux有不同的发行版本,不同的发行版本其图形接口可能不同,但是其命令行的shell是一样的。
-
更方便的远程管理,命令行比较快。
-
shell能将日常的工作作成script,达到作业自动化。
由于各种历史原因,存在多个不同的shell,如下以centos为例:
- /bin/sh (已经被 /bin/bash 所取代)
- /bin/bash (就是 Linux 默认的 shell)
- /bin/tcsh (整合 C Shell ,提供更多的功能)
- /bin/csh (已经被 /bin/tcsh 所取代)
其中bash是linux发行版中的标准shell,bash主要的优点如下:
- 命令记录能力(history),历史命令保存在
~/.bash_history
中 - 命令名与文件名的补全功能(tab)
- 命令别名设置功能(alias),比如某个常用命令比较长的话,可以
alias lm='ls -al'
,用lm来取代 - 程序化脚本化(shell scripts)
- 通配符(wildcard),想知道 /usr/bin 下面有多少以 X 为开头的文件吗?使用:
ls -l /usr/bin/X*
就能够知道
1.1. 查询指令是否为 Bash shell 的内置命令: type
通过 type 这个指令我们可以知道每个指令是否为 bash 的内置指令。 此外,由于利用 type 搜 寻后面的名称时,如果后面接的名称并不能以可执行文件的状态被找到, 那么该名称是不会 被显示出来的。也就是说, type 主要在找出“可执行文件”而不是一般文件文件名喔! 呵呵! 所以,这个 type 也可以用来作为类似 which 指令的用途啦!找指令用的!
[root@CMDBServerDev04 ~]# type ls
ls は `ls --color=auto' のエイリアスです
[root@CMDBServerDev04 ~]# type cd
cd はシェル組み込み関数です
# 使用tab列举出所有ls开头的命令
[root@CMDBServerDev04 ~]# type ls
ls lsb_release lscpu lslocks lsmod lspci
lsattr lsblk lsinitrd lslogins lsof lsscsi
1.2. 指令的下达与快速编辑按钮
- 如果一串命令很长,无法在一行内输入,可以使用
\
进行跳转,紧接后面的按下的enter就没有执行功能,能在后面继续输入命令
[root@CMDBServerDev04 lijuntest]# cp 1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt \
> 8.txt 9.txt myfolder
[root@CMDBServerDev04 lijuntest]# cd myfolder/
[root@CMDBServerDev04 myfolder]# ls
1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt
- 快速编辑命令
组合键 | 功能 | 组合键 | 功能 |
---|---|---|---|
[ctrl]+u | 从光标处向前删除指令串 | [ctrl]+k | 向后删除指令串 |
[ctrl]+a | 将光标移动到指令串最前面 | [ctrl]+e | 移动到指令串最后面 |
2. Shell的变量功能
2.1 影响 bash 环境操作的变量
例如你下达 ls 这个指令时,系统就是通过 PATH 这个变量里面的内容所记录的路径顺序来搜寻指令的! 如果在搜寻完 PATH 变量内的路径还找不到 ls 这个指令时, 就会在屏幕上显示“ command not found ”。 为了区分与自订变量的不同,环境变量通常都用大写字母表示,常见的环境变量如下:
[root@CMDBServerDev04 ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@CMDBServerDev04 ~]# echo $HOME
/root
[root@CMDBServerDev04 ~]# echo $MAIL
/var/spool/mail/root
[root@CMDBServerDev04 ~]# echo $SHELL
/bin/bash
2.2 变量的取用与设置: echo,变量设置规则,unset
- 变量的设置与打印
# 当前没有设置该变量,故为空
[root@CMDBServerDev04 ~]# echo ${myname}
# 变量设置
[root@CMDBServerDev04 ~]# myname="lijun"
[root@CMDBServerDev04 ~]# echo ${myname}
lijun
# 打印上面设置的变量
[root@CMDBServerDev04 ~]# echo $myname
lijun
- 双引号与单引号
单引号内部的字符直接输出,双引号内部如果有$
,可以输出其变量
[root@CMDBServerDev04 ~]# var="lang is $LANG"
[root@CMDBServerDev04 ~]# echo $var
lang is ja_JP.UTF-8
[root@CMDBServerDev04 ~]# var='lang is $LANG'
[root@CMDBServerDev04 ~]# echo $var
lang is $LANG
- 在一串指令的执行中,还需要借由其他额外的指令所提供的信息时,可以使用反单引号```,如:
[root@CMDBServerDev04 ~]# myhost=hostname
[root@CMDBServerDev04 ~]# echo $myhost
hostname
# 下面的命令,与上面的等效
[root@CMDBServerDev04 ~]# echo `hostname`
CMDBServerDev04
# 示例2,进入对应的kernel
[root@CMDBServerDev04 ~]# cd /lib/modules/`uname -r`/kernel
[root@CMDBServerDev04 kernel]# cd ~
[root@CMDBServerDev04 ~]# cd /lib/modules/$(uname -r)/kernel
[root@CMDBServerDev04 kernel]# cd ~
[root@CMDBServerDev04 ~]# version=`uname -r`
[root@CMDBServerDev04 ~]# echo $version
3.10.0-327.el7.x86_64
- 变量的扩增
[root@CMDBServerDev04 ~]# comman_phrase="JP"
# 后续接需要连接的字符串
[root@CMDBServerDev04 ~]# my_phrase=$comman_phrase"_amazon"
[root@CMDBServerDev04 ~]# echo $my_phrase
JP_amazon
# 示例2
[root@CMDBServerDev04 ~]# name="li-"
[root@CMDBServerDev04 ~]# myname=${name}"utasuke"
[root@CMDBServerDev04 ~]# echo $myname
li-utasuke
- 取消变量使用
unset
,如:
[root@CMDBServerDev04 ~]# myname="lijun"
[root@CMDBServerDev04 ~]# echo $myname
lijun
[root@CMDBServerDev04 ~]# unset myname
[root@CMDBServerDev04 ~]# echo $myname
- 使用export进行变量导出,使得可以在子程序中使用
[root@CMDBServerDev04 ~]# name="li-"
# 进入子程序
[root@CMDBServerDev04 ~]# bash
# 没有设置export,故在子程序中无法输出name
[root@CMDBServerDev04 ~]# echo $name
# 退出子程序
[root@CMDBServerDev04 ~]# exit
exit
# 导出变量name
[root@CMDBServerDev04 ~]# export name
# 再次进入子程序
[root@CMDBServerDev04 ~]# bash
# 可以输出变量name
[root@CMDBServerDev04 ~]# echo $name
li-
[root@CMDBServerDev04 ~]# exit
exit
2.3 环境变量的功能
[root@CMDBServerDev04 lijuntest]# env
...
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root/lijuntest
LANG=ja_JP.UTF-8
HOME=/root
...
[root@CMDBServerDev04 lijuntest]# cd $HOME
[root@CMDBServerDev04 ~]#
# 通过export也可以得到类似的结果
[root@CMDBServerDev04 ~]# export
...
declare -x HOME="/root"
declare -x HOSTNAME="CMDBServerDev04"
...
2.4 变量键盘读取read,阵列array,宣告declare
- 键盘读取
# 接收输入,将输入存储到myread变量
[root@CMDBServerDev04 ~]# read myread
hello,world!
# 打印出myread变量
[root@CMDBServerDev04 ~]# echo $myread
hello,world!
# 提示接收输入,并设置最长时间为30秒
[root@CMDBServerDev04 ~]# read -p "Please enter your name:" -t 30 myname
Please enter your name:lijun
# 打印出myname变量
[root@CMDBServerDev04 ~]# echo ${myname}
lijun
- 宣告变量类型 declare / typeset
# 默认是字符串类型
[root@CMDBServerDev04 ~]# sum=100+200+300
[root@CMDBServerDev04 ~]# echo $sum
100+200+300
# 显式指定为整型
[root@CMDBServerDev04 ~]# declare -i sum=100+200+300
[root@CMDBServerDev04 ~]# echo $sum
600
# 将sum设置为环境变量
[root@CMDBServerDev04 ~]# declare -x sum
# 输出环境变量sum
[root@CMDBServerDev04 ~]# export | grep sum
declare -ix sum="600"
# 将sum设置为只读
[root@CMDBServerDev04 ~]# declare -r sum
# 试图修改sum会出错
[root@CMDBServerDev04 ~]# sum="wanttochange"
-bash: sum: readonly variable
# 将sum设置为非环境变量的自订变量
[root@CMDBServerDev04 ~]# declare +x sum
# 环境变量中找不到sum了
[root@CMDBServerDev04 ~]# export | grep sum
[root@CMDBServerDev04 ~]# declare -p sum
declare -ir sum="600"
- 阵列array变量类型
[root@CMDBServerDev04 ~]# var[0]=0
[root@CMDBServerDev04 ~]# var[1]=1
[root@CMDBServerDev04 ~]# var[2]=2
[root@CMDBServerDev04 ~]# echo "${var[0]},${var[1]},${var[2]}"
0,1,2
2.5 ulimit 文件系统与程序的限制
# 列出当前用户的资源限制列表,0表示没有限制
[root@CMDBServerDev04 ~]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
...
# 限制用户只能创建10M以下的文件
[root@CMDBServerDev04 ~]# ulimit -f 10240
# 再次列出当前用户的资源限制列表
[root@CMDBServerDev04 ~]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) 10240
...
# 创建文件,最后显示超出大小限制
[root@CMDBServerDev04 ~]# dd if=/dev/zero of=123 bs=1M count=20
File size limit exceeded
# 下面是创建的文件,这里是byte为单位,实际是10240KB
[root@CMDBServerDev04 ~]# ls -al | grep 123
-rw-r--r-- 1 root root 10485760 Feb 9 12:43 123
如果要复原ulimit的size,重新登录系统即可。
3. 命令别名与历史命令
3.1 命令别名设置 alias unalias
# 为了防止误删除,将删除默认带上确认提示
[root@CMDBServerDev04 ~]# alias rm="rm -i"
[root@CMDBServerDev04 ~]# rm 123
rm: remove regular file ‘123’? n
# 取消rm的重命名
[root@CMDBServerDev04 ~]# unalias rm
[root@CMDBServerDev04 ~]# rm 123
# 有时命令过长,用一个别名更加方便
[root@CMDBServerDev04 ~]# alias lm="ls -al | more"
[root@CMDBServerDev04 ~]# lm
...
-rw-r--r-- 1 root root 9368661 Dec 7 11:26 apache-tomcat-8.0.47.tar.gz
...
# 打印当前的所有别名
[root@CMDBServerDev04 ~]# alias
...
alias lm='ls -al | more'
alias mv='mv -i'
...
3.2 历史命令
[root@CMDBServerDev04 ~]# alias h=history
[root@CMDBServerDev04 ~]# h
...
657 dd if=/dev/zero of=123 bs=1M count=20
658 ls
659 ls -al
...
# 执行第658条command
[root@CMDBServerDev04 ~]# !658
ls
apache-tomcat-8.0.47.tar.gz
# 执行上一次的命令
[root@CMDBServerDev04 ~]# !!
ls
apache-tomcat-8.0.47.tar.gz
# 执行以cl开头的命令,在上面是clear
[root@CMDBServerDev04 ~]# !cl
clear
使用history -c;history -w
能更新history文件。
4. Bash shell的操作环境
4.1 路径与指令搜寻顺序
当一个命令比如ls被下达后,其运行的顺序是这样的:
- 由alias找到该指令来执行
- 由bash内置的builtin指令来执行
- 通过$PATH这个变量的顺序来搜寻到的第一个指令来执行
# 执行结果有颜色
[root@CMDBServerDev04 ~]# ls
apache-tomcat-8.0.47.tar.gz cmdbuild-2.5.0
# 执行结果无颜色
[root@CMDBServerDev04 ~]# /bin/ls
apache-tomcat-8.0.47.tar.gz cmdbuild-2.5.0
# 执行顺序如下,先执行的alias别名,故有color
[root@CMDBServerDev04 ~]# type -a ls
ls is aliased to `ls --color=auto'
ls is /usr/bin/ls
# 查看ls命令的别名内容
[root@CMDBServerDev04 ~]# alias | grep ls
alias ls='ls --color=auto'
# 比如给echo赋予别名
[root@CMDBServerDev04 ~]# alias echo="echo -n"
# 通过type可以查看echo命令的执行顺序
# 先别人alias,在builtin内置,最后用$PATH变量搜寻
[root@CMDBServerDev04 ~]# type -a echo
echo is aliased to `echo -n'
echo is a shell builtin
echo is /usr/bin/echo
4.2 进入OS时的欢迎消息
通过vi /etc/issue
和vi /etc/motd
可以编辑欢迎消息样式和内容
4.3 bash 的环境配置文件
记忆内容较多,暂时跳过
4.4 常用快捷key与掩码
- 常用快捷key
命令 | 功能 | 命令 | 功能 |
---|---|---|---|
Ctrl + C | 终止目前的命令 | Ctrl + D | 输入结束 (EOF),例如邮件结束的时候; |
Ctrl + M | 就是 Enter | Ctrl + S | 暂停屏幕的输出 |
Ctrl + Q | 恢复屏幕的输出 | Ctrl + U | 在提示字符下,将整列命令删除 |
Ctrl + Z | “暂停”目前的命令 |
- 常用掩码
命令 | 功能 |
---|---|
* | 0个或多个任意字符 |
? | 一定有一个任意字符 |
[ ] | [abcd]指abcd四个中的一个字符 |
[ -] | [1-9]指1到9的字符 |
[^ ] | [^abc] 有非abc的字符 |
- 特殊符号
命令 | 功能 |
---|---|
# | 注释 |
\ | 将特殊字符或掩码还原成普通字符 |
| |
管线命令 |
; | 连续指令下达分隔符号:连续性命令的界定 (注意!与管线命令并不相同) |
~ | 使用者的主文件夹 |
$ | 取用变量前置字符:亦即是变量之前需要加的变量取代值 |
& | 工作控制 (job control):将指令变成背景下工作 |
! | 逻辑运算意义上的“非” not 的意思! |
/ | 目录符号:路径分隔的符号 |
>, » | 数据流重导向:输出导向,分别是“取代”与“累加” |
<, « | 数据流重导向:输入导向 (这两个留待下节介绍) |
’ ‘ | 单引号,不具有变量置换的功能 ($ 变为纯文本) |
” “ | 具有变量置换的功能! ($ 可保留相关功能) |
` | 两个“ ` ”中间为可以先执行的指令,亦可使用 $( ) |
( ) | 在中间为子 shell 的起始与结束 |
{ } | 在中间为命令区块的组合! |
5. 数据流重导向
数据流重导向就是将某个指令执行后应该要出现在屏幕上的数据, 给他传输到 其他的地方,例如文件或者是设备(例如打印机之类)
# 输出到屏幕
[root@CMDBServerDev04 ~]# ls
apache-tomcat-8.0.47.tar.gz
# 以追加的方式输出到文件
[root@CMDBServerDev04 ~]# ls >> ls.txt
# 以追加的方式,将error信息输出到文件
[root@CMDBServerDev04 ~]# declare -i div=2/0 2>>error.txt
注意: >
是以覆盖的方式输出,>>
以追加的方式输出。
/dev/null
垃圾桶黑洞设备
# 将错误的数据丢弃,屏幕上显示正确的数据
[root@CMDBServerDev04 ~]# find /home -name .bashrc 2>> /dev/null
/home/kotani/.bashrc
<
与<<
标准输入
# 接收输入,写入到文件
[root@CMDBServerDev04 ~]# cat > input1.txt
hello,here is my first msg
# 覆盖的方式输入
[root@CMDBServerDev04 ~]# cat > input1.txt
12345
# 追加的方式输入
[root@CMDBServerDev04 ~]# cat >> input1.txt
789
5.1 命令执行的判断依据 ;
&&
||
;
依次执行多条命令
[root@CMDBServerDev04 lijuntest]# ls;mkdir newfolder;ls
1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt
1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt newfolder
&&
与||
,按照指定逻辑进行多条命令的执行
命令 | 功能 |
---|---|
cmd1 && cmd2 |
若 cmd1 执行完毕且正确执行($?=0),则开始执行 cmd2。 2. 若 cmd1 执行完毕且为错误 ($?≠0),则 cmd2 不执行。 |
cmd1 || cmd2 |
若 cmd1 执行完毕且正确执行($?=0),则 cmd2 不执行。 2. 若 cmd1 执 行完毕且为错误 ($?≠0),则开始执行 cmd2。 |
# 先创建一个文件夹,在ls该文件夹,如果存在,则在下面创建文件
[root@CMDBServerDev04 lijuntest]# mkdir newfolder;ls newfolder && touch newfolder/newfile
# 先ls newfolder2,因为这个文件夹不存在,故后续也无法执行
[root@CMDBServerDev04 newfolder]# ls newfolder2 && touch newfolder2/newfile
ls: cannot access newfolder2: No such file or directory
# 先ls newfolder2,如果不成功,则新建该文件夹,新建成功后在该文件夹下touch一个新文件
[root@CMDBServerDev04 newfolder]# ls newfolder2 || mkdir newfolder2 && touch newfolder2/newfile
6. 管线命令
- 管线命令仅会处理 standard output,对于 standard error output 会予以忽略
- 管线命令必须要能够接受来自前一个指令的数据成为 standard input 继续处理才行。
如 less,more,head,tail都是管线命令。
[root@CMDBServerDev04 ~]# ls -al | less
[root@CMDBServerDev04 ~]# ls -al | head
如果硬要让 standard error 可以被管线命令所使用,那该如何处理?其实就 是通过上一小节的数据流重导向即可! 让 2>&1 加入指令中~就可以让 2> 变成 1> 了。
6.1 截取命令 cut
grep
待续
6.2 排序命令 sort
wc
uniq
、
待续
6.3 双向重导向 tee
待续
6.4 字符转换命令 tr
col
join
paste
expand
待续
6.5 分区命令 split
待续
6.6 参数代换 xargs
待续
6.7 减号-
的用途
待续