Linux宝典

Linux个人宝典资料合集

  • 学习路线

img

基本知识

内建命令与外部命令

内建命令实际上是 shell 程序的一部分,其中包含的是一些比较简单的 Linux 系统命令,这些命令是写在 bash 源码的 builtins 里面的,由 shell 程序识别并在 shell 程序内部完成运行,通常在 Linux 系统加载运行时 shell 就被加载并驻留在系统内存中。而且解析内部命令 shell 不需要创建子进程,因此其执行速度比外部命令快。比如:history、cd、exit 等等。

可以用help + 命令来看所有内建命令的帮助信息

外部命令是 Linux 系统中的实用程序部分,因为实用程序的功能通常都比较强大,所以其包含的程序量也会很大,在系统加载时并不随系统一起被加载到内存中,而是在需要时才将其调入内存。虽然其不包含在 shell 中,但是其命令执行过程是由 shell 程序控制的。外部命令是在 Bash 之外额外安装的,通常放在/bin,/usr/bin,/sbin,/usr/sbin 等等。比如:ls、vi 等。

可以用命令 + –help 来获取外部命令的帮助信息

用于区分类型的命令为:

1
2
3
4
5
6
7
8
9
10
11
12
13
type exit
type vim
type ls
/*
#得到这样的结果说明是内建命令,正如上文所说内建命令都是在 bash 源码中的 builtins 的.def中
xxx is a shell builtin

#得到这样的结果说明是外部命令,正如上文所说,外部命令在/usr/bin or /usr/sbin等等中
xxx is /usr/bin/xxx

#若是得到alias的结果,说明该指令为命令别名所设定的名称;
xxx is an alias for xx --xxx
*

FHS标准

FHS(英文:Filesystem Hierarchy Standard 中文:文件系统层次结构标准),多数 Linux 版本采用这种文件组织形式,FHS 定义了系统中每个区域的用途、所需要的最小构成的文件和目录同时还给出了例外处理与矛盾处理。

img

关于上面提到的 FHS,这里还有个很重要的内容你一定要明白,FHS 是根据以往无数 Linux 用户和开发者的经验总结出来的,并且会维持更新,FHS 依据文件系统使用的频繁与否以及是否允许用户随意改动(注意,不是不能,学习过程中,不要怕这些),将目录定义为四种交互作用的形态,如下表所示:

img

重定向

Linux 默认提供了三个特殊设备,用于终端的显示和输出,分别为stdin(标准输入,对应于你在终端的输入),stdout(标准输出,对应于终端的输出),stderr(标准错误输出,对应于终端的输出)。

文件描述符 设备文件 说明
0 /dev/stdin 标准输入
1 /dev/stdout 标准输出
2 /dev/stderr 标准错误

文件描述符:文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于 UNIX、Linux 这样的操作系统。

标准输出 | 重定向符 >,>>,<,<<

>会覆盖目标的原有内容。当文件存在时会先删除原文件,再重新创建文件,然后把内容写入该文件;否则直接创建文件

>>会在目标原有内容后追加内容。当文件存在时直接在文件末尾进行内容追加,不会删除原文件;否则直接创建文件。

标准错误的重定向

1
2
3
4
# 将标准错误重定向到标准输出,再将标准输出重定向到文件,注意要将重定向到文件写到前面
cat Documents/test.c hello.c >somefile 2>&1
# 或者只用bash提供的特殊的重定向符号"&"将标准错误和标准输出同时重定向到文件
cat Documents/test.c hello.c &>somefilehell

永久重定向

1
2
3
4
5
6
7
8
# 先开启一个子 Shell
zsh
# 使用exec替换当前进程的重定向,将标准输出重定向到一个文件
exec 1>somefile
# 后面你执行的命令的输出都将被重定向到文件中,直到你退出当前子shell,或取消exec的重定向(后面将告诉你怎么做)
ls
exit
cat somefile

样例

创建输出文件描述符

在 Shell 中有 9 个文件描述符。上面我们使用了也是它默认提供的 0,1,2 号文件描述符。另外我们还可以使用 3-8 的文件描述符,只是它们默认没有打开而已。你可以使用下面命令查看当前 Shell 进程中打开的文件描述符:

1
2
cd /dev/fd/
ls -Al

同样使用exec命令可以创建新的文件描述符

1
2
3
4
5
6
7
8
zsh
exec 3>somefile
# 先进入目录,再查看,否则你可能不能得到正确的结果,然后再回到上一次的目录
cd /dev/fd/;ls -Al;cd -
# 注意下面的命令>与&之间不应该有空格,如果有空格则会出错
echo "this is test" >&3
cat somefile
exit

关闭文件描述符

1
2
exec 3>&-
cd /dev/fd;ls -Al;cd -

完全屏蔽命令的输出

我们可以利用/dev/null屏蔽命令的输出:

1
cat Documents/test.c 1>/dev/null 2>&1

上面这样的操作将使你得不到任何输出结果。

组合命令小要点

顺序执行多条命令

1
2
3
4
5
sudo apt-get update
# 等待——————————然后输入下面的命令
sudo apt-get install some-tool //这里some-tool是指具体的软件包
# 等待——————————然后输入下面的命令
some-tool

将上述命令转化成一次性输入完

全部执行
1
2
sudo apt-get update;sudo apt-get install some-tool;some-tool
# 让它自己运行
有选择的执行
1
2
which cowsay>/dev/null && cowsay -f head-in ohch~
# 上面的&&就是用来实现选择性执行的,它表示如果前面的命令执行结果(不是表示终端输出的内容,而是表示命令执行状态的结果)返回 0 则执行后面的,否则不执行,你可以从$?环境变量获取上一次命令的返回结果:
1
$ which cowsay>/dev/null && echo "exist" || echo "not exist"

可以从$?环境变量获取上一次命令的返回结果:

1
echo $?

流程图

管道

常用命令

功能

查看版本内核

1
2
3
cat /etc/redhat-release
cat /etc/issue
uname -r

命令

帮助命令

man命令
1
man ls

man命令的章节说明

章节数 说明
1 Standard commands (标准命令)
2 System calls (系统调用)
3 Library functions (库函数)
4 Special devices (设备说明)
5 File formats (文件格式)
6 Games and toys (游戏和娱乐)
7 Miscellaneous (杂项)
8 Administrative Commands (管理员命令)
9 其他(Linux 特定的), 用来存放内核例行程序的文档。

打开手册之后我们可以通过 pgup 与 pgdn 或者上下键来上下翻看,可以按 q 退出当前页面

info命令
  • 命令

    1
    2
    3
    4
    5
    # 安装 info
    sudo apt-get update
    sudo apt-get install info
    # 查看 ls 命令的 info
    info ls

文件操作

touch命令
1
touch test
cp命令
  1. 复制文件

    1
    cp test father/son/grandson #将之前创建的 test 文件复制到 /home/shiyanlou/father/son/grandson 目录中
  2. 复制目录

    1
    2
    3
    4
    cd /home/shiyanlou
    mkdir family
    cp -r father family
    #要成功复制目录需要加上 -r 或者 -R 参数,表示递归复制,就是说有点目录及其下面的子目录层层进入复制的意思:
rm命令
  • 删除文件

    1
    2
    3
    4
    5
    rm test
    #删除一个文件

    rm -f test
    #为了忽略删除只读文件的权限,可以直接使用-f参数强制删除
  • 删除目录

    1
    2
    rm -r family
    # 同复制目录一样,要删除一个目录也要加上一个-r或者-R参数 权限不足的时候也可以加上-f强制删除
mv命令
  • 移动文件

    1
    2
    3
    4
    mkdir Documents
    touch file1
    mv file1 Documents
    # 将文件“ file1 ”移动到 Documents 目录
  • 重命名文件

    1
    2
    mv file1 myfile
    #file1为旧文件名 myfile为新文件名
rename命令

rename 命令并不是内置命令,若提示无该命令可以使用 sudo apt-get install rename 命令自行安装。

  • 批量重命名

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    cd /home/shiyanlou/

    # 使用通配符批量创建 5 个文件:
    touch file{1..5}.txt

    # 批量将这 5 个后缀为 .txt 的文本文件重命名为以 .c 为后缀的文件:
    rename 's/\.txt/\.c/' *.txt

    # 批量将这 5 个文件,文件名和后缀改为大写:
    rename 'y/a-z/A-Z/' *.c
cat命令与tac命令

前两个命令都是用来打印文件内容到标准输出(终端),其中 cat 为正序显示,tac 为倒序显示。

标准输入输出:当我们执行一个 shell 命令行时通常会自动打开三个标准文件,即标准输入文件(stdin),默认对应终端的键盘、标准输出文件(stdout)和标准错误输出文件(stderr),后两个文件都对应被重定向到终端的屏幕,以便我们能直接看到输出内容。进程将从标准输入文件中得到输入数据,将正常输出数据输出到标准输出文件,而将错误信息送到标准错误文件中。

  • 查看文件

    1
    2
    3
    4
    cd /home/shiyanlou
    cp /etc/passwd passwd
    cat passwd
    cat -n passwd #加上-n显示行号
nl命令

添加行号并打印,这是个比 cat -n 更专业的行号打印命令。

-b : 指定添加行号的方式,主要有两种:

​ -b a:表示无论是否为空行,同样列出行号(“cat -n”就是这种方式)

​ -b t:只列出非空行的编号并列出(默认为这种方式)

-n : 设置行号的样式,主要有三种:

​ -n ln:在行号字段最左端显示

​ -n rn:在行号字段最右边显示,且不加 0

​ -n rz:在行号字段最右边显示,且加 0 -w : 行号字段占用的位数(默认为 6 位)

more命令与less命令

其中 more 命令比较简单,只能向一个方向滚动,而 less 为基于 morevi (一个强大的编辑器,我们有单独的课程来让你学习)开发,功能更强大。less 的使用基本和 more 一致

  • 查看文件

    1
    more passwd

    打开后默认只显示一屏内容,终端底部显示当前阅读的进度。可以使用 Enter 键向下滚动一行,使用 Space 键向下滚动一屏,按下 h 显示帮助,q 退出。

head命令与tail命令
  • 查看文件

    1
    tail /etc/passwd
  • 查看文件后几行

    1
    2
    3
    tail -n 1 /etc/passwd
    # 加上 -n 参数,后面紧跟行数
    # -f可以动态查看日志,做到监视的目的
file命令
  • 查看文件类型

    1
    file /bin/ls

    ps Linux中的文件类型不是通过后缀来区分的,而是依照文件的内容进行处理

whereis命令
1
2
whereis who
whereis find

whereis 只能搜索二进制文件(-b),man 帮助文件(-m)和源代码文件(-s)。如果想要获得更全面的搜索结果可以使用 locate 命令。

locate命令

使用 locate 命令查找文件也不会遍历硬盘,它通过查询 /var/lib/mlocate/mlocate.db 数据库来检索信息。不过这个数据库也不是实时更新的,系统会使用定时任务每天自动执行 updatedb 命令来更新数据库。所以有时候你刚添加的文件,它可能会找不到,需要手动执行一次 updatedb 命令(在我们的环境中必须先执行一次该命令)。注意这个命令也不是内置的命令,例如在我们的环境中就需要手动安装,然后执行更新。

1
2
3
sudo apt-get update
sudo apt-get install locate
sudo updatedb

它可以用来查找指定目录下的不同文件类型

1
2
locate /etc/sh
# 注意,它不只是在 /etc 目录下查找,还会自动递归子目录进行查找。
  • 查找 /usr/share/ 下所有 jpg 文件

    1
    2
    locate /usr/share/\*.jpg
    # *号前面的反斜杠转义一定要添加,否则无法找到
which命令

which 本身是 Shell 内建的一个命令,我们通常使用 which 来确定是否安装了某个指定的程序,因为它只从 PATH 环境变量指定的路径中去搜索命令并且返回第一个搜索到的结果。也就是说,我们可以看到某个系统命令是否存在以及执行的到底是哪一个地方的命令。

1
2
3
which man
which nginx
which ping
find命令

find 应该是这几个命令中最强大的了,它不但可以通过文件类型、文件名进行查找而且可以根据文件的属性(如文件的时间戳,文件的权限等)进行搜索。find 命令强大到,要把它讲明白至少需要单独好几节课程才行,我们这里只介绍一些常用的内容。

  • 语法

    1
    find [path][option] [action] 
tee命令

在标准输出到屏幕不变的情况下保存在文件中

1
echo 'Hello World!' | tee filename
tree命令

目录路径

cd命令
1
2
3
4
5
6
7
8
cd ..
cd ~ #进入home目录 # 或者 cd /home/<你的用户名>

# 绝对路径
cd /usr/local/bin
# 相对路径
cd ../../usr/local/bin
#提示:在进行目录切换的过程中请多使用 Tab 键自动补全,可避免输入错误,连续按两次 Tab 可以显示全部候选结果。

这个命令可以看到路径下的树结构

1
2
3
4
tree /
/*
如果没有安装那么需要先 sudo apt-get install tree (先update)
*/

