更多 bash 命令

本节会讲一些管理进程、磁盘的命令

监测程序

Windows 可以通过任务栏以及任务管理器查看当前运行的程序,Linux 则是用 ps

$ ps
  PID TTY          TIME CMD
20046 pts/0    00:00:00 bash
20067 pts/0    00:00:00 ps

默认情况下,ps 只会显示运行在当前控制台下,属于当前用户的进程。上面输出了这些进程的编号(PID)、运行在哪个终端(TTY)、以及进程已用的 CPU 时间(TIME)

要显示更多信息,需要加参数。不幸的是,ps 的参数特别复杂,它有三种不同类型的参数:

  • Unix 风格,前面加单破折线 -
  • BSD 风格,前面无破折线
  • GNU 风格,前面加双破折线 --

Unix 风格

参数 描述
-A 显示所有进程
-N 显示与指定参数不符的所有进程
-a 显示除控制进程(session leader1 )和无终端进程外的所有进程
-d 显示除控制进程外的所有进程
-e 显示所有进程
-C cmdlist 显示包含在 cmdlist 列表中的进程
-G grplist 显示组ID在 grplist 列表中的进程
-U userlist 显示属主的用户ID在 userlist 列表中的进程
-g grplist 显示会话或组ID在 grplist 列表中的进程2
-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)3 信息
-H 用层级格式来显示进程(树状,用来显示父进程)
-n namelist 定义了WCHAN 列显示的值
-w 采用宽输出模式,不限宽度显示
-L 显示进程中的线程
-V 显示ps 命令的版本号

一般我们并不会记单个参数,而是记一组参数。常用的参数组合有:

$ ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 Feb03 ?        00:00:10 /sbin/init

显示所有进程,并扩展输出如下信息:

  • UID:用户编号
  • PID:进程编号
  • PPID:父进程编号
  • C:进程生命周期中的 CPU 利用率
  • STIME:启动时间
  • TTY:启动终端
  • TIME:运行进程的累计 CPU 时间
  • CMD:进程的程序名
$ ps -elf
F S UID        PID  PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
4 S root         1     0  0  80   0 - 41389 -      Feb03 ?        00:00:10 /sbin/init
  • F:内核分配给进程的标志
  • S:进程状态(O:运行;S:休眠;R:可运行,等待运行;Z:僵化;T:停止)
  • PRI:进程优先级
  • NI:谦让度值
  • ADDR:进程的内存地址
  • SZ:如果进程被换出,所需的交换空间
  • WCHAN:进程休眠的内核函数的地址

BSD 风格

BSD 是加州大学伯克利分校开发的一个 Unix 版本,BSD版的 ps 常用参数如下:

$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.5 165556  9788 ?        Ss   Feb03   0:10 /sbin/init
  • VSZ:进程在内存中的大小(KB 为单位)
  • RSS:进程在未换出时占用的物理内存
  • STAT:当前进程状态的双字符状态码(第一个字符同 Unix 风格,第二个字符进一步说明进程状态:
    • <:高优先级
    • N:低优先级
    • L:有页面锁定在内存
    • s:是控制进程
    • l:多线程的
    • +:运行在前台

GNU 风格

GNU 长参数可以与 Unix 或 BSD 参数混合使用,用于指定只显示某个用户的进程等。常用 GNU 长参数如下:

参数 描述
–deselect 显示所有进程,命令行中列出的进程
–Group grplist 显示组ID在 grplist 列表中的进程
–User userlist 显示用户ID在 userlist 列表中的进程
–group grplist 显示有效组ID在 grplist 列表中的进程
–pid pidlist 显示PID在 pidlist 列表中的进程
–ppid pidlist 显示父PID在 pidlist 列表中的进程
–sid sidlist 显示会话ID在 sidlist 列表中的进程
–tty ttylist 显示终端设备号在 ttylist 列表中的进程
–user userlist 显示有效用户ID在 userlist 列表中的进程
–format format 仅显示由 format 指定的列
–context 显示额外的安全信息
–forest 用层级结构显示出进程和父进程之间的关系
–headers 在每页输出中都显示列的头
–no-headers 不显示列的头
–sort order 指定将输出按哪列排序
–help 显示帮助信息
–info 显示调试信息
–version 显示ps 命令的版本号

实时监测进程

ps 只能显示当前时间点的进程信息,要实时显示,则要用 top

$ top
top - 12:18:32 up 3 days, 17:07,  1 user,  load average: 0.22, 0.27, 0.24
Tasks: 138 total,   1 running, 137 sleeping,   0 stopped,   0 zombie
%Cpu(s):  5.7 us,  0.8 sy,  0.0 ni, 93.0 id,  0.0 wa,  0.2 hi,  0.2 si,  0.0 st
MiB Mem :   1897.9 total,    470.2 free,    666.7 used,    761.0 buff/cache
MiB Swap:   1024.0 total,   1024.0 free,      0.0 used.   1124.0 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
 3332 pi        20   0   37376  21448   8528 S  22.8   1.1 195:01.51 python3
 9127 pi        20   0   17944   3304   2796 R  17.6   0.2   0:00.04 top

前几行是CPU、内存、交换空间的使用情况,后面则是每个进程的信息:

  • PID:进程编号
  • USER:进程属主的名字
  • PR:进程优先级
  • NI:进程的谦让度
  • VIRT:占用的虚拟内存
  • RES:占用的物理内存
  • SHR:进程与其他进程共享的内存总量
  • S:进程的状态(D:可中断的休眠;R:运行;S:休眠;T:跟踪状态或停止;Z:僵化)
  • %CPU:占用的 CPU 比例
  • %MEM:占用的内存比例
  • TIME+:从启动到现在占用的 CPU 时间总量
  • COMMAND:程序名

结束进程

Linux 中,进程之间通过信号进行通信,进程根据接收的信号来作出响应的反应。标准 Unix 进程信号有:

信号 名称 描述
1 HUP 挂起
2 INT 中断
3 QUIT 结束运行
9 KILL 无条件终止
11 SEGV 段错误
15 TERM 尽可能终止
17 STOP 无条件停止运行,但不终止
18 TSTP 停止或暂停,但继续在后台运行
19 CONT 在STOP 或TSTP 之后恢复执行

可以用 kill PID_num 结束 PID 为 PID_num 的进程。

对于某些顽固的进程,可以用 kill -9 PID_num 来强制结束进程。

kill 本质上是向进程发送一个信号,这个信号默认是停止,我们也可以用它发送其他信号,用法是 kill -s signal_name PID_num,可以用 kill -L 查看可发送的所有信号。

另一个用于结束进程的命令是 killall name,它通过进程名结束进程,并且支持通配符。

监测磁盘空间

挂载存储媒体

前面说过,Linux文件系统将所有的磁盘都并入一个虚拟目录,在使用新的存储媒体之前,需要把它放到虚拟目录下,称为 挂载(mounting)

有些发行版可以自动挂载(比如桌面版的 Ubuntu),反之就要手动挂载。我们可以用 mount

默认情况下,mount 会输出当前已挂载的设备:

$ mount
/dev/mmcblk0p2 on / type ext4 (rw,noatime,nodiratime)
devtmpfs on /dev type devtmpfs (rw,relatime,size=938364k,nr_inodes=234591,mode=755)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,relatime)

每一行都提供了如下信息,以第一行为例:

  • 媒体的设备文件名:/dev/mmcblk0p2
  • 媒体挂载到虚拟目录的挂载点:/
  • 文件系统类型:ext4
  • 已挂载媒体的访问状态:(rw,noatime,nodiratime)

要手动挂载设备,可以用下面的命令:

$ sudo mount -t type device directory

device 是设备文件,可以用 sudo fdisk -l 查看,directory 是挂载点。

mount 的常用参数有:

参数 描述
-v 详细模式,将会说明挂载设备的每一步
-r 将设备挂载为只读的
-w 将设备挂载为可读写的(默认参数)
-o 给文件系统添加特定的选项

要卸载设备,可以用 umount

$ umount [directory|device]

umount 支持通过设备文件或挂载点来指定要卸载的命令,如果有程序在使用设备(比如你 cd 到了设备里),则系统就不会允许逆卸载它。

查看磁盘空间

我们可以用 df 来查看磁盘空间:

$ df
Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/root       29586284  7204476  21126548  26% /
devtmpfs          938364        0    938364   0% /dev
tmpfs             971740        0    971740   0% /dev/shm
tmpfs             971740    45416    926324   5% /run
tmpfs               5120        0      5120   0% /run/lock
tmpfs             971740        0    971740   0% /sys/fs/cgroup
/dev/mmcblk0p1    257772    75948    181824  30% /boot
/dev/sda1      125032444 62160104  62872340  50% /media/pi/Todd
tmpfs             194348        0    194348   0% /run/user/1000

中间的数字是以 1024字节的块为单位(也就是 K),我们可以加上 -h 参数,这样就会按照用户易读的形式显示:

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root        29G  6.9G   21G  26% /
devtmpfs        917M     0  917M   0% /dev
tmpfs           949M     0  949M   0% /dev/shm
tmpfs           949M   45M  905M   5% /run
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           949M     0  949M   0% /sys/fs/cgroup
/dev/mmcblk0p1  252M   75M  178M  30% /boot
/dev/sda1       120G   60G   60G  50% /media/pi/Todd
tmpfs           190M     0  190M   0% /run/user/1000

