你学shell干嘛?
一个脚本就完事了,省出来的时间可以躺在病床上思考人生。
就像大多数文章介绍一样,要从它的历史开始,本文也例行公事介绍一下Linux和shell的历史。
Linux系统是Linus Torvalds在赫尔辛基大学上学时仿造Unix系统开发的一款操作系统。
Linux可分为Linux内核、GNU工具、图形化桌面环境、应用软件四部分。
shell属于GNU工具,是一种特殊的交互式工具。它为用户提供启动程序、管理文件系统中的文件以及运行在Linux系统上的进程的途径。
由于他们是开源的,不同组织开发出了不同版本。常见的Linux发行版有Ubuntu、CentOS、Red Hat、Fedora、Debian、Kali等,常见的shell有bash、zsh、ash、tcsh等。
好了,历史就介绍到这里,更详细信息请自行查询。
本文基于Ubuntu系统的bash shell。
首先是一些基本的shell命令,初学者也应该掌握的,不再赘述。
命令 | 描述 | 参数 |
---|---|---|
cd | 切换目录 .代表当前目录 …代表上一级目录 |
1. 无参:切换到用户家目录,cd 2. 有参:参数为要换的路径,cd Desktop |
pwd | 查看当前目录绝对路径 | - |
ls | 查看当前目录文件列表 | 1. 无参:显示当前目录文件列表,ls 2. 有参: 目录:查看指定目录下的文件列表,ls Desktop -a:显示所有文件(包括隐藏文件、普通文件及目录),ls -a -l:显示文件的更多信息,ls -l -h:以合适的单位显示文件大小 -F:区分文件和目录 |
touch | 新建文件 | 参数为要新建的文件,touch hello.txt |
mkdir | 新建目录 | 参数为要新建的目录,mkdir hello |
cp | 复制文件或目录 | 文件或目录:复制文件或目录,cp hello.txt …/ -r:递归地复制,cp -r hello/src/ ./ |
mv | 移动/重命名文件或目录 | 文件或目录:移动文件或目录,mv hello.txt …/ 如果移动前后的路径相同,则为重命名,mv hello.txt hi.txt |
rm | 删除文件或目录 | 文件或目录:rm hello.txt -r:递归的删除,rm -r a(a是一个包含其他文件或目录的目录) -i:提示是否要删除 -f:没有提示并且强制删除 |
cat | 查看文件内容,一次性输出所有内容 | 文件名:打印该文件的全部内容 -n:打印时显示行号,包括空行 -b:打印时显示行号,不包括空行 |
more/less | 查看文件内容,分页输出文件内容 | |
head | 显示文件开头几行的内容 | 文件名:显示文件的前10行 -n:指定显示的行数,head -n 20 hello.txt |
tail | 显示文件结尾几行的内容 | 文件名:显示文件的末尾10行 -n:指定显示的行数,tail -n 20 hello.txt -f:可以实时监测文件的写入,tail -f hello.txt |
有些参数可以合并使用,如显示文件列表命令,ls,即想显示文件的更多信息,又想以合适的单位显示文件大小,不必写成 ls -l -h
,写成 ls -lh
即可。
另外,有些命令有简写形式,比如 ll
命令,不要以为它是 ls -l
的简写,其实它等价于 ls -alF
,这个可以在用户家目录下的 .bashrc
文件中可以看到,关于这个文件,后面会讲到。
监测进程-ps
运行在系统上的程序叫做进程。要监测这些进程,可以使用 ps
命令。它有很多参数,可以打印进程的很多信息,但不一定都是我们需要的,使用时需要我们筛选。默认情况下(不加参数),它的打印是这样的:
其中,PID代表进程ID(Process ID),TTY是进程运行的终端,TIME是进程已用的CPU时间。
默认情况下, ps 命令只会显示运行在当前控制台下的属于当前用户的进程。
它支持3种风格的命令参数:
ps有很多参数,这里只介绍几个常用的。
首先是Unix风格的参数:
这也是最常用的风格。
参数 | 描述 |
---|---|
-A | 显示所有进程 |
-N | 显示与指定参数不符的所有进程 |
-d | 显示除控制进程外的所有进程 |
-e | 显示所有进程 |
-C cmdlist | 显示包含在 cmdlist 列表中的进程 |
-G grplist | 显示组ID在 grplist 列表中的进程 |
-U userlist | 显示属主的用户ID在 userlist 列表中的进程 |
-p pidlist | 显示PID在 pidlist 列表中的进程 |
-s sesslist | 显示会话ID在 sesslist 列表中的进程 |
-t ttylist | 显示终端ID在 ttylist 列表中的进程 |
-u userlist | 显示有效用户ID在 userlist 列表中的进程 |
-F | 显示更多额外输出(相对 -f 参数而言) |
-O format | 显示默认的输出列以及 format 列表指定的特定列 |
-M | 显示进程的安全信息 |
-c | 显示进程的额外调度器信息 |
-f | 显示完整格式的输出 |
-j | 显示任务信息 |
-l | 显示长列表 |
-o format | 仅显示由 format 指定的列 |
-y | 不要显示进程标记(process flag,表明进程状态的标记) |
-z | 显示安全标签(security context)信息 |
-H | 用层级格式来显示进程(树状,用来显示父进程) |
-w | 采用宽输出模式,不限宽度显示 |
-L | 显示进程中的线程 |
-V | 显示 ps 命令的版本号 |
-n namelist | ps有很多参数,这里只介绍定义了 WCHAN 列显示的值 |
这只是一部分,还有很多,平时使用只记住几个常用的就可以了,下面解释一下输出含义。
输入ps -efl,打印如下:
其中,各列含义为:
F :内核分配给进程的系统标记
S :进程的状态(O代表正在运行;S代表在休眠;R代表可运行,正等待运行;Z代表僵化,进程已结束但父进程已不存在;T代表停止)
UID:启动这些进程的用户
PID:进程的进程ID
PPID:父进程的进程号(如果该进程是由另一个进程启动的)
C:进程生命周期中的CPU利用率
PRI :进程的优先级(越大的数字代表越低的优先级)
NI :谦让度值用来参与决定优先级
ADDR :进程的内存地址
SZ :假如进程被换出,所需交换空间的大致大小
WCHAN :进程休眠的内核函数的地址
STIME:进程启动时的系统时间
TTY:进程启动时的终端设备
TIME:运行进程需要的累计CPU时间
CMD:启动的程序名称
BSD风格和GNU风格的命令和UNIX大同小异,想要了解请自行查询。
介绍一个GNU风格好用的参数 --forest
,它可以显示进程的父子关系,如下图:
再搭配 -e
等参数,可以显示更丰富的信息。
实时监测进程-top
ps显示的是某个时间点的静态进程信息,top命令可以动态地显示实时进程信息。
top的打印如下图:
其中,第一部分显示的是系统概况:第一行显示了当前时间、系统的运行时间、登录的用户数以及系统的平均负载。平均负载有3个值:最近1分钟的、最近5分钟的和最近15分钟的平均负载。值越大说明系统的负载越高。由于进程短期的突发性活动,出现最近1分钟的高负载值也很常见,但如果近15分钟内的平均负载都很高,就说明系统可能有问题。多大的值算高负载,这个与设备配置有关,但一般值超过了2,就说明系统比较繁忙了。
第二行显示了进程概要信息(top 命令的输出中将进程叫作任务(task)):有多少进程处在运行、休眠、停止或是僵化状态(僵化状态是指进程完成了,但父进程没有响应)。
第三行显示了CPU的概要信息。 top 根据进程的属主(用户还是系统)和进程的状态(运行、空闲还是等待)将CPU利用率分成几类输出。
这里有的top命令会显示成
Cpu(s): 5.6% us, 1.7% sy, 0.0% ni, 92.6% id, 0.0% wa, 0.0% hi, 0.0% si, 0.0% st
这和top命令的版本有关,意思一样。
5.6 us — 用户空间占用CPU的百分比。
1.7 sy — 内核空间占用CPU的百分比。
0.0 ni — 改变过优先级的进程占用CPU的百分比
96.2 id — 空闲CPU百分比
0.0 wa — IO等待占用CPU的百分比
0.0 hi — 硬中断(Hardware IRQ)占用CPU的百分比
0.0 si — 软中断(Software Interrupts)占用CPU的百分比
后面两行显示了系统的内存状态。第一行是系统的物理内存:总共有多少内存,当前用了多少,还有多少空闲。后一行是同样的信息,不过是针对系统交换空间(如果分配了的话)的状态而言的。
最后一部分显示了当前运行中的进程的详细列表,有些列跟 ps 命令的输出类似。
PID:进程的ID。
USER:进程属主的名字。
PR:进程的优先级。
NI:进程的谦让度值。
VIRT:进程占用的虚拟内存总量。
RES:进程占用的物理内存总量。
SHR:进程和其他进程共享的内存总量。
S:进程的状态(D代表可中断的休眠状态,R代表在运行状态,S代表休眠状态,T代表跟踪状态或停止状态,Z代表僵化状态)。
%CPU:进程使用的CPU时间比例。
%MEM:进程使用的内存占可用内存的比例。
TIME+:自进程启动到目前为止的CPU时间总量。
COMMAND:进程所对应的命令行名称,也就是启动的程序名。
默认情况下, top 命令在启动时会按照 %CPU 值对进程排序。可以在 top 运行时使用多种交互命令重新排序。每个交互式命令都是单字符,在 top 命令运行时键入可改变 top 的行为。键入f允许你选择对输出进行排序的字段,键入d允许你修改轮询间隔。键入q可以退出 top 。
结束进程-kill-killall
在Linux中,进程之间通过信号来通信。进程的信号就是预定义好的一个消息,进程能识别它并决定忽略还是作出反应。linux信号如下表:
信号 | 名称 | 描述 |
---|---|---|
1 | HUP | 挂起 |
2 | INT | 中断 |
3 | QUIT | 结束运行 |
9 | KILL | 无条件终止 |
11 | SEGV | 段错误 |
15 | TERM | 尽可能终止 |
17 | STOP | 无条件停止运行,但不终止 |
18 | TSTP | 停止或暂停,但继续在后台运行 |
19 | CONT | 在STOP或TSTP之后恢复执行 |
kill的默认参数为15(TERM),即 kill [PID]
和 kill -15 [PID]
等价,但要想发送进程信号,你必须是进程的属主或root用户。
TERM信号是尽可能终止,当然会有不听话的进程,这是可以用 kill -9 [PID]
,无条件杀死某个进程。
还有一个命令 killall
,它可以通过指定进程名来结束进程(kill命令只支持通过进程ID),同时killall命令还支持通配符,可以自己试一下,但使用root命令执行killall时要小心,因为可能杀死很重要的进程。
挂载与卸载设备-mount-umount
和Windows有好多磁盘目录不同,Linux只有一个目录,叫作“虚拟目录”,多个磁盘都在这一个目录下,在目录中加入新存储媒体(比如插入优盘)的操作就叫作“挂载”。现在的大多数Linux系统都可以自动挂载与卸载可移动存储媒体,也可以手动操作。
手动挂载命令为:mount
如果不加参数,mount命令会输出当前系统上挂载的设备列表,如下图:
其中,每行信息包含四部分,比如第一行,sysfs、/sys、sysfs、(rw,nosuid,nodev,noexec,relatime)分别对应以下信息:
媒体的设备文件名、媒体挂载到虚拟目录的挂载点、文件系统类型、已挂载媒体的访问状态。
如果要手动挂载设备,可以使用命令 mount device directory
,其中,device是要挂载的设备, directory是挂载目录(也叫挂载点),比如将优盘 /dev/sdb1
挂载到 /media/disk
,可以使用命令 mount /dev/sdb1 /media/disk
。
注意,要手动在虚拟目录中挂载设备,需要使用root权限。
手动卸载命令为:umount
卸载命令格式为 umount [directory | device ]
,它支持通过设备文件或挂载点来指定要卸载的设备,但如果设备在使用中,系统就不允许卸载。
查看磁盘空间-df
df 命令会显示每个有数据的已挂载文件系统的信息,如下图:
其中每部分代表意义如下:
Filesystem:设备的设备文件位置
1K-blocks:能容纳多少个1024字节大小的块
Used:已用了多少个1024字节大小的块
Available:还有多少个1024字节大小的块可用
Use%:已用空间所占的比例
Mounted on:设备挂载到了哪个挂载点上
df有一个常用参数h,可以把输出中的磁盘空间按照用户易读的形式显示,可以试一下。
查看目录空间-du
du 命令可以显示某个特定目录(默认情况下是当前目录)的空间使用情况。
不带参数时,du命令会递归地显示当前目录下所有文件的大小,如下图:
这只是一部分打印,实际会产生刷屏式的输出,这显然不实用。
它有一些参数,可以帮助我们:
-c :显示所有已列出文件总的大小。
-h :按用户易读的格式输出大小,即用K替代千字节,用M替代兆字节,用G替代吉字
节。
-s :显示每个输出参数的总计。
对数据排序-sort
默认情况下, sort 命令按照字符的顺序对文本文件中的数据按行进行排序。先比较第一个字符,如果一样,就比较第二个字符,以此类推。如下图:
注意,默认情况下,数字也会按照字符的形式来排序。使用 -n
参数可以按照数值排序。如下图:
sort还有好多参数,如下表;
参数 | 描述 |
---|---|
-b | 排序时忽略起始空白 |
-C | 不排序,如果数据无序也不要报告 |
-c | 不排序,但检查输入数据是否已排序 |
-d | 仅考虑空白和字母,不考虑特殊字符 |
-f | 默认情况下,会将大写字母排在前面,该参数会忽略大小写 |
-g | 按通用数值排序 (跟-n不同,把数值按浮点数排序,支持科学计数法) |
-i | 排序时忽略不可打印字符 |
-M | 对三字符月份名按月份排序 |
-m | 将两个已排序数据文件合并 |
-n | 按字符串数值排序(不转换为浮点数) |
-o | 将排序结果写到指定文件 |
-r | 反序排序(升序变降序) |
-S | 指定使用的内存大小 |
-T | 指定一个位置来存储临时工作文件 |
-t | 指定一个用来分割行字符串的字符 |
-k m[,n] | 排序从m位置开始(从1开始计数), 如果指定了n位置,到n位置结束,通常和-t一起用 |
-u | 和-c一起使用时,检查严格排序; 不和-c一起使用时,仅输出第一例相似的两行 |
-z | 用NULL字符作为行尾,而不是用换行符 |
-k 和 -t 参数在对按字段分隔的数据进行排序时非常有用,例如/etc/passwd文件。可以用 -t参数来指定字段分隔符,然后用 -k 参数来指定排序的字段。举个例子,要对前面提到的密码文件/etc/passwd根据用户ID进行数值排序,可以这么做:
搜索数据-grep-egrep-fgrep
grep 命令会在输入或指定的文件中查找包含匹配指定模式的字符的行。
如下图,对于文件string,可以使用 grep [options] pattern [file]
的形式,其中options是可选参数,pattern是要查找的内容,file是文件名。
也可以使用管道对传进来的内容进行搜索。
常用的几个参数:
参数 | 描述 |
---|---|
v | 反向搜索(输出不匹配的行) |
n | 显示匹配行所在的行号 |
c | 输出匹配的行数 |
e | 指定多个匹配模式 |
grep 支持使用正则表达式,例如命令 grep [oe] string
等效于 grep -e o -e e string
。
egrep 命令是 grep 的一个衍生,支持POSIX扩展正则表达式。POSIX扩展正则表达式含有更多的可以用来指定匹配模式的字符。 fgrep 则是另外一个版本,支持将匹配模式指定为用换行符分隔的一列固定长度的字符串。这样就可以把这列字符串放到一个文件中,然后在 fgrep 命令中用其在一个大型文件中搜索字符串了。
压缩数据-tar
tar的命令格式:
tar function [options] object1 object2 ...
function 参数定义了 tar 命令应该做什么,如下表:
功能 | 描述 |
---|---|
-A | 将一个已有tar归档文件追加到另一个已有tar归档文件 |
-c | 创建一个新的tar归档文件 |
-r | 追加文件到已有tar归档文件末尾 |
-t | 列出已有tar归档文件的内容 |
-u | 将比tar归档文件中已有的同名文件新的文件追加到该tar归档文件中 |
-x | 从已有tar归档文件中提取文件 |
每个功能可用选项来针对tar归档文件定义一个特定行为。
选项 | 描述 |
---|---|
-C | 切换到指定目录 |
-f | 输出结果到文件或设备 file |
-j | 将输出重定向给 bzip2 命令来压缩内容 |
-p | 保留所有文件权限 |
-v | 在处理文件时显示文件 |
-z | 将输出重定向给 gzip 命令来压缩内容 |
tar常用到的命令如下:
压缩文件: tar -cvf test.tar test/ test2/
查看压缩文件: tar -tf test.tar
解压文件: tar -xvf test.tar
下一篇:Linux shell编程(二): Linux shell基础