img

cp命令
  1. 复制文件

    1
    cp test father/son/grandson #将之前创建的 test 文件复制到 /home/shiyanlou/father/son/grandson 目录中
  2. 复制目录

    1
    2
    3
    4
    cd /home/shiyanlou
    mkdir family
    cp -r father family
    #要成功复制目录需要加上 -r 或者 -R 参数,表示递归复制,就是说有点目录及其下面的子目录层层进入复制的意思:
pwd命令

获取当前路径

1
pwd #获取当前路径
mkdir命令

新建目录

1
2
3
mkdir mydir #当前路径下创建mydir目录
mkdir -p father/son/grandson
# 这里需要注意到-p参数可以同时创建一个多级目录,即便不存在父目录也是可以的

还有一点需要注意的是,若当前目录已经创建了一个 test 文件,再使用 mkdir test 新建同名的文件夹,系统会报错文件已存在。这符合 Linux 一切介文件的理念。

若当前目录存在一个 test 文件夹,则 touch 命令,则会更改该文件夹的时间戳而不是新建文件。

文本命令(文本编辑三剑客)

grep
sed
awk
* cut

文件打包压缩

压缩文件说明

文件后缀名 说明
*.zip zip 程序打包压缩的文件
*.rar rar 程序压缩的文件
*.7z 7zip 程序压缩的文件
*.tar tar 程序打包,未压缩的文件
*.gz gzip 程序(GNU zip)压缩的文件
*.xz xz 程序压缩的文件
*.bz2 bzip2 程序压缩的文件
*.tar.gz tar 打包,gzip 程序压缩的文件
*.tar.xz tar 打包,xz 程序压缩的文件
*tar.bz2 tar 打包,bzip2 程序压缩的文件
*.tar.7z tar 打包,7z 程序压缩的文件
zip命令
  • 打包文件夹

    1
    2
    3
    4
    zip -r -q -o shiyanlou.zip /home/shiyanlou/Desktop
    du -h shiyanlou.zip
    file shiyanlou.zip
    #上面命令将目录 /home/shiyanlou/Desktop 打包成一个文件,并查看了打包后文件的大小和类型。第一行命令中,-r 参数表示递归打包包含子目录的全部内容,-q 参数表示为安静模式,即不向屏幕输出信息,-o,表示输出文件,需在其后紧跟打包输出文件名。后面使用 du 命令查看打包后文件的大小(后面会具体说明该命令)。
  • 设置压缩级别为 9 和 1(9 最大,1 最小),重新打包

    1
    2
    3
    zip -r -9 -q -o shiyanlou_9.zip /home/shiyanlou/Desktop -x ~/*.zip
    zip -r -1 -q -o shiyanlou_1.zip /home/shiyanlou/Desktop -x ~/*.zip
    #这里添加了一个参数用于设置压缩级别 -[1-9],1 表示最快压缩但体积大,9 表示体积最小但耗时最久。最后那个 -x 是为了排除我们上一次创建的 zip 文件,否则又会被打包进这一次的压缩文件中,注意:这里只能使用绝对路径,否则不起作用。
  • 创建加密zip包

    1
    2
    zip -r -e -o shiyanlou_encryption.zip /home/shiyanlou/Desktop
    #使用 -e 参数可以创建加密压缩包
  • windows适配

    1
    2
    zip -r -l -o shiyanlou.zip /home/shiyanlou/Desktop
    #需要加上 -l 参数将 LF 转换为 CR+LF 来达到以上目的。
unzip命令
  • 解压命令

    1
    unzip shiyanlou.zip
  • 使用安静模式,将文件解压到指定目录:

    1
    2
    unzip -q shiyanlou.zip -d ziptest
    # -q表示安静模式 -d表示文件解压的指定目录,如果上述目录不存在,将会自动创建
  • 查看压缩包内的内容

    1
    2
    unzip -l shiyanlou.zip
    # -l参数可以查看压缩包的内容

PS

注意: 使用 unzip 解压文件时我们同样应该注意兼容问题,不过这里我们关心的不再是上面的问题,而是中文编码的问题,通常 Windows 系统上面创建的压缩文件,如果有有包含中文的文档或以中文作为文件名的文件时默认会采用 GBK 或其它编码,而 Linux 上面默认使用的是 UTF-8 编码,如果不加任何处理,直接解压的话可能会出现中文乱码的问题(有时候它会自动帮你处理),为了解决这个问题,我们可以在解压时指定编码类型。

1
unzip -O GBK 中文压缩文件.zip
du命令
1
2
3
du -h -d 0 *.zip ~ | sort
# h, --human-readable(顾名思义,你可以试试不加的情况)
# d, --max-depth(所查看文件的深度)
tar命令

在 Linux 上面更常用的是 tar 工具,tar 原本只是一个打包工具,只是同时还是实现了对 7z、gzip、xz、bzip2 等工具的支持,这些压缩工具本身只能实现对文件或目录(单独压缩目录中的文件)的压缩,没有实现对文件的打包压缩,所以我们也无需再单独去学习其他几个工具,tar 的解压和压缩都是同一个命令,只需参数不同,使用比较方便。

  • 创建一个tar包

    1
    2
    3
    cd /home/shiyanlou
    tar -P -cf shiyanlou.tar /home/shiyanlou/Desktop
    #上面命令中,-P 保留绝对路径符,-c 表示创建一个 tar 包文件,-f 用于指定创建的文件名,注意文件名必须紧跟在 -f 参数之后,比如不能写成 tar -fc shiyanlou.tar,可以写成 tar -f shiyanlou.tar -c ~。你还可以加上 -v 参数以可视的的方式输出打包的文件。
  • 解包一个文件到指定路径的已存在目录

    1
    2
    3
    mkdir tardir
    tar -xf shiyanlou.tar -C tardir
    # -x 参数 解包 -C参数 已存在路径
  • 只查看不解包文件

    1
    2
    tar -tf shiyanlou.tar
    # -t参数
  • 解包时保留文件属性和跟随链接(符号链接或软链接)

    1
    2
    tar -cphf etc.tar /etc
    # -p 保留文件的属性 -h 备份链接指向的源文件而不是链接本身
  • 对其他压缩文件格式解压

    压缩文件格式 参数
    *.tar.gz -z
    *.tar.xz -J
    *tar.bz2 -j
    • 创建tar.gz文件

      1
      2
      tar -czf shiyanlou.tar.gz /home/shiyanlou/Desktop
      # 这里的-z就是表示为gz文件
    • 解压 *.tar.gz文件

      1
      tar -xzf shiyanlou.tar.gz

组合命令

cut命令

打印/etc/passwd文件中以:为分隔符的第 1 个字段和第 6 个字段分别表示用户名和其家目录:

1
$ cut /etc/passwd -d ':' -f 1,6

打印/etc/passwd文件中每一行的前 N 个字符:

1
2
3
4
5
6
7
8
# 前五个(包含第五个)
$ cut /etc/passwd -c -5
# 前五个之后的(包含第五个)
$ cut /etc/passwd -c 5-
# 第五个
$ cut /etc/passwd -c 5
# 2到5之间的(包含第五个)
$ cut /etc/passwd -c 2-5
grep命令

结合正则表达式可以实现很复杂却很高效的匹配和查找

一般形式
1
grep [命令选项]... 用于匹配的表达式 [文件]...

搜索/home/shiyanlou目录下所有包含”shiyanlou”的文本文件,并显示出现在文本中的行号:

1
2
3
4
$ grep -rnI "shiyanlou" ~
# -r 参数表示递归搜索子目录中的文件
# -n表示打印匹配项行号
# -I表示忽略二进制文件

img

匹配字段中使用正则表达式

1
2
3
# 查看环境变量中以"yanlou"结尾的字符串
$ export | grep ".*yanlou$"
# $表示一行的末尾
wc命令

统计并输出一个文件中行、单词和字节的数目,比如输出/etc/passwd文件的统计信息:

1
$ wc /etc/passwd

分别只输出行数、单词数、字节数、字符数和输入文本中最长一行的字节数:

1
2
3
4
5
6
7
8
9
10
# 行数
$ wc -l /etc/passwd
# 单词数
$ wc -w /etc/passwd
# 字节数
$ wc -c /etc/passwd
# 字符数
$ wc -m /etc/passwd
# 最长行字节数
$ wc -L /etc/passwd
xargs命令

xargs 是一条 UNIX 和类 UNIX 操作系统的常用命令。它的作用是将参数列表转换成小块分段传递给其他命令,以避免参数列表过长的问题。

处理产生大量输出结果的命令如 find,locate 和 grep 的结果

1
2
$ cut -d: -f1 < /etc/passwd | sort | xargs echo
# 将/etc/passwd文件按:分割取第一个字段排序后,使用echo命令生成一个列表

PS

注意:对于西文字符来说,一个字符就是一个字节,但对于中文字符一个汉字是大于 2 个字节的,具体数目是由字符编码决定的

此处输入图片的描述

结合管道,统计 /etc 下面所有目录数:

1
$ ls -dl /etc/*/ | wc -l