df 命令只能显示整个磁盘的空间,并不能显示文件和目录的大小,这时候就要用 du,它会显示当前目录下所有文件、目录、子目录的大小,这是一个比较长的列表,我们一般用 -d1 指定深度为 1,另外,用 -h 以用户易读的形式显示:

$ du -hd1
8.0K    ./.gnupg
36K     ./.config
12K     ./.aspnet
4.0M    ./code
56K     ./.cache
346M    ./.local
350M    .

处理数据文件

对文本进行排序

Linux 中会涉及到很多命令输出和日志,通常我们希望按编号、日期等排序,可以用 sort。默认是按照英文字母排序:

$ cat file1
one
two
three
four
five
$ sort file1
five
four
one
three
two

如果要按照数字大小排序,则要用 sort -n

$ cat file2
1
2
100
45
3
10
145
75
$ sort file2
1
10
100
145
2
3
45
75

如果要按照月份缩写排序,则要用 sort -M

$ sort -M file3
Jan
Feb
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec

其他参数如下:

单破折线

双破折线

描述

-b

--ignore-leading-blanks

排序时忽略起始的空白

-C

--check=quiet

不排序,如果数据无序也不要报告

-c

--check

不排序,但检查输入数据是不是已排序;未排序的话,报告

-d

--dictionary-order

仅考虑空白和字母,不考虑特殊字符

-f

--ignore-case

默认情况下,会将大写字母排在前面;这个参数会忽略大小写

-g

--general-number-sort

按通用数值来排序(跟-n 不同,把值当浮点数来排序,支持科学计数法表示的值)

-i

--ignore-nonprinting

在排序时忽略不可打印字符

-k

--key=POS1 [,POS2 ]

排序从POS1位置开始;如果指定了POS2的话,到POS2位置结束

-M

--month-sort

用三字符月份名按月份排序

-m

--merge

将两个已排序数据文件合并

-n

--numeric-sort

按字符串数值来排序(并不转换为浮点数)

-o

--output=file

将排序结果写出到指定的文件中

-R

--random-sort

按随机生成的散列表的键值排序

 

--random-source=FILE

指定-R 参数用到的随机字节的源文件

-r

--reverse

反序排序(升序变成降序)

-S

--buffer-size=SIZE

指定使用的内存大小

-s

--stable

禁用最后重排序比较

-T

--temporary-directory=DIR

指定一个位置来存储临时工作文件

-t

--field-separator=SEP

指定一个用来区分键位置的字符

-u

--unique

-c 参数一起使用时,检查严格排序;不和-c 参数一起用时,仅输出第一例相似的两行

-z

--zero-terminated

用NULL字符作为行尾,而不是用换行符

搜索数据

我们用 grep 命令查找文件中的某一行,它的语法如下:

grep [option] pattern [file]

pattern 是正则表达式。关于正则表达式,我们在后面会学,简单来说,和前面的通配符是差不多的。

压缩数据

工具 文件扩展名 描述
bzip2 .bz2 采用Burrows-Wheeler块排序文本压缩算法和霍夫曼编码
compress .Z 最初的Unix文件压缩工具,已经快没人用了
gzip .gz GNU压缩工具,用Lempel-Ziv编码
zip .zip Windows上PKZIP工具的Unix实现

Linux 上常用的是 gzip,这个软件包包含下面工具:

  • gzip:用来压缩文件
  • gzcat:用来查看压缩过的文本文件的内容
  • gunzip:用来解压文件
$ ls -l test*
-rw-r--r-- 1 pi sudo 90 Feb  7 20:51 test.txt
$ gzip test*
$ ls -l test*
-rw-r--r-- 1 pi sudo 104 Feb  7 20:51 test.txt.gz

归档数据

归档就是将多个文件合成一个文件。Linux 上常用的归档工具是 tar,用法如下:

tar function [option] object1 object2 ...

tar 常用的功能有:

  • tar -c 创建新的归档文件
  • tar -t 查看归档文件的内容
  • tar -x 从归档文件中提取文件

我们经常配合其他的参数使用,比如:

创建归档文件,并指定归档文件的文件名:

$ tar -cvf test.tar test/ test2/

列出tar文件test.tar的内容(但并不提取文件):

$ tar -tf test.tar

从tar文件test.tar中提取内容:

$ tar -xvf test.tar

另外,在 Linux 中经常看到以.tgz结尾的文件,这些是 gzip 压缩过的 tar 文件,可以用命令 tar -zxvf filename .tgz 来解压