Linux 常用指令
本文主要转载并修改自 CyC2018/CS-Notes/Linux - GitHub
PATH
可以在环境变量 PATH 中声明可执行文件的路径,路径之间用 : 分隔。
1 | /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin |
sudo
sudo 允许一般用户使用 root 可执行的命令,不过只有在 /etc/sudoers 配置文件中添加的用户才能使用该指令。
VIM 三个模式
- 一般指令模式(Command mode):VIM 的默认模式,可以用于移动游标查看内容;
- 编辑模式(Insert mode):按下 “i” 等按键之后进入,可以对文本进行编辑;
- 指令列模式(Bottom-line mode):按下 “:” 按键之后进入,用于保存退出等操作。
在指令列模式下,有以下命令用于离开或者保存文件。
命令 | 作用 |
---|---|
:w | 写入磁盘 |
:w! | 当文件为只读时,强制写入磁盘。到底能不能写入,与用户对该文件的权限有关 |
:q | 离开 |
:q! | 强制离开不保存 |
:wq | 写入磁盘后离开 |
:wq! | 强制写入磁盘后离开 |
文件
文件属性
用户分为三种:文件拥有者、群组以及其它人,对不同的用户有不同的文件权限。
使用 ls 查看一个文件时,会显示一个文件的信息,例如 drwxr-xr-x 3 root root 17 May 6 00:14 .config
,对这个信息的解释如下:
- drwxr-xr-x:文件类型以及权限,第 1 位为文件类型字段,后 9 位为文件权限字段
- 3:链接数
- root:文件拥有者
- root:所属群组
- 17:文件大小
- May 6 00:14:文件最后被修改的时间
- .config:文件名
常见的文件类型及其含义有:
- d:目录
- -:文件
- l:链接文件
9 位的文件权限字段中,每 3 个为一组,共 3 组,每一组分别代表对文件拥有者、所属群组以及其它人的文件权限。一组权限中的 3 位分别为 r、w、x 权限,表示可读、可写、可执行。
文件时间有以下三种:
- modification time (mtime):文件的内容更新就会更新;
- status time (ctime):文件的状态(权限、属性)更新就会更新;
- access time (atime):读取文件时就会更新。
文件与目录的基本操作
1. ls
列出文件或者目录的信息,目录的信息就是其中包含的文件。
1 | ## ls [-aAdfFhilnrRSt] file|dir |
2. cd
更换当前目录。
1 | cd [相对路径或绝对路径] |
3. mkdir
创建目录。
1 | ## mkdir [-mp] 目录名称 |
4. rmdir
删除目录,目录必须为空。
1 | rmdir [-p] 目录名称 |
5. touch
更新文件时间或者建立新文件。
1 | ## touch [-acdmt] filename |
6. cp
复制文件。如果源文件有两个以上,则目的文件一定要是目录才行。
1 | cp [-adfilprsu] source destination |
7. rm
删除文件。
1 | ## rm [-fir] 文件或目录 |
8. mv
移动文件。
1 | ## mv [-fiu] source destination |
修改权限
可以将一组权限用数字来表示,此时一组权限的 3 个位当做二进制数字的位,从左到右每个位的权值为 4、2、1,即每个权限对应的数字权值为 r : 4、w : 2、x : 1。
1 | ## chmod [-R] xyz dirname/filename |
示例:将 .bashrc 文件的权限修改为 -rwxr-xr–。
1 | ## chmod 754 .bashrc |
也可以使用符号来设定权限。
1 | ## chmod [ugoa] [+-=] [rwx] dirname/filename |
示例:为 .bashrc 文件的所有用户添加写权限。
1 | ## chmod a+w .bashrc |
默认权限
- 文件默认权限:文件默认没有可执行权限,因此为 666,也就是 -rw-rw-rw- 。
- 目录默认权限:目录必须要能够进入,也就是必须拥有可执行权限,因此为 777 ,也就是 drwxrwxrwx。
可以通过 umask 设置或者查看默认权限,通常以掩码的形式来表示,例如 002 表示其它用户的权限去除了一个 2 的权限,也就是写权限,因此建立新文件时默认的权限为 -rw-rw-r–。
目录的权限
文件名不是存储在一个文件的内容中,而是存储在一个文件所在的目录中。因此,拥有文件的 w 权限并不能对文件名进行修改。
目录存储文件列表,一个目录的权限也就是对其文件列表的权限。因此,目录的 r 权限表示可以读取文件列表;w 权限表示可以修改文件列表,具体来说,就是添加删除文件,对文件名进行修改;x 权限可以让该目录成为工作目录,x 权限是 r 和 w 权限的基础,如果不能使一个目录成为工作目录,也就没办法读取文件列表以及对文件列表进行修改了。
链接
1 | ## ln [-sf] source_filename dist_filename |
1. 实体链接
在目录下创建一个条目,记录着文件名与 inode 编号,这个 inode 就是源文件的 inode。
删除任意一个条目,文件还是存在,只要引用数量不为 0。
有以下限制:不能跨越文件系统、不能对目录进行链接。
1 | ## ln /etc/crontab . |
2. 符号链接
符号链接文件保存着源文件所在的绝对路径,在读取时会定位到源文件上,可以理解为 Windows 的快捷方式。
当源文件被删除了,链接文件就打不开了。
因为记录的是路径,所以可以为目录建立符号链接。
1 | ## ll -i /etc/crontab /root/crontab2 |
获取文件内容
1. cat
取得文件内容。
1 | ## cat [-AbEnTv] filename |
2. tac
是 cat 的反向操作,从最后一行开始打印。
3. more
和 cat 不同的是它可以一页一页查看文件内容,比较适合大文件的查看。
4. less
和 more 类似,但是多了一个向前翻页的功能。
5. head
取得文件前几行。
1 | ## head [-n number] filename |
6. tail
是 head 的反向操作,只是取得是后几行。
7. od
以字符或者十六进制的形式显示二进制文件。
指令与文件搜索
1. which
指令搜索。
1 | ## which [-a] command |
2. whereis
文件搜索。速度比较快,因为它只搜索几个特定的目录。
1 | ## whereis [-bmsu] dirname/filename |
3. locate
文件搜索。可以用关键字或者正则表达式进行搜索。
locate 使用 /var/lib/mlocate/ 这个数据库来进行搜索,它存储在内存中,并且每天更新一次,所以无法用 locate 搜索新建的文件。可以使用 updatedb 来立即更新数据库。
1 | ## locate [-ir] keyword |
4. find
文件搜索。可以使用文件的属性和权限进行搜索。
1 | ## find [basedir] [option] |
① 与时间有关的选项
1 | -mtime n :列出在 n 天前的那一天修改过内容的文件 |
+4、4 和 -4 的指示的时间范围如下:
② 与文件拥有者和所属群组有关的选项
1 | -uid n |
③ 与文件权限和名称有关的选项
1 | -name filename |
压缩与打包
压缩文件名
Linux 底下有很多压缩文件名,常见的如下:
扩展名 | 压缩程序 |
---|---|
*.Z | compress |
*.zip | zip |
*.gz | gzip |
*.bz2 | bzip2 |
*.xz | xz |
*.tar | tar 程序打包的数据,没有经过压缩 |
*.tar.gz | tar 程序打包的文件,经过 gzip 的压缩 |
*.tar.bz2 | tar 程序打包的文件,经过 bzip2 的压缩 |
*.tar.xz | tar 程序打包的文件,经过 xz 的压缩 |
压缩指令
1. gzip
gzip 是 Linux 使用最广的压缩指令,可以解开 compress、zip 与 gzip 所压缩的文件。
经过 gzip 压缩过,源文件就不存在了。
有 9 个不同的压缩等级可以使用。
可以使用 zcat、zmore、zless 来读取压缩文件的内容。
1 | $ gzip [-cdtv#] filename |
2. bzip2
提供比 gzip 更高的压缩比。
查看命令:bzcat、bzmore、bzless、bzgrep。
1 | $ bzip2 [-cdkzv#] filename |
3. xz
提供比 bzip2 更佳的压缩比。
可以看到,gzip、bzip2、xz 的压缩比不断优化。不过要注意的是,压缩比越高,压缩的时间也越长。
查看命令:xzcat、xzmore、xzless、xzgrep。
1 | $ xz [-dtlkc#] filename |
打包
压缩指令只能对一个文件进行压缩,而打包能够将多个文件打包成一个大文件。tar 不仅可以用于打包,也可以使用 gzip、bzip2、xz 将打包文件进行压缩。
1 | $ tar [-z|-j|-J] [cv] [-f 新建的 tar 文件] filename... ==打包压缩 |
使用方式 | 命令 |
---|---|
打包压缩 | tar -jcv -f filename.tar.bz2 要被压缩的文件或目录名称 |
查 看 | tar -jtv -f filename.tar.bz2 |
解压缩 | tar -jxv -f filename.tar.bz2 -C 要解压缩的目录 |
Bash
可以通过 Shell 请求内核提供服务,Bash 正是 Shell 的一种。
特性
- 命令历史:记录使用过的命令
- 命令与文件补全:快捷键:tab
- 命名别名:例如 ll 是 ls -al 的别名
- shell scripts
- 通配符:例如 ls -l /usr/bin/X* 列出 /usr/bin 下面所有以 X 开头的文件
变量操作
对一个变量赋值直接使用 =。
对变量取用需要在变量前加上 $ ,也可以用 ${} 的形式;
输出变量使用 echo 命令。
1 | $ x=abc |
变量内容如果有空格,必须使用双引号或者单引号。
- 双引号内的特殊字符可以保留原本特性,例如 x=”lang is $LANG”,则 x 的值为 lang is zh_TW.UTF-8;
- 单引号内的特殊字符就是特殊字符本身,例如 x=’lang is $LANG’,则 x 的值为 lang is $LANG。
可以使用 `指令` 或者 $(指令) 的方式将指令的执行结果赋值给变量。例如 version=$(uname -r),则 version 的值为 4.15.0-22-generic。
可以使用 export 命令将自定义变量转成环境变量,环境变量可以在子程序中使用,所谓子程序就是由当前 Bash 而产生的子 Bash。
Bash 的变量可以声明为数组和整数数字。注意数字类型没有浮点数。如果不进行声明,默认是字符串类型。变量的声明使用 declare 命令:
1 | $ declare [-aixr] variable |
使用 [ ] 来对数组进行索引操作:
1 | $ array[1]=a |
指令搜索顺序
- 以绝对或相对路径来执行指令,例如 /bin/ls 或者 ./ls ;
- 由别名找到该指令来执行;
- 由 Bash 内置的指令来执行;
- 按 $PATH 变量指定的搜索路径的顺序找到第一个指令来执行。
数据流重定向
重定向指的是使用文件代替标准输入、标准输出和标准错误输出。
1 | 代码 | 运算符 |
---|---|---|
标准输入 (stdin) | 0 | < 或 << |
标准输出 (stdout) | 1 | > 或 >> |
标准错误输出 (stderr) | 2 | 2> 或 2>> |
其中,有一个箭头的表示以覆盖的方式重定向,而有两个箭头的表示以追加的方式重定向。
可以将不需要的标准输出以及标准错误输出重定向到 /dev/null,相当于扔进垃圾箱。
如果需要将标准输出以及标准错误输出同时重定向到一个文件,需要将某个输出转换为另一个输出,例如 2>&1 表示将标准错误输出转换为标准输出。
1 | $ find /home -name .bashrc > list 2>&1 |
管道指令
管道是将一个命令的标准输出作为另一个命令的标准输入,在数据需要经过多个步骤的处理之后才能得到我们想要的内容时就可以使用管道。
在命令之间使用 | 分隔各个管道命令。
1 | $ ls -al /etc | less |
提取指令
cut 对数据进行切分,取出想要的部分。
切分过程一行一行地进行。
1 | $ cut |
示例 1:last 显示登入者的信息,取出用户名。
1 | $ last |
示例 2:将 export 输出的信息,取出第 12 字符以后的所有字符串。
1 | $ export |
排序指令
sort 用于排序。
1 | $ sort [-fbMnrtuk] [file or stdin] |
示例:/etc/passwd 文件内容以 : 来分隔,要求以第三列进行排序。
1 | $ cat /etc/passwd | sort -t ':' -k 3 |
uniq 可以将重复的数据只取一个。
1 | $ uniq [-ic] |
示例:取得每个人的登录总次数
1 | $ last | cut -d ' ' -f 1 | sort | uniq -c |
双向输出重定向
输出重定向会将输出内容重定向到文件中,而 tee 不仅能够完成这个功能,还能保留屏幕上的输出。也就是说,使用 tee 指令,一个输出会同时传送到文件和屏幕上。
1 | $ tee [-a] file |
字符转换指令
tr 用来删除一行中的字符,或者对字符进行替换。
1 | $ tr [-ds] SET1 ... |
示例,将 last 输出的信息所有小写转换为大写。
1 | $ last | tr '[a-z]' '[A-Z]' |
col 将 tab 字符转为空格字符。
1 | $ col [-xb] |
expand 将 tab 转换一定数量的空格,默认是 8 个。
1 | $ expand [-t] file |
join 将有相同数据的那一行合并在一起。
1 | $ join [-ti12] file1 file2 |
paste 直接将两行粘贴在一起。
1 | $ paste [-d] file1 file2 |
分区指令
split 将一个文件划分成多个文件。
1 | $ split [-bl] file PREFIX |
正则表达式
grep
g/re/p(globally search a regular expression and print),使用正则表示式进行全局查找并打印。
1 | $ grep [-acinv] [--color=auto] 搜寻字符串 filename |
示例:把含有 the 字符串的行提取出来(注意默认会有 –color=auto 选项,因此以下内容在 Linux 中有颜色显示 the 字符串)
1 | $ grep -n 'the' regular_express.txt |
示例:正则表达式 a{m,n} 用来匹配字符 a m~n 次,这里需要将 { 和 } 进行转义,因为它们在 shell 是有特殊意义的。
1 | $ grep -n 'a\{2,5\}' regular_express.txt |
printf
用于格式化输出。它不属于管道命令,在给 printf 传数据时需要使用 $( ) 形式。
1 | $ printf '%10s %5i %5i %5i %8.2f \n' $(cat printf.txt) |
awk
是由 Alfred Aho,Peter Weinberger 和 Brian Kernighan 创造,awk 这个名字就是这三个创始人名字的首字母。
awk 每次处理一行,处理的最小单位是字段,每个字段的命名方式为:$n,n 为字段号,从 1 开始,$0 表示一整行。
示例:取出最近五个登录用户的用户名和 IP。首先用 last -n 5 取出用最近五个登录用户的所有信息,可以看到用户名和 IP 分别在第 1 列和第 3 列,我们用 $1 和 $3 就能取出这两个字段,然后用 print 进行打印。
1 | $ last -n 5 |
1 | $ last -n 5 | awk '{print $1 "\t" $3}' |
可以根据字段的某些条件进行匹配,例如匹配字段小于某个值的那一行数据。
1 | $ awk '条件类型 1 {动作 1} 条件类型 2 {动作 2} ...' filename |
示例:/etc/passwd 文件第三个字段为 UID,对 UID 小于 10 的数据进行处理。
1 | $ cat /etc/passwd | awk 'BEGIN {FS=":"} $3 < 10 {print $1 "\t " $3}' |
awk 变量:
变量名称 | 代表意义 |
---|---|
NF | 每一行拥有的字段总数 |
NR | 目前所处理的是第几行数据 |
FS | 目前的分隔字符,默认是空格键 |
示例:显示正在处理的行号以及每一行有多少字段
1 | $ last -n 5 | awk '{print $1 "\t lines: " NR "\t columns: " NF}' |
进程管理
查看进程
1. ps
查看某个时间点的进程信息。
示例:查看自己的进程
1 | ## ps -l |
示例:查看系统所有进程
1 | ## ps aux |
示例:查看特定的进程
1 | ## ps aux | grep threadx |
2. pstree
查看进程树。
示例:查看所有进程树
1 | ## pstree -A |
3. top
实时显示进程信息。
示例:两秒钟刷新一次
1 | ## top -d 2 |
4. netstat
查看占用端口的进程
示例:查看特定端口的进程
1 | ## netstat -anp | grep port |
进程状态
状态 | 说明 |
---|---|
R | running or runnable (on run queue) 正在执行或者可执行,此时进程位于执行队列中。 |
D | uninterruptible sleep (usually I/O) 不可中断阻塞,通常为 IO 阻塞。 |
S | interruptible sleep (waiting for an event to complete) 可中断阻塞,此时进程正在等待某个事件完成。 |
Z | zombie (terminated but not reaped by its parent) 僵死,进程已经终止但是尚未被其父进程获取信息。 |
T | stopped (either by a job control signal or because it is being traced) 结束,进程既可以被作业控制信号结束,也可能是正在被追踪。 |
SIGCHLD
当一个子进程改变了它的状态时(停止运行,继续运行或者退出),有两件事会发生在父进程中:
- 得到 SIGCHLD 信号;
- waitpid() 或者 wait() 调用会返回。
其中子进程发送的 SIGCHLD 信号包含了子进程的信息,比如进程 ID、进程状态、进程使用 CPU 的时间等。
在子进程退出时,它的进程描述符不会立即释放,这是为了让父进程得到子进程信息,父进程通过 wait() 和 waitpid() 来获得一个已经退出的子进程的信息。
wait()
1 | pid_t wait(int *status) |
父进程调用 wait() 会一直阻塞,直到收到一个子进程退出的 SIGCHLD 信号,之后 wait() 函数会销毁子进程并返回。
如果成功,返回被收集的子进程的进程 ID;如果调用进程没有子进程,调用就会失败,此时返回 -1,同时 errno 被置为 ECHILD。
参数 status 用来保存被收集的子进程退出时的一些状态,如果对这个子进程是如何死掉的毫不在意,只想把这个子进程消灭掉,可以设置这个参数为 NULL。
waitpid()
1 | pid_t waitpid(pid_t pid, int *status, int options) |
作用和 wait() 完全相同,但是多了两个可由用户控制的参数 pid 和 options。
pid 参数指示一个子进程的 ID,表示只关心这个子进程退出的 SIGCHLD 信号。如果 pid=-1 时,那么和 wait() 作用相同,都是关心所有子进程退出的 SIGCHLD 信号。
options 参数主要有 WNOHANG 和 WUNTRACED 两个选项,WNOHANG 可以使 waitpid() 调用变成非阻塞的,也就是说它会立即返回,父进程可以继续执行其它任务。
孤儿进程
一个父进程退出,而它的一个或多个子进程还在运行,那么这些子进程将成为孤儿进程。
孤儿进程将被 init 进程(进程号为 1)所收养,并由 init 进程对它们完成状态收集工作。
由于孤儿进程会被 init 进程收养,所以孤儿进程不会对系统造成危害。
僵尸进程
一个子进程的进程描述符在子进程退出时不会释放,只有当父进程通过 wait() 或 waitpid() 获取了子进程信息后才会释放。如果子进程退出,而父进程并没有调用 wait() 或 waitpid(),那么子进程的进程描述符仍然保存在系统中,这种进程称之为僵尸进程。
僵尸进程通过 ps 命令显示出来的状态为 Z(zombie)。
系统所能使用的进程号是有限的,如果产生大量僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程。
要消灭系统中大量的僵尸进程,只需要将其父进程杀死,此时僵尸进程就会变成孤儿进程,从而被 init 进程所收养,这样 init 进程就会释放所有的僵尸进程所占有的资源,从而结束僵尸进程。