此处输入图片的描述

sort命令

将输入按照一定方式排序,然后再输出

支持的排序:按字典排序,数字排序,按月份排序,随机排序,反转排序,指定特定字段进行排序等等

字典排序/反转排序/按特定字段排序:

1
2
3
4
5
$ cat /etc/passwd | sort
$ cat /etc/passwd | sort -r
$ cat /etc/passwd | sort -t':' -k 3
# -t参数用于指定字段的分隔符,这里是以":"作为分隔符
# -k [字段号] 用于指定对哪一个字段进行排序

这里/etc/passwd文件的第三个字段为数字,默认情况下是以字典序排序的,如果要按照数字排序就要加上-n参数:

1
$ cat /etc/passwd | sort -t':' -k 3 -n

注意观察第二个冒号后的数字:

此处输入图片的描述

uniq命令

过滤或者输出重复行

过滤重复行

使用history命令查看最近执行过的命令(实际为读取${SHELL}_history 文件,如我们环境中的~/.zsh_history 文件),去掉命令后面的参数然后去掉重复的命令:

1
$ history | cut -c 8- | cut -d ' ' -f 1 | uniq

去重效果不明显——因为uniq命令只能去连续重复的行,不是全文去重

要达到预期效果,我们先排序:

1
2
$ history | cut -c 8- | cut -d ' ' -f 1 | sort | uniq
# 或者$ history | cut -c 8- | cut -d ' ' -f 1 | sort -u
输出重复行
1
2
3
4
# 输出重复过的行(重复的只输出一个)及重复次数
history | cut -c 8- | cut -d ' ' -f 1 | sort | uniq -dc
# 输出所有重复的行
history | cut -c 8- | cut -d ' ' -f 1 | sort | uniq -D

定时服务

at+cron+anacron.png

at命令
  • 安装

    1
    apt-get install at
  • 检查at服务是否启动:

    1
    ps -ef | grep -v grep | grep atd
  • 启动

    1
    sudo service atd start

    at1.png

  • 使用

    添加计划任务

    1
    2
    3
    4
    5
    at now + 1 minute
    at> date >> at.log
    at> <EOT> # Ctrl+D结束
    # 上述命令表示1分钟之后执行任务date
    # 按Ctrl+D结束任务编辑

    灵活的指定时间的形式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 2022年 05月 11日 星期三 10:24:00 CST
    at -f file now + 1 minutes # job X at Wed May 11 10:25:00 2022
    at -f file 4pm + 3 days # job 11 at Sat May 14 16:00:00 2022
    at -f file noon Jul 31 # 12点
    at -f file 6:00 tomorrow
    at -f file tomorrow
    at -f file 10am 05/15/2022
    at -f file teatime #下午4点
    at -f file.sh 05pm + 3 days # 3天后的下午5点
    at -f file.sh tomorrow # 明天 today
    at -f file.sh noon # 中午 midnight/teatime
    at -f file.sh 16:00 05/05/2021 # 完整的日期和时间
  • 用户控制

    • /etc/at.allow
    • /etc/at.deny

    at命令先查询 /etc/at.allow 文件,凡事出现在该文件中的用户都可以使用at命令,这个就是所谓的白名单。如果没有这个文件,则查找 /etc/at.deny,这个就是 黑名单 ,凡是不在该文件中的用户都可以使用at命令。一般系统都是允许所有正常用户使用at命令,所以在/etc目录中存放一个空的at.deny文件。

    查看当前等待运行的任务。

    1
    2
    3
    atq  #查看当前还有哪些待执行任务

    atrm <num> #删除计划任务,后跟的是任务的号码
crontab命令

常见于设置周期性被执行的命令,实现自动进行系统管理的目的

crontab 命令从输入设备读取指令,并将其存放于 crontab 文件中,以供之后读取和执行。通常,crontab 储存的指令被守护进程激活,crond 为其守护进程,crond 常常在后台运行,每一分钟会检查一次是否有预定的作业需要执行。

通过 crontab 命令,我们可以在固定的间隔时间执行指定的系统指令或 shell   script 脚本。时间间隔的单位可以是分钟、小时、日、月、周的任意组合。

格式
1
2
3
4
5
6
7
8
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
准备

crontab 在本实验环境中需要做一些特殊的准备,首先我们会启动 rsyslog,以便我们可以通过日志中的信息来了解我们的任务是否真正的被执行了(在本实验环境中需要手动启动,而在自己本地中 Ubuntu 会默认自行启动不需要手动启动)

1
2
sudo apt-get install -y rsyslog
sudo service rsyslog start

service-rsyslog-start

在本实验环境中 crontab 也是不被默认启动的,同时不能在后台由 upstart 来管理,所以需要我们来启动它:

1
sudo cron -f &

此处输入图片的描述

基本用法

添加一个计划任务

1
crontab -e

第一次启动会出现这样一个画面,这是让我们选择编辑的工具,选择第二个基本的 vim 就可以了。有的系统中没有提示,直接就是vim编辑器,也有的系统中第一个选项是nano编辑器。

此处输入图片的描述

而选择后我们会进入这样一个画面,这就是添加计划的地方了,与一般的配置文档相同,以#号开头的都是注释

每行的开头五个域,指定计划任务执行的时间和日期等,从左开始依次是:

  • 分钟 m(minute)
  • 小时 h(hour)
  • 日 dom(day of month)
  • 月 mon(month)
  • 星期 dow(day of week)

最后是要执行的命令,也可以是脚本

实验楼

详细的格式可以使用前面学习到的 man 命令查看帮助信息:

1
man crontab

在了解命令格式之后,我们通过这样的一个例子来完成一个任务的添加,在文档的最后一排加上这样一排命令,该任务是每分钟我们会在/home/shiyanlou 目录下创建一个以当前的年月日时分秒为名字的空白文件

1
*/1 * * * * touch /home/shiyanlou/$(date +\%Y\%m\%d\%H\%M\%S)

注意 “ % ” 在 crontab 文件中,有结束命令行、换行、重定向的作用,前面加 ” \ ” 符号转义,否则,“ % ” 符号将执行其结束命令行或者换行的作用,并且其后的内容会被做为标准输入发送给前面的命令。

添加成功后我们会得到最后一排 installing new crontab 的一个提示。实际上,刚才编辑没有保存之前是一个临时文件,当保存成功的时候才添加了计划任务。这个保存的配置文件不是 /etc/crontab,而是在 /var/spool/cron/crontabs 目录中增加一个与用户名同名的配置文件。

实验楼

可以通过如下指令来查看当前用户有哪些计划任务。

1
crontab -l

正确的保存并且添加成功了该任务

实验楼

虽然我们添加了任务,但是如果 cron 的守护进程并没有启动,它根本不会监测到有任务,当然也就不会执行计划任务,可以通过以下 2 种方式来确定 cron 是否成功的在后台启动,默默的按计划执行任务,若是没有就得参照3.2中的准备命令。

1
2
3
4
5
ps aux | grep cron

or

pgrep cron

此处输入图片的描述

通过下图可以看到任务在创建之后,执行了几次,生成了一些文件,且每分钟生成一个:

此处输入图片的描述

通过如下命令可以查看执行任务命令之后在日志中的信息反馈

1
sudo tail -f /var/log/syslog

从图中我们可以看到分别在 13 点 28、29、30 分的 01 秒为我们在 shiyanlou 用户的家目录下创建了文件

此处输入图片的描述

当我们并不需要这个任务的时候我们可以使用这么一个命令去删除任务

1
crontab -r

通过图中我们可以看出我们删除之后再查看任务列表,系统显示该用户没有计划任务了。

此处输入图片的描述

深入

每个用户使用 crontab -e 添加计划任务,都会在 /var/spool/cron/crontabs 中添加一个该用户自己的任务文档,这样目的是为了隔离。

实验楼

如果是系统级别的定时任务,只需要以 sudo 权限编辑 /etc/crontab 文件就可以。

cron 服务监测时间最小单位是分钟,所以 cron 会每分钟去读取一次 /etc/crontab/var/spool/cron/crontabs 里面的內容。

在 /etc 目录下,cron 相关的目录有下面几个:

实验楼

每个目录的作用:

  1. /etc/cron.daily,目录下的脚本会每天执行一次,在每天的 6 点 25 分时运行;
  2. /etc/cron.hourly,目录下的脚本会每个小时执行一次,在每小时的 17 分钟时运行;
  3. /etc/cron.monthly,目录下的脚本会每月执行一次,在每月 1 号的 6 点 52 分时运行;
  4. /etc/cron.weekly,目录下的脚本会每周执行一次,在每周第七天的 6 点 47 分时运行;

系统默认执行时间可以根据需求进行修改。

在 /etc 目录中,还有一个 /etc/cron.d 目录,其中存放一些cron计划任务的配置文件,相应的任务也会得到执行,其配置格式与 /etc/crontab 文件相同。例如:可以放置跟apache的计划任务,文件名可以命名为 /etc/cron.d/httpd。

anacron命令

执行按天为最小计划时间单位的计划任务

并不要求计算机24×7连续运行,对于一些笔记本或者台式计算机来说,经常处于关机不工作状态,如果使用cron就会错过计划任务,但是使用anacron就可以在下一次启动后执行计划任务

安装
1
sudo apt-get install -y anacron

然后可以看到/etc/anacrontab文件,打开可以查看文件的内容

anacron1.png

anacron的配置跟cron配置不同,包含四个域:

anacron2.png

这四个域表示的含义如下图所示:

anacron3.png

  • period: 指明天数

    • 1 - daily
    • 7 - weekly
    • 30 - monthly
    • N - number of days
    • @monthly - 每月执行job
  • delay: 执行job之前延迟的分钟数

  • identifier:记录job执行的时间戳的文件名

  • command:要执行的job,命令或者shell脚本。

    在/var/spool/anacron/目录下会出现一些文件,这些文件对应着配置的job,记录了最近一次执行job的日期。

进程管理

查看

top 实时的查看进程的状态,以及系统的一些信息(如 CPU、内存信息等)

ps 来静态查看当前的进程信息

pstree 来查看当前活跃进程的树形结构

top工具

常用的一个查看工具,能实时的查看我们系统的一些关键信息的变化:

1
top

实验楼

top 是一个在前台执行的程序,所以执行后便进入到这样的一个交互界面,正是因为交互界面我们才可以实时的获取到系统与进程的信息。在交互界面中我们可以通过一些指令来操作和筛选。

top 显示的第一排

内容 解释
top 表示当前程序的名称
11:05:18 表示当前的系统的时间
up 8 days,17:12 表示该机器已经启动了多长时间
1 user 表示当前系统中只有一个用户
load average: 0.29,0.20,0.25 分别对应 1、5、15 分钟内 cpu 的平均负载

load average 在 wikipedia 中的解释是 the system load is a measure of the amount of work that a computer system is doing 也就是对当前 CPU 工作量的度量,具体来说也就是指运行队列的平均长度,也就是等待 CPU 的平均进程数相关的一个计算值。

假设我们的系统是单 CPU、单内核的,把它比喻成是一条单向的桥,把 CPU 任务比作汽车。

  • load = 0 的时候意味着这个桥上并没有车,cpu 没有任何任务;
  • load < 1 的时候意味着桥上的车并不多,一切都还是很流畅的,cpu 的任务并不多,资源还很充足;
  • load = 1 的时候就意味着桥已经被车给占满了,没有一点空隙,cpu 的已经在全力工作了,所有的资源都被用完了,当然还好,这还在能力范围之内,只是有点慢而已;
  • load > 1 的时候就意味着不仅仅是桥上已经被车占满了,就连桥外都被占满了,cpu 已经在全力工作,系统资源的用完了,但是还是有大量的进程在请求,在等待。若是这个值大于2、大于3,表示进程请求超过 CPU 工作能力的 2 到 3 倍。而若是这个值 > 5 说明系统已经在超负荷运作了。

这是单个 CPU 单核的情况,而实际生活中我们需要将得到的这个值除以我们的核数来看。我们可以通过以下的命令来查看 CPU 的个数与核心数

1
2
3
4
5
#查看物理CPU的个数
#cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc -l

#每个cpu的核心数
cat /proc/cpuinfo |grep "physical id"|grep "0"|wc -l

通过上面的指数我们可以得知 load 的临界值为 1 ,但是在实际生活中,比较有经验的运维或者系统管理员会将临界值定为 0.7。这里的指数都是除以核心数以后的值,不要混淆了

  • 若是 load < 0.7 并不会去关注他;
  • 若是 0.7< load < 1 的时候我们就需要稍微关注一下了,虽然还可以应付但是这个值已经离临界不远了;
  • 若是 load = 1 的时候我们就需要警惕了,因为这个时候已经没有更多的资源的了,已经在全力以赴了;
  • 若是 load > 5 的时候系统已经快不行了,这个时候你需要加班解决问题了

通常我们都会先看 15 分钟的值来看这个大体的趋势,然后再看 5 分钟的值对比来看是否有下降的趋势。

查看 busybox 的代码可以知道,数据是每 5 秒钟就检查一次活跃的进程数,然后计算出该值,然后 load 从 /proc/loadavg 中读取的。而这个 load 的值是如何计算的呢,这是 load 的计算的源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#define FSHIFT      11          /* nr of bits of precision */
#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point(定点) */
#define LOAD_FREQ (5*HZ) /* 5 sec intervals,每隔5秒计算一次平均负载值 */
#define CALC_LOAD(load, exp, n) \
load *= exp; \
load += n*(FIXED_1 - exp); \
load >>= FSHIFT;

unsigned long avenrun[3];

EXPORT_SYMBOL(avenrun);

/*
* calc_load - given tick count, update the avenrun load estimates.
* This is called while holding a write_lock on xtime_lock.
*/
static inline void calc_load(unsigned long ticks)
{
unsigned long active_tasks; /* fixed-point */
static int count = LOAD_FREQ;
count -= ticks;
if (count < 0) {
count += LOAD_FREQ;
active_tasks = count_active_tasks();
CALC_LOAD(avenrun[0], EXP_1, active_tasks);
CALC_LOAD(avenrun[1], EXP_5, active_tasks);
CALC_LOAD(avenrun[2], EXP_15, active_tasks);
}
}

有兴趣的朋友可以研究一下,是如何计算的。代码中的后面这部分相当于它的计算公式

top 的第二行数据,基本上第二行是进程的一个情况统计

内容 解释
Tasks: 26 total 进程总数
1 running 1 个正在运行的进程数
25 sleeping 25 个睡眠的进程数
0 stopped 没有停止的进程数
0 zombie 没有僵尸进程数

来看 top 的第三行数据,这一行基本上是 CPU 的一个使用情况的统计了

内容 解释
Cpu(s): 1.0%us 用户空间进程占用 CPU 百分比
1.0% sy 内核空间运行占用 CPU 百分比
0.0%ni 用户进程空间内改变过优先级的进程占用 CPU 百分比
97.9%id 空闲 CPU 百分比
0.0%wa 等待输入输出的 CPU 时间百分比
0.1%hi 硬中断(Hardware IRQ)占用 CPU 的百分比
0.0%si 软中断(Software IRQ)占用 CPU 的百分比
0.0%st (Steal time) 是 hypervisor 等虚拟服务中,虚拟 CPU 等待实际 CPU 的时间的百分比

CPU 利用率是对一个时间段内 CPU 使用状况的统计,通过这个指标可以看出在某一个时间段内 CPU 被占用的情况,而 Load Average 是 CPU 的 Load,它所包含的信息不是 CPU 的使用率状况,而是在一段时间内 CPU 正在处理以及等待 CPU 处理的进程数情况统计信息,这两个指标并不一样。

来看 top 的第四行数据,这一行基本上是内存的一个使用情况的统计了:

内容 解释
8176740 total 物理内存总量
8032104 used 使用的物理内存总量
144636 free 空闲内存总量
313088 buffers 用作内核缓存的内存量

注意

系统中可用的物理内存最大值并不是 free 这个单一的值,而是 free + buffers + swap 中的 cached 的和

来看 top 的第五行数据,这一行基本上是交换区的一个使用情况的统计了

内容 解释
total 交换区总量
used 使用的交换区总量
free 空闲交换区总量
cached 缓冲的交换区总量,内存中的内容被换出到交换区,而后又被换入到内存,但使用过的交换区尚未被覆盖

再下面就是进程的一个情况了

列名 解释
PID 进程 id
USER 该进程的所属用户
PR 该进程执行的优先级 priority 值
NI 该进程的 nice 值
VIRT 该进程任务所使用的虚拟内存的总数
RES 该进程所使用的物理内存数,也称之为驻留内存数
SHR 该进程共享内存的大小
S 该进程进程的状态: S=sleep R=running Z=zombie
%CPU 该进程 CPU 的利用率
%MEM 该进程内存的利用率
TIME+ 该进程活跃的总时间
COMMAND 该进程运行的名字

注意

NICE 值叫做静态优先级,是用户空间的一个优先级值,其取值范围是-20 至 19。这个值越小,表示进程”优先级”越高,而值越大“优先级”越低。nice 值中的 -20 到 19,中 -20 优先级最高, 0 是默认的值,而 19 优先级最低

PR 值表示 Priority 值叫动态优先级,是进程在内核中实际的优先级值,进程优先级的取值范围是通过一个宏定义的,这个宏的名称是 MAX_PRIO,它的值为 140。Linux 实际上实现了 140 个优先级范围,取值范围是从 0-139,这个值越小,优先级越高。而这其中的 0 - 99 是实时进程的值,而 100 - 139 是给用户的。

其中 PR 中的 100 to 139 值部分有这么一个对应 PR = 20 + (-20 to +19),这里的 -20 to +19 便是 nice 值,所以说两个虽然都是优先级,而且有千丝万缕的关系,但是他们的值,他们的作用范围并不相同

VIRT任务所使用的虚拟内存的总数,其中包含所有的代码,数据,共享库和被换出 swap 空间的页面等所占据空间的总数

在上文我们曾经说过 top 是一个前台程序,所以是一个可以交互的

常用交互命令 解释
q 退出程序
I 切换显示平均负载和启动时间的信息
P 根据 CPU 使用百分比大小进行排序
M 根据驻留内存大小进行排序
i 忽略闲置和僵死的进程,这是一个开关式命令
k 终止一个进程,系统提示输入 PID 及发送的信号值。一般终止进程用 15 信号,不能正常结束则使用 9 信号。安全模式下该命令被屏蔽。
ps工具

ps 也是我们最常用的查看进程的工具之一

1
ps aux

实验楼

1
ps axjf

实验楼

总体了解下会出现哪些信息给我们,这些信息又代表着什么(更多的 keywords 大家可以通过 man ps 了解)

内容 解释
F 进程的标志(process flags),当 flags 值为 1 则表示此子程序只是 fork 但没有执行 exec,为 4 表示此程序使用超级管理员 root 权限
USER 进程的拥有用户
PID 进程的 ID
PPID 其父进程的 PID
SID session 的 ID
TPGID 前台进程组的 ID
%CPU 进程占用的 CPU 百分比
%MEM 占用内存的百分比
NI 进程的 NICE 值
VSZ 进程使用虚拟内存大小
RSS 驻留内存中页的大小
TTY 终端 ID
S or STAT 进程状态
WCHAN 正在等待的进程资源
START 启动进程的时间
TIME 进程消耗 CPU 的时间
COMMAND 命令的名称和参数

TPGID栏写着-1 的都是没有控制终端的进程,也就是守护进程

STAT表示进程的状态,而进程的状态有很多,如下表所示

状态 解释
R Running.运行中
S Interruptible Sleep.等待调用
D Uninterruptible Sleep.不可中断睡眠
T Stoped.暂停或者跟踪状态
X Dead.即将被撤销
Z Zombie.僵尸进程
W Paging.内存交换
N 优先级低的进程
< 优先级高的进程
s 进程的领导者
L 锁定状态
l 多线程状态
+ 前台进程

其中的 D 是不能被中断睡眠的状态,处在这种状态的进程不接受外来的任何 signal,所以无法使用 kill 命令杀掉处于 D 状态的进程,无论是 killkill -9 还是 kill -15,一般处于这种状态可能是进程 I/O 的时候出问题了。

ps 工具有许多的参数,下面解释部分常用的参数

使用 -l 参数可以显示自己这次登录的 bash 相关的进程信息罗列出来

1
ps -l

实验楼

相对来说我们更加常用下面这个命令,他将会罗列出所有的进程信息

1
ps aux

实验楼

若是查找其中的某个进程的话,我们还可以配合着 grep 和正则表达式一起使用

1
ps aux | grep zsh

实验楼

此外我们还可以查看时,将连同部分的进程呈树状显示出来

1
ps axjf

实验楼

自定义所需要的参数显示

1
ps -afxo user,ppid,pid,pgid,command

实验楼

可以使用 man 来获取更多相关的信息

pstree工具

很直接的看到相同的进程数量,最主要可以看到所有进程之间的相关性

1
pstree

实验楼

1
2
3
4
5
6
pstree -up

#参数选择:
#-A :各程序树之间以 ASCII 字元來連接;
#-p :同时列出每个 process 的 PID;
#-u :同时列出每个 process 的所屬账户名称。

实验楼

管理
kill命令

当一个进程结束的时候或者要异常结束的时候,会向其父进程返回一个或者接收一个 SIGHUP 信号而做出的结束进程或者其他的操作,这个 SIGHUP 信号不仅可以由系统发送,可以使用 kill 来发送这个信号来操作进程的结束或者重启等等

用 kill 来操作下一些不属于 job 范畴的进程,直接对 pid 下手

1
2
3
4
5
6
7
8
#首先我们使用图形界面打开了 gedit、gvim,用 ps 可以查看到
ps aux

#使用9这个信号强制结束 gedit 进程
kill -9 1608

#我们再查找这个进程的时候就找不到了
ps aux | grep gedit

实验楼

实验楼

执行顺序

靠该进程的优先级值来判定进程调度的优先级

优先级的值就是 PR 与 nice 来控制与体现

nice 的值我们是可以通过 nice 命令来修改的,而需要注意的是 nice 值可以调整的范围是 -20 ~ 19,其中 root 有着至高无上的权力,既可以调整自己的进程也可以调整其他用户的程序,并且是所有的值都可以用,而普通用户只可以调制属于自己的进程,并且其使用的范围只能是 0 ~ 19,因为系统为了避免一般用户抢占系统资源而设置的一个限制

1
2
3
4
5
6
7
#这个实验在环境中无法做,因为权限不够,可以自己在本地尝试

#打开一个程序放在后台,或者用图形界面打开
nice -n -5 vim &

#用 ps 查看其优先级
ps -afxo user,ppid,pid,stat,pri,ni,time,command | grep vim

还可以用 renice 来修改已经存在的进程的优先级,同样因为权限的原因在实验环境中无法尝试

1
renice -5 pid

用户管理

查看用户
1
2
3
4
5
$ who am i

# 或者

$ who mom likes

3-2.1-1

输出的第一列表示打开当前伪终端的用户的用户名(要查看当前登录用户的用户名,去掉空格直接使用 whoami 即可),第二列的 pts/0pts 表示伪终端,所谓伪是相对于 /dev/tty 设备而言的,前面课程中控制台与终端时的那七个虚拟控制台吗?使用 [Ctrl]+[Alt]+[F1]~[F7] 进行切换的 /dev/tty 设备么,这是“真终端”,伪终端就是当你在图形用户界面使用 /dev/tty7 时每打开一个终端就会产生一个伪终端,pts/0 后面那个数字就表示打开的伪终端序号,你可以尝试再打开一个终端,然后在里面输入 who am i,看第二列是不是就变成 pts/1 了,第三列则表示当前伪终端的启动时间。

还有一点需要注意的是,在某些环境中 who am iwho mom likes 命令不会输出任何内容,这是因为当前使用的 SHELL 不是登录时的 SHELL,没有用户与 who 的 stdin 相关联,因此不会输出任何内容。例如:可能如下图所示,输入这些命令却没有任何提示。

图片描述

此时如果打开一个登录 SHELL 的终端例如 Tmux,然后在新的终端里执行上述命令即可。

1
$ tmux

图片描述

who 命令其它常用参数

参数 说明
-a 打印能打印的全部
-d 打印死掉的进程
-m am imom likes
-q 打印当前登录用户数及用户名
-u 打印当前登录用户登录信息
-r 打印运行等
创建用户

在 Linux 系统里, root 账户拥有整个系统至高无上的权利,比如 新建/添加 用户。

root 权限,系统权限的一种,与 SYSTEM 权限可以理解成一个概念,但高于 Administrator 权限,root 是 Linux 和 UNIX 系统中的超级管理员用户帐户,该帐户拥有整个系统至高无上的权力,所有对象他都可以操作,所以很多黑客在入侵系统的时候,都要把权限提升到 root 权限,这个操作等同于在 Windows 下就是将新建的非法帐户添加到 Administrators 用户组。更比如安卓操作系统中(基于 Linux 内核)获得 root 权限之后就意味着已经获得了手机的最高权限,这时候你可以对手机中的任何文件(包括系统文件)执行所有增、删、改、查的操作。

大部分 Linux 系统在安装时都会建议用户新建一个用户而不是直接使用 root用户进行登录,当然也有直接使用 root 登录的,例如 Kali(基于 Debian 的 Linux 发行版,集成大量工具软件,主要用于数字取证的操作系统)。一般我们登录系统时都是以普通账户的身份登录的,要创建用户需要 root 权限,这里就要用到 sudo 这个命令了。不过使用这个命令有两个前提:

  • 要知道当前登录用户的密码
  • 当前用户必须在 sudo 用户组。

说明:shiyanlou 用户也属于 sudo 用户组。

su,su- 与 sudo

需要注意 Linux 环境下输入密码是不会显示的。

su <user> 可以切换到用户 user,执行时需要输入目标用户的密码,sudo <cmd> 可以以特权级别运行 cmd 命令,需要当前用户属于 sudo 组,且需要输入当前用户的密码。su - <user> 命令也是切换用户,但是同时用户的环境变量工作目录也会跟着改变成目标用户所对应的。

【试一试】 现在我们新建一个叫 lilei 的用户:

1
$ sudo adduser lilei

实验楼的环境目前设置为 shiyanlou 用户执行 sudo 不需要输入密码,通常此处需要按照提示输入 shiyanlou 密码(Linux 下密码输入是不显示任何内容的),shiyanlou 用户密码可以通过 sudo passwd shiyanlou 命令进行设置(建议不要更改,可能会影响后续检查通过)。

【试一试】 现在请你使用passwd命令给 lilei 用户设置密码,其他选项的一些内容你可以选择直接回车使用默认值。

3-2.2-1

这个命令不但可以添加用户到系统,同时也会默认为新用户在 /home 目录下创建一个工作目录:

1
$ ls /home

图片描述

现在已经创建好一个用户,并且可以使用创建的用户登录了,使用如下命令切换登录用户:

1
$ su -l lilei

输入刚刚设置的 lilei 的密码,然后输入如下命令并查看输出:

1
2
3
$ who am i
$ whoami
$ pwd

图片描述

退出当前用户跟退出终端一样,可以使用 exit 命令或者使用快捷键 Ctrl+D

图片描述

用户组

在 Linux 里面每个用户都有一个归属(用户组),用户组简单地理解就是一组用户的集合,它们共享一些资源和权限,同时拥有私有资源,就跟家的形式差不多。当然一个用户是可以属于多个用户组的。

查看属于哪些用户组
  • 方法一:使用 groups 命令
1
$ groups shiyanlou

此处输入图片的描述

其中冒号之前表示用户,后面表示该用户所属的用户组。这里可以看到 shiyanlou 用户属于 shiyanlou 用户组,每次新建用户如果不指定用户组的话,默认会自动创建一个与用户名相同的用户组(差不多就相当于家长的意思)。

  • 方法二:查看 /etc/group 文件
1
$ cat /etc/group | sort

你将看到如下一堆输出,在最下面看到 shiyanlou 的用户组信息:

3-2.3-3

没找到?没关系,你可以使用 grep 命令过滤掉一些你不想看到的结果:

1
$ cat /etc/group | grep -E "shiyanlou"

此处输入图片的描述

  • /etc/group 文件格式说明

    /etc/group 的内容包括用户组(Group)、用户组口令、GID(组 ID) 及该用户组所包含的用户(User),每个用户组一条记录。格式如下:

    group_name:password:GID:user_list

    你看到上面的 password 字段为一个 x,并不是说密码就是它,只是表示密码不可见而已。

    这里需要注意,如果用户的 GID 等于用户组的 GID,那么最后一个字段 user_list 就是空的,这里的 GID 是指用户默认所在组的 GID,可以使用 id 命令查看。比如 shiyanlou 用户,在 /etc/group 中的 shiyanlou 用户组后面是不会显示的。lilei 用户,在 /etc/group 中的 lilei 用户组后面是不会显示的。

将其它用户加入 sudo 用户组

默认情况下新创建的用户是不具有 root 权限的,也不在 sudo 用户组,可以让其加入 sudo 用户组从而获取 root 权限:

1
2
3
# 注意 Linux 上输入密码是不会显示的
$ su -l lilei
$ sudo ls

图片描述

会提示 lilei 不在 sudoers 文件中,意思就是 lilei 不在 sudo 用户组中,至于 sudoers 文件(/etc/sudoers)最好不要动它,操作不慎会导致比较麻烦的后果。

使用 usermod 命令可以为用户添加用户组,同样使用该命令你必需有 root 权限,你可以直接使用 root 用户为其它用户添加用户组,或者用其它已经在 sudo 用户组的用户使用 sudo 命令获取权限来执行该命令。

用 shiyanlou 用户执行 sudo 命令将 lilei 添加到 sudo 用户组,让它也可以使用 sudo 命令获得 root 权限

首先切换回 shiyanlou 用户

1
$ su - shiyanlou

此处需要输入 shiyanlou 用户密码,shiyanlou 的密码可以在右侧工具栏,SSH 直连里看到。

图片描述

当然也可以通过 sudo passwd shiyanlou 进行设置,或者你直接关闭当前终端打开一个新的终端。

1
2
3
$ groups lilei
$ sudo usermod -G sudo lilei
$ groups lilei

图片描述

然后你再切换回 lilei 用户,现在就可以使用 sudo 获取 root 权限了。

图片描述

删除用户和用户组
1
$ sudo deluser lilei --remove-home

3-2.4-1

使用 --remove-home 参数在删除用户时候会一并将该用户的工作目录一并删除。如果不使用那么系统会自动在 /home 目录为该用户保留工作目录。

图片描述

删除用户组可以使用 groupdel 命令,倘若该群组中仍包括某些用户,则必须先删除群组中用户后,才能删除群组

文件权限管理

文件的访问控制权限,即哪些用户和组群可以访问文件以及可以执行什么样的操作。

Unix/Linux 系统是一个典型的多用户系统,不同的用户处于不同的地位,对文件和目录有不同的访问权限。为了保护系统的安全性,Unix/Linux 系统除了对用户权限作了严格的界定外,还在用户身份认证、访问控制、传输安全、文件读写权限等方面作了周密的控制。

在 Unix/Linux 中的每一个文件或目录都包含有访问权限,这些访问权限决定了谁能访问和如何访问这些文件和目录。

查看文件权限

ls 命令

使用较长格式列出文件

1
$ ls -l

图片描述

img

img

  • 文件类型

Linux 里面一切皆文件

正因为这一点才有了设备文件这一说

/dev 目录下有各种设备文件,大都跟具体的硬件设备相关

socket:网络套接字

pipe 管道,这个东西很重要,大家已经多次使用了

软链接文件:链接文件是分为两种的,一种是“软链接”,另一种当然是“硬链接”。软链接等同于 Windows 上的快捷方式

  • 文件权限

读权限,表示你可以使用 cat <file name> 之类的命令来读取某个文件的内容;

写权限,表示你可以编辑和修改某个文件的内容;

执行权限,通常指可以运行的二进制程序文件或者脚本文件,如同 Windows 上的 exe 后缀的文件,不过 Linux 上不是通过文件后缀名来区分文件的类型。

一个目录同时具有读权限和执行权限才可以打开并查看内部文件,而一个目录要有写权限才允许在其中创建其它文件,这是因为目录文件实际保存着该目录里面的文件的列表等信息。

所属用户组权限,是指你所在的用户组中的所有其它用户对于该文件的权限。

  • 链接数

链接到该文件所在的 inode 结点的文件名数目(涉及到 Linux 文件系统的相关概念知识,感兴趣查看 硬链接和软链接的联系与区别)。

  • 文件大小

以 inode 结点大小为单位来表示的文件大小,可以给 ls 加上 -lh 参数来更直观的查看文件的大小。

ls 命令的一些其它常用的用法:

  • 显示除了 .(当前目录)和 ..(上一级目录)之外的所有文件,包括隐藏文件(Linux 下以 . 开头的文件为隐藏文件)。
1
$ ls -a

图片描述

可以同时使用 -a-l 参数:

1
$ ls -al

查看某一个目录的完整属性,而不是显示目录里面的文件属性:

1
$ ls -dl <目录名>
  • 显示所有文件大小,并以普通人类能看懂的方式呈现:
1
$ ls -asSh

图片描述

其中小 s 为显示文件大小,大 S 为按文件大小排序,若需要知道如何按其它方式排序,可以使用 man ls 命令查询。

变更文件所有者

若前面已经执行删除 lilei 用户的命令,这里重新创建一下。

切换到 lilei 用户,然后在 /home/lilei 目录新建一个文件,命名为 iphone11

1
2
3
4
$ su - lilei
$ pwd
$ touch iphone11
$ ls -alh iphone11

可见文件所有者是 lilei :

图片描述

现在切换回到 shiyanlou 用户,使用以下命令变更文件所有者为 shiyanlou

1
2
3
4
# 需要切换到 shiyanlou 用户执行以下操作
$ cd /home/lilei
$ ls iphone11
$ sudo chown shiyanlou iphone11

现在查看,发现文件所有者成功修改为 shiyanlou。

图片描述

修改文件权限

文件的权限有两种表示方式:

  • 方式一:二进制数字表示

img

每个文件有三组固定的权限,分别对应拥有者,所属用户组,其他用户,这个顺序是固定的

文件的读写执行对应字母 rwx,以二进制表示就是 111,用十进制表示就是 7,对进制转换不熟悉的同学可以看看 进制转换。例如我们刚刚新建的文件 iphone11 的权限是 rw-rw-rw-,换成对应的十进制表示就是 666,这就表示这个文件的拥有者,所属用户组和其他用户具有读写权限,不具有执行权限。

如果要将文件 iphone11 的权限改为只有我自己可以用,那么就可以用这个方法更改它的权限。

为了演示,先在文件里加点内容:

1
$ echo "echo \"hello shiyanlou\"" > iphone11

然后修改权限:

1
2
$ chmod 600 iphone11
$ ls -alh iphone11

图片描述

切换到 lilei 用户,尝试写入和读取操作,可以看到 lilei 用户已经不能读写这个 iphone11 文件了:

图片描述

  • 方式二:加减赋值操作
1
$ chmod go-rw iphone11

图片描述

go 还有 u 分别表示 group(用户组)、others(其他用户) 和 user(用户),+- 分别表示增加和去掉相应的权限。

拓展学习

adduseruseradd 的区别

useradd 只创建用户,不会创建用户密码和工作目录,创建完了需要使用 passwd <username> 去设置新用户的密码。

adduser 在创建用户的同时,会创建工作目录和密码(提示你设置),做这一系列的操作。

useradduserdel 这类操作更像是一种命令,执行完了就返回。

adduser 更像是一种程序,需要你输入、确定等一系列操作。

常用快捷键

按键 作用
Ctrl+d 键盘输入结束或退出终端
Ctrl+s 暂停当前程序,暂停后按下任意键恢复运行
Ctrl+z 将当前程序放到后台运行,恢复到前台为命令fg
Ctrl+a 将光标移至输入行头,相当于Home
Ctrl+e 将光标移至输入行末,相当于End
Ctrl+k 删除从光标所在位置到行末
Alt+Backspace 向前删除一个单词
Shift+PgUp 将终端显示向上滚动
Shift+PgDn 将终端显示向下滚动

杂项

  • 环境配置

    1
    2
    sudo apt-get update 
    sudo apt-get install sysvbanner
  • 命令代码

    1
    2
    3
    4
    5
    printerbanner -w 50 A
    /*
    -w 参数指定打印宽度,因为我们的环境在屏幕中显示比较小,必须要加上宽度限制。
    还有两个类似的命令toilet,figlet,也可以安装试用。
    */

aafire

1
2
3
sudo apt-get install libaa-bin
# 提示 command not found ,请自行解决
aafire

gif

cacaview

1
2
3
4
sudo apt-get install caca-utils
cacaview <pic_file>
cacademo
cacafire

asciiview

执行以下命令安装工具包并下载图片:

1
2
3
sudo apt update
sudo apt install -y aview imagemagick
wget https://labfile.oss.aliyuncs.com/courses/1/Linus.png

执行 asciiview [图片文件名] 即可打开图片