Cheat Sheet

解压缩并解包(到指定位置)

1
2
tar -xf archive.tar.(gz|bz2|xz)
tar -xf archive.tar.(gz|bz2|xz) -C /path/to/destination

打包并压缩

1
tar -acf archive.tar.(gz|bz2|xz) file1 file2 directory

zip 文件的压缩解压

1
unzip archive.zip -d tmp/

目录基础

切换目录

cd命令(change directory)用于改变目录:

  • cd <path>:切换到<path>目录下,可以是相对路径或/开头的绝对路径;
  • cd:缺省时会回到家目录~
  • cd .. 返回上一级目录
  • cd -可以回到上一次所处的位置

解释一下 Linux 中的路径表示规则:

  • /开头的路径是绝对路径,表示从根目录开始,例如 /opt/xxx
  • 不以 / 开头的路径是相对路径,表示从当前目录开始,例如 a/b
  • 特殊字符:
    • . 表示当前目录
    • .. 表示上一级目录;
    • ~ 表示当前用户的家目录,例如 /home/<username>

注意:对于目录的表示,是否以 / 结尾的写法(例如 /opt/opt/)在 cd 命令中没有区别,但是在某些命令中会存在区别,倾向于用前者指代目录自身,用后者指代目录中的内容。

查看目录

ls命令(list directory)用于列出目录下的文件,基本用法如下

  • ls <path>:列出目录下的所有文件
  • ls:缺省<path>则会列出当前目录下的文件

除此之外,还需要注意ls支持的一些选项

  • -a--all:除了普通文件,还显示以.开头的隐藏文件(文件夹),可以用ls -a | grep '^\.'过滤,只显示隐藏文件(文件夹)
  • -A--almost-all:和-a类似,但是不再显示...这两个特殊角色
  • -l:以列表模式显示文件信息,每一行包括文件的权限、链接数、所有者、组、文件大小、最后修改时间和文件名,对于链接还会显示指向的文件名
  • -F: 在条目的最后添加一个符号,以指示类型,包括*/=>@|,其中*代表可执行文件,/代表目录,@代表符号链接
  • -color=...:是否使用彩色输出,auto表示自动选择,always表示使用彩色输出,never表示不使用彩色输出,在不支持彩色的终端可能会产生一堆控制字符

这些选项可以组合使用,例如ls -al等效于ls -a -l,也可以通过别名对使用进行简化,例如在CentOS下的bash有如下的默认设置

1
2
alias ls='ls --color=auto'
alias ll='ls -l'

在Ubuntu下的bash有如下的默认设置

1
2
3
4
alias ls='ls --color=auto'
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'

创建目录

mkdir命令(make directory)用于创建空目录:

  • mkdir <path>:新建空目录<path>
  • mkdir -p a/b/c:创建多级目录,如果中间目录不存在则自动创建,通常用于确保某个目录存在

文件基础

创建文件

touch命令可以创建一个空文件,但是如果同名文件已经存在,touch不会修改它的实际内容,但是会更新一下它的创建时间等信息。(摸一下)

1
touch a.txt

查找文件

find命令用于查找文件,下面提供几个例子:

  • 查找/home目录下(包括子目录下)的名称为 a.txt 文件 find /home -name a.txt 也支持文件名通配符
  • 查找/opt目录下(包括子目录下)的拥有者为 username 的文件 find /opt -user username
  • 查找/home目录下(包括子目录下)的大小超过 200M 的文件 find /home +200M (+n 大于 -n 小于,n 等于;支持的单位有 k,M,G 等)

删除文件

rm(remove)命令可以用于删除文件:

  • rm <demo>:删除文件
  • rm -f <demo>:强制删除文件
  • rm -i <demo>:询问互动式删除,需要确认一遍
  • rm -r <path>:递归删除目录和里面的全部内容

对于空目录可以使用 rmdir 命令删除,但是很少使用,因为可以被 rm -r 替代。

修改文件属性

修改文件权限的指令是chmod(change mode),常见用法如下

  • chomd u=rwx,g=rx,o=x filename:u 是拥有者,g 是所在组,o 是其他用户,直接指定文件的各个权限
  • chmod u+x filenamechmod u-x filename:给拥有者增加/撤销该文件的执行权限
  • chmod 777 filename:使用二进制编码来简写,例如 777 代表二进制的111111111,也就是给三类用户所有权限,例如 751 就是111101001

即使是普通用户自己创建的文件,也不会自动拥有它的所有权限,可以使用命令给自己拥有的文件赋予合理的权限,root 用户拥有绝对的能力,即使一个文件非它创建,它也可以修改这个文件的权限。

通常情况下,普通用户对自己的家目录有完全的权限,对/etc/tmp/opt之类的目录中的文件,只有读和执行的权利,只有对目录下属于用户自己的文件拥有写的权限。

最常见的情景是,直接创建的一个 shell 脚本是不能直接执行的(在目录中不是绿色的),使用chmod 777 filename或者类似指令赋予足够的权限,变成绿色。

1
2
3
4
# 这样总可以执行
bash ./a.sh
# 这个必须对a.sh拥有执行权限
./a.sh

修改文件拥有者和文件所在组的指令是chown(change owner),常见用法如下

  • chown newowner filename:修改文件拥有者
  • chown :newgroup filename:修改文件所在组
  • chown newowner:newgroup filename:同时修改文件拥有者和文件所在组

补充:对于chmodchown命令,加上-R选项才会进行递归修改,否则对于目录只会修改目录自身,不会修改其中的子目录和子文件。

查看文本文件

  • cat <file> 查看<file>的全部内容,cat -n <file>会显示行号。通常cat会搭配管道符使用,例如使用cat <file> | more搭配more命令查看大文件
  • head <file> 查看<file>的开头几行(默认显示10行内容,可以加参数修改行数,例如-n 20,下同)
  • tail <file> 查看<file>的末尾几行
  • tail -f <file> 动态更新地查看<file>文件的末尾几行,适合监控动态增长的日志文件,例如tail -f /var/log/syslog
  • more <file> 一页一页地查看 <file>
  • less <file> 一页一页地查看 <file>,而且使用比 more 更便利,支持向前翻页;加载大文件时会部分读取,因此不会很卡。

有时候一个文件太大了,我们只需要截取中间的一部分来输出(如果是头部或尾部,直接使用headtail即可),使用cat全部输出不太方便,在vim中复制又不方便,可以参考下面的做法:

  1. 使用vim查看文件,开启行号显示:set numberview命令会以readonly模式使用vim打开文件)
  2. 确定需要输出的片段的起止行
  3. 执行shell命令:!awk -n "5,10p" filename

如果已经确定了片段的起止行,也可以直接在shell中使用awk -n "5,10p" filename

对于tail -f <file>,在Windows上的powershell有相似的命令,可以用于监控动态增长的日志

1
Get-Content -Path <file> -Wait

编辑文本文件

在服务器上通常使用vimnano来编辑文本文件:

  • vim:过于复杂,这里不做讨论(:q!可以强制退出 vim 并且不做任何修改)
  • nano:比较简单,ctrl+x 退出

对于Ubuntu,很多命令会使用默认编辑器editor打开文件,editor默认指向nano,可以使用下面的命令将其替换为vim,修改环境变量$EDITOR也会有类似效果

1
sudo update-alternatives --config editor

拷贝和移动

cpmv是拷贝和移动命令(copy,move):

  • cp <demo> <path>:把文件或目录 <demo> 拷贝到 <path> 目录(要求目录已经存在)
  • cp <demo1> <demo2>:把文件或目录 <demo1> 拷贝为 <demo2>
  • cp <demo> <path>/<demo2>:上面两种操作的组合:拷贝+重命名
  • mv <demo> <path>:把文件或目录 <demo> 移动到 <path> 目录(要求目录已经存在)
  • mv <demo1> <demo2>:把文件或目录 <demo1> 重命名为 <demo2>
  • mv <demo> <path>/<demo2>:上面两种操作的组合:移动+重命名

注意这些命令的具体行为可能有多种解释,下面以cp为例,对于mv同理

1
cp source target

根据实际情况,有以下几种可能:

  • 如果target不存在,这个命令会被解释为:通过复制source文件来创建新的target文件;
  • 如果target存在:
    • 如果target是一个文件,这个命令会被解释为:使用source文件对原本target文件的内容进行覆盖;
    • 如果target是一个命令,这个命令会被解释为:将source文件复制到target目录下以创建同名文件。

更好的做法是对目录总是使用/结尾

1
cp source target/

这样可以保证target/一定会被解释为目录,如果该目录不存在则会报错,否则会将source文件复制到target目录下以创建同名文件。

符号链接

Linux系统的符号链接(软链接)效果可以大致理解为Windows系统的快捷方式。

基本使用如下(必须加上-s选项)

1
ln -s /path/to/original/file /path/to/symlink

这个命令会创建符号链接/path/to/symlink,它指向的目标文件为/path/to/original/file

对于软链接的访问会直接访问到目标文件,例如使用 vim 打开。对软链接的重命名,得到的结果仍然是一个指向原本目标文件的软链接。 对软链接的删除只会删除符号链接自身,不会影响指向的文件;

注:

  • 如果不使用-s选项就会创建硬链接,硬链接的机制和软链接是完全不同的,它和实际文件在文件系统的底层是等价的,都指向同一个实际存储的文件,例如在 Ubuntu 中,/bin/python3.8/usr/bin/python3.8 是硬链接关系。
  • 如果软链接失效(指向的文件不存在),可能在 ls 命令中显示红色警告;
  • 实际上硬链接和软连接都是文件系统的概念,在Windows中也有同样的概念,Windows中的快捷方式只是Explorer层面提供的行为,而非文件系统中的概念。

文件同步

文件同步的常用命令为 rsync,在大多数 Linux 系统中都已经默认安装。 它可以用于本地计算机与远程计算机之间,或者两个本地目录之间同步文件。

特点:

  • 同步的双方不是对等的,而是有方向性,只使用源目录的内容同步目标目录;
  • 对于远程同步,要求传输的双方都安装 rsync
  • 只传输必要的差异部分,差异检查规则默认是检查文件大小和修改时间。

基本语法

1
rsync [options] source destination

例如本地的两个目录之间同步

1
rsync -av /path/to/source/ /path/to/destination/

从本地同步到远程

1
rsync -avz /local/path/ username@remote_host:/remote/path/

从远程同步到本地

1
rsync -avz username@remote_host:/remote/path/ /local/path/

常用选项:

  • -v:显示详细信息
  • -a:归档模式,保留文件属性
  • -z:传输时压缩数据
  • -n:模拟运行,不进行实际传输(最好加上-v

镜像选项 --delete:在默认情况下,rsync 只确保源目录的内容都复制到目标目录。它不会使两个目录保持完全相同,并且不会删除文件。 如果要使得目标目录成为源目录的镜像副本,必须使用 --delete 参数,这将删除只存在于目标目录、不存在于源目录的文件。

注:这个命令的细节很多,例如 source 是否以 / 结尾,还有各种选项的组合都很复杂,简单了解即可。

创建临时文件/目录

mktemp命令可以用于创建名称随机的临时文件或目录,通常是在/tmp目录下进行创建(系统重启或某些情况下会自动清理), 这个命令对于某些需要临时文件或目录才能工作的脚本非常实用:

  • 临时文件或目录默认只有创建者可以访问,并且创建的文件或目录名称是随机的,安全性较强;
  • 避免了脚本在工作时对主要目录的污染,最好在脚本退出时主动删除这些临时文件或目录。

例如创建并获取临时文件

1
2
3
4
5
6
TMPFILE=$(mktemp) || exit 1
echo "Our temp file is $TMPFILE"

...

rm -f "$TMPFILE"

创建并进入临时目录(将其作为脚本的工作目录)

1
2
3
4
5
6
TMP_DIR=$(mktemp -d)
cd "$TMP_DIR" || exit 1

...

rm -rf "$TMP_DIR"

输出重定向

在Linux的shell中可以通过如下方式将输出重定向:

  • 标准输出重定向到指定文件:>采用覆盖方式,>>采用追加方式。若目标文件不存在则会自动创建,下同。例如cat a.txt > b.txtecho hello >> a.txt
  • 错误输出重定向到指定文件:2>采用覆盖方式,2>>采用追加方式。
  • 合并标准输出和错误输出重定向到指定文件:&>采用覆盖方式,&>>采用追加方式。
  • 一个特别的用法:do_something > /dev/null,将命令产生的标准输出重定向到 /dev/null,相当于将输出内容都丢弃到“垃圾桶”。

有时存在这样的需求:将标准输出流输出到控制台的同时保存到指定文件中记录,可以使用tee命令实现,例如

1
2
ls -l | tee ls.log
ls -l | tee -a ls.log # -a append

补充:对于Window上的powershell,同样也支持使用>>>将标准输出重定向,对于错误输出则需要其它的语法,丢弃标准输出可以使用do_something > $null,或者使用do_something | Out-Null

压缩解压

zip

zipunzip命令用于创建和解压缩.zip格式的压缩文件。

压缩文件的基本使用如下:创建一个名为 archive.zip 的压缩文件,并包含了指定的文件。

1
zip archive.zip file1 file2

需要注意的是,如果直接添加目录,那么只是添加了文件夹自身,不含其中的项!必须使用-r选项才能递归压缩整个目录

1
zip -r archive.zip directory

混合添加文件和文件夹也需要使用-r选项

1
zip -r archive.zip file1 file2 directory

解压缩文件的基本使用如下:解压缩名为 archive.zip 的压缩文件,在当前位置恢复原始文件或目录结构。(可能产生大量文件,污染当前目录)

1
unzip archive.zip

也可以指定解压后存放的目标位置/tmp(如果路径不存在,可能会尝试自动创建)

1
unzip archive.zip -d /tmp

查看压缩文件的内容(不会执行解压操作)

1
unzip -l archive.zip

gzip

gzip命令是Linux最基础的压缩命令,处理逻辑非常简单:

  • 只能压缩或解压单个文件,不支持多个文件或文件夹的处理
  • 不支持指定输出文件的名称,压缩后的输出文件名称就是在原始名称后面加上.gz,解压后的输出文件名称就是原始名称移除.gz
  • 解压只支持处理后缀为.gz的文件,其它后缀会报错;压缩同样不支持对后缀为.gz的文件进行,不会出现.gz.gz的情况
  • 无论是压缩还是解压的操作,默认都会将输入文件自动删除!或者理解为将其原位替换为输出文件(可以通过选项阻止自动删除)

压缩单个文件得到.gz文件

1
2
3
gzip a.txt
# [+] a.txt.gz
# [-] a.txt

解压单个.gz文件(既可以使用-d选项,也可以使用专门的gunzip,两者等效)

1
2
3
4
5
gzip -d a.txt.gz
# [+] a.txt
# [-] a.txt.gz

# or gunzip a.txt.gz

使用-k选项可以抑制对输入文件的自动删除,而是会将其保留

1
2
gzip -k a.txt
# [+] a.txt.gz

gzip只能对单个文件操作,如果传入多个文件,会将其中的每一项分别进行压缩或解压,例如

1
2
3
gzip file1 file2
# [+] file1.gz file2.gz
# [-] file1 file2

也支持使用通配符,例如将当前目录下的所有文件压缩(并自动替换为压缩文件)

1
gzip *

gzip不支持对文件夹的压缩,如果直接传入文件夹名称会被忽略,例如

1
gzip folder/

这个命令是无效的,会被忽略并警告:folder是目录。但是我们可以加上-r选项,此时的处理逻辑是: 递归查找folder/及其子目录中的所有文件,分别将其压缩并替换掉原本的文件(仍然位于相应的子目录中)。

除此之外,还有如下的选项:

  • -v选项可以显示命令执行的细节
  • -l选项可以查看.gz文件的压缩率(不会执行解压)
  • -q选项可以静默执行

归档 tar

tar命令严格来说不属于压缩解压命令,应该被称为打包命令或归档命令,本身不含执行任何的压缩算法,但是实践中通常会通过选项搭配压缩命令来使用,因此也放在这里讨论。

支持的基本选项如下:

  • -c, --create打包得到一个新的归档文件
  • -x, --extract, --get从归档文件中解包
  • -f, --file=ARCHIVE指定将要处理归档文件名-f参数是必选的,后面必须立刻加上文件名参数)
  • -C, --directory=DIR:解包后展开到指定目录(缺省时会展开到当前目录)
  • -v, --verbose:显示指令执行过程中的信息,如果包太大这些信息可能会很乱
  • -t, --list:列出归档文件中的内容(不会将其解包)

打包解包

打包文件/目录为归档文件:

1
tar -cf archive.tar file1 file2 directory

这将创建archive.tar文件,其中包含了指定的文件和目录。

解包归档文件到指定位置(默认的目标路径为当前位置)

1
2
tar -xf archive.tar
tar -xf archive.tar -C /path/to/destination

这将解包archive.tar文件,在目的地中恢复原始文件或目录结构:

  • 如果打包的是当前位置的一个文件夹folder/,那么解包后就会在目标路径创建文件夹./folder/
  • 如果打包的是当前位置的几个文件file1,file2,那么解包后就会在目标路径放置文件file1,file2
  • 如果打包时采用相对路径例如../file1,会移除../,解包之后仍然会把文件或文件夹放置在目标路径
  • 如果打包时采用绝对路径例如/path/to/file,会移除顶层/,解包后会在目标路径下创建path/to/file

查看归档信息

使用-tvf选项可以查看归档文件内容,但是不会将其展开

1
tar -tvf archive.tar

这将显示归档文件 archive.tar 中包含的文件和目录信息,例如

1
2
3
4
5
6
7
8
drwxrwxr-x ubuntu/ubuntu     0 2024-05-16 23:48 folder/
-rw-rw-r-- ubuntu/ubuntu 18 2024-05-16 23:47 folder/file1.txt
-rw-rw-r-- ubuntu/ubuntu 18 2024-05-16 23:47 folder/file-11.txt
-rw-rw-r-- ubuntu/ubuntu 18 2024-05-16 23:47 folder/file-12.txt
drwxrwxr-x ubuntu/ubuntu 0 2024-05-16 23:48 folder/subfolder/
-rw-rw-r-- ubuntu/ubuntu 18 2024-05-16 23:48 folder/subfolder/file-21.txt
-rw-rw-r-- ubuntu/ubuntu 18 2024-05-16 23:48 folder/subfolder/file-22.txt
-rw-rw-r-- ubuntu/ubuntu 18 2024-05-16 23:47 folder/file-13.txt

如果把-v移除,使用tar -tf则只会显示名称,不会显示完整列表,例如

1
2
3
4
5
6
7
8
folder/
folder/file1.txt
folder/file-11.txt
folder/file-12.txt
folder/subfolder/
folder/subfolder/file-21.txt
folder/subfolder/file-22.txt
folder/file-13.txt

这里显示的文件列表和目录结构就是解包之后会创建的所有内容,因此在解压之前有必要先查看一下,确保不会出现生成一大堆文件污染当前目录的问题。

附带压缩解压

可以使用特殊选项在打包解包的同时自动调用对应的压缩和解压命令:

  • -z-gzip:使用gzip,对应后缀为.tar.gz 或缩写的 .tgz后缀
  • -j-bzip2:使用bzip2,对应后缀为.tar.bz2
  • -J-xz:使用xz,对应后缀为.tar.xz

三种压缩命令略有区别:gzip最基础,通用性最强,压缩速度最快;xz压缩效率最高,对应的压缩速度最慢;bzip2大概介于两者之间。

先打包,然后使用某个压缩命令进行压缩

1
2
3
tar -zcf archive.tar.gz file1 file2 directory
tar -jcf archive.tar.bz2 file1 file2 directory
tar -Jcf archive.tar.xz file1 file2 directory

使用某个压缩命令进行解压缩,然后解包

1
2
3
4
5
6
7
tar -zxf archive.tar.gz
tar -jxf archive.tar.bz2
tar -Jxf archive.tar.xz

tar -zxf archive.tar.gz -C /path/to/destination
tar -jxf archive.tar.bz2 -C /path/to/destination
tar -Jxf archive.tar.xz -C /path/to/destination

补充

tar命令实际上支持三种风格的调用方式,在不同的教程中可能使用了不同的风格,例如

1
2
3
4
5
6
7
8
# traditional style
tar cvf archive.tar file1.txt file2.txt

# UNIX style or short-option style
tar -cvf archive.tar file1.txt file2.txt

# GNU style or long-option style
tar --create --verbose --file=archive.tar file1.txt file2.txt

可以混用不同风格的调用方式。如果记不住不同的压缩包后缀对应的压缩解压命令,可以使用便于更直观的长选项来指定,只需要记住通用部分(-cf-xf)即可

1
2
3
tar --gzip -xf archive.tar.gz       # --gzip  = -z
tar --bzip2 -xf archive.tar.bz2 # --bzip2 = -j
tar --xz -xf archive.tar.xz # --xz = -J

对于较新版本的tar命令,支持在压缩时通过-a选项自动判断根据输出文件名判断需要进行的压缩类型,例如

1
tar -acf archive.tar.(gz|bz2|xz) file1 file2 directory

这里的-a是不能省略的,否则tar命令会跳过压缩过程,只进行打包操作。

在解压缩时更不需要指定类型,因为tar会自动根据文件头信息判断。

1
2
tar -xf archive.tar.(gz|bz2|xz)
tar -xf archive.tar.(gz|bz2|xz) -C /path/to/destination

网络文件传输

wget

wget命令可以通过[url]下载对应的网络文件。最基本的用法如下

1
2
3
wget [url]

wget https://download.redis.io/releases/redis-6.0.8.tar.gz

加上-c选项支持断点续传,在下载之前会检查本地是否有未完成的下载,可以继续之前因为网络问题中断的大文件下载。

默认情况下,会使用[url]最后一个斜杠后的内容作为保存的文件名,可以使用-O选项指定下载到本地后保存的文件名

1
2
3
wget -O [filename] [url]

wget -O redis.tar.gz https://download.redis.io/releases/redis-6.0.8.tar.gz

如果原始文件名已经存在,默认情况下会在后面加后缀,不会自动覆盖,但是使用-O明确保存文件名时,会覆盖同名文件。

默认情况下,下载的文件会保存在当前工作目录中,可以使用-P选项将文件保存到指定目录下

1
2
3
wget -P [path] [url]

wget -P /usr/software https://download.redis.io/releases/redis-6.0.8.tar.gz

使用-i选项可以从多个[url]下载多个文件,需要我们把多个目标[url]保存在一个文本文件中,通过-i选项提供给wget

1
wget -i filelist.txt

文本文件例如

1
2
3
https://example.com/file1.zip
https://example.com/file2.zip
https://example.com/file3.zip

scp

scp是基于ssh的文件传输命令(需要保证可以通过ssh正常访问到远程服务器),包括下载和上传文件。最基本的上传和下载命令如下

1
2
3
4
5
# upload
scp [localfile] [user]@[hostname]:[remotedir]

# download
scp [user]@[hostname]:[remotefile] [localdir]

例如

1
2
scp /path/to/local/file user@remote_host:/path/to/remote/dir`
scp user@remote_host:/path/to/remote/file /path/to/local/dir`

对于远程路径,如果使用/开头则是绝对路径,否则基于用户家目录的相对路径,例如user@remote_host:path/to/remote/dir

还支持很多选项,例如:

  • -r:递归执行文件夹的所有文件(打包为压缩包的传输效率更高)
  • -P:指定端口
  • -v:输出详细内容
  • -i:指定ssh连接所使用的私钥文件

除了在本地和服务器之间,scp还支持两个远程服务器之间的文件传输,只要它们都可以通过ssh登陆即可

1
scp [user1]@[hostname1]:[remotefile1] [user2]@[hostname2]:[remotefile2]

curl

curl命令可以通过命令行模拟浏览器的各种网络请求,包括下载和上传文件,功能非常强大,但是返回的结果默认为标准输出流,下面提供几个常见示例。

-o--output: 将内容保存到指定文件中。

1
curl -o output.html http://example.com

-O--remote-name: 将下载的文件命名为远程文件名。

1
curl -O http://example.com/file.zip

-L--location: 跟随网络请求的重定向。

1
curl -L http://example.com

-u--user: 提供基本认证所需的用户名和密码。

1
curl -u username:password http://example.com

-s--silent: 静默模式,不输出进度或错误信息。

1
curl -s http://example.com

补充

有的网站禁止了 curlwget 的直接访问,此时可以加上伪装,例如

1
2
3
curl -A "Mozilla/5.0" <url>

wget --user-agent="Mozilla/5.0" <url>

定时任务

在Linux系统中,crontab是一个非常强大的工具,可以用于在服务器中执行定时任务。

crontab 命令

查看当前用户的crontab任务列表

1
crontab -l

删除当前用户所有的crontab任务

1
crontab -r

编辑当前用户的crontab文件

1
crontab -e

crontab 语法

crontab文件中的每一行对应一个定时任务,其格式如下

1
2
3
4
5
6
7
8
* * * * * command
- - - - -
| | | | |
| | | | +---- 星期几 (0 - 7) (Sunday is both 0 and 7)
| | | +------ 月份 (1 - 12)
| | +-------- 每月的第几天 (1 - 31)
| +---------- 小时 (0 - 23)
+------------ 分钟 (0 - 59)

关于时间频率的语法,例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 每分钟执行一次
* * * * * /path/to/your/command

# 每天凌晨2:30执行一次
30 2 * * * /path/to/your/command

# 每周一凌晨3:00执行一次
0 3 * * 1 /path/to/your/command

# 每周一到周五的每小时执行一次
0 * * * 1-5 /path/to/your/command

# 每月1号凌晨4:00执行一次
0 4 1 * * /path/to/your/command

对于执行的命令,需要特别注意:crontab中的命令被执行时,默认不会加载用户的环境变量,尽量使用绝对路径,或者在脚本中设置所需的环境变量。

为了调试和记录任务执行情况,可以将输出重定向到日志文件,例如

1
* * * * * /path/to/your/command >> /path/to/logfile 2>&1

查询

查询信息

  • clear:清屏(ctrl+l也可以)
  • pwd(print working directory):显示当前目录
  • echo:输出内容到控制台,例如echo 'hello'输出字符串,echo $PATH输出PATH环境变量
  • cal 显示日历表
  • date 输出日期时间,例如Mon Oct 3 21:59:14 CST 2022,注意这里CST是中国时区的缩写
  • history 10 查看最近执行的 10 条历史命令,!3可以再次执行 history 中编号为 3 的命令

关于查看当前用户,有一些相似的命令:

  • who:显示当前所有登录的用户(列表)
  • who -m:显示当前会话的用户
  • whoami:显示当前有效用户(等价于 id -un

补充说明:

  • 如果以 A 用户登陆,然后切换到 B 用户,那么 who 不会显示 Bwho -m 仍然显示 A,但是 whoami 会显示 B
  • who 命令如果加上两个参数(例如who am iwho are you),会被视作 who -m 处理,这是一个早期保留的命令彩蛋。

查询手册

Linux中的命令实在是太多了,记不住用法的时候可以查询自带的手册,使用man命令(manual), 例如man ls可以查询ls命令的用法,直接q就可以退出了。

man手册进行了一个基础的分类,包括:

  1. 用户命令
  2. 系统调用
  3. C库函数
  4. 设备和特殊文件
  5. 文件格式和约定
  6. 游戏和演示
  7. 杂项
  8. 系统管理命令

这种分类可以避免一些重名问题,例如printf既是一个用户命令,也是一个C库函数,我们需要指定分类数字才能正确查询到对应的手册。

1
2
man 1 printf
man 3 printf

缺省时,因为1的优先级更高,只会显示用户命令printf的手册。

1
man printf

用户管理

用户创建/删除

在Ubuntu中可以使用adduserdeluser这两个命令进行基本的用户管理,交互非常方便。

某些Linux发行版例如CentOS可能只有更基础的 useradduserdel 命令可以使用, 这两个命令的使用比较复杂,需要提供很多参数,adduserdeluser可以理解为对它们的封装,在使用上对用户更加友好。

adduser 用于创建新用户并为其设置初始信息

1
sudo adduser <username>

在执行 adduser <username> 命令时,会提示依次输入以下信息:

  • 密码:要求为新用户设置一个密码。
  • 全名:用户的全名(GECOS 信息)。
  • 电话号码:可选的用户电话信息。
  • 其他信息:还会提示填写办公室位置等信息。
  • 确认信息:在信息输入完毕后,会要求确认这些信息是否正确。

除了密码之外的内容可以缺省跳过即可。

adduser 实际会自动执行以下步骤:

  • 创建用户的家目录。(最好在创建之前,保证新用户的家目录是不存在的)
  • 为用户设置默认的 shell(通常是 /bin/bash)。
  • 将用户添加到与其用户名同名的用户组中。
  • 配置 /etc/passwd/etc/shadow/etc/group/etc/gshadow 等文件。

deluser 用于删除用户及其相关信息

1
sudo deluser <username>

删除用户主要是针对用户信息的删除,而不是用户的数据文件。 默认情况下会保留被删除用户的其家目录,以及用户所拥有的所有文件,但是也可以通过特定选项达到彻底删除的效果。

用户切换

使用su user可以切换到user用户,但是不会加载user用户的某些环境变量和配置文件, 更好的做法是su - user,它会完整进行一次user用户的登录过程,并且登陆后默认在user用户的家目录中。

sudo 用户权限

sudo 用户在默认情况下拥有几乎和root用户完全一样的权限,甚至包括修改root用户密码,当然也支持精细化配置具体允许的sudo权限。

下面的命令可以查看当前有哪些sudo用户(属于sudo用户组)

1
getent group sudo

或者用下面的命令也可以

1
grep '^sudo' /etc/group

下面的命令可以把指定用户添加到sudo用户组中

1
usermod -aG sudo alice

除了查询sudo用户组,下面的命令可以测试当前用户是否具有sudo权限

1
sudo -l

系统监控

杀死进程

如果某个进程卡死了,可以使用 ctrl+z 将其挂起,然后使用下面的命令按照关键字查找进程id(关键字可以是用户名或者具体命令的单词)

1
ps -aux | grep <keyword>

然后可以杀死对应进程

1
2
3
4
kill id

# kill force
kill -9 id

CPU和内存监控

free命令可以显示当前系统的内存和交换分区的使用情况。

1
free -h

输出形如

1
2
3
               total        used        free      shared  buff/cache   available
Mem: 7.4Gi 2.1Gi 4.2Gi 3.0Mi 1.1Gi 5.1Gi
Swap: 2.0Gi 3.0Mi 2.0Gi

其中free表示当前完全未使用的内存,available表示当前可以供应用程序立即使用的内存,通常availablefree更大。 两者不等价是因为现代操作系统会使用缓存来提高性能,这些缓存会占用内存。但是一旦新程序需要,缓存就会被释放出来,因此available更具参考价值。

top命令(table of processes)可以实时显示系统进程和资源使用情况,包括 CPU、内存等。(q可以退出)

1
top

输出形如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
top - 21:05:47 up 12 days, 13:50,  2 users,  load average: 1.04, 1.21, 1.66
Tasks: 334 total, 1 running, 333 sleeping, 0 stopped, 0 zombie
%Cpu(s): 3.6 us, 0.1 sy, 0.0 ni, 96.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 26385062+total, 25013684+free, 10826344 used, 2887432 buff/cache
KiB Swap: 32767996 total, 32767996 free, 0 used. 25193814+avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
28967 xxxxxx 20 0 19.467g 8.531g 152140 S 102.0 3.4 151:43.66 MATLAB
31585 xxxxxx 20 0 166192 2876 1944 R 0.3 0.0 0:00.08 top
1 root 20 0 49184 5560 2440 S 0.0 0.0 0:33.60 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.13 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:00.25 ksoftirqd/0
8 root rt 0 0 0 0 S 0.0 0.0 0:00.60 migration/0
9 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh
10 root 20 0 0 0 0 S 0.0 0.0 2:23.79 rcu_sched
11 root rt 0 0 0 0 S 0.0 0.0 0:03.06 watchdog/0

对于头部信息的解读:

  • 第一行:系统时间,系统运行时间,当前登录的用户数量,系统负载平均值(低于1代表空闲,高于1代表繁忙)
  • 第二行:当前总进程数,正在执行的进程数
  • 第三行:进程占用的 CPU 百分比
    • 3.6 us代表用户空间进程占用,包括大部分应用程序;
    • 0.1 sy代表内核空间进程占用,用于执行系统内核和驱动程序等;
    • 96.4 id代表CPU空闲时间占比。
  • 第四行:系统总内存量,空间的内存量,已使用的内存量

对于进程列表的解读:

  • PID:进程ID。
  • USER:进程所有者的用户名。
  • PR:进程优先级。
  • NI:进程的 nice 值(优先级调整值)。
  • VIRT:进程使用的虚拟内存总量。
  • RES:进程使用的常驻内存量。
  • SHR:进程使用的共享内存量。
  • S:进程状态(例如:R 运行、S 睡眠、D 不可中断睡眠、Z 僵尸、T 停止)。
  • %CPU:进程消耗的 CPU 百分比。(可能超过百分之一百,这是并行的原因)
  • %MEM:进程使用的内存百分比。
  • TIME+:进程使用的总 CPU 时间,单位为秒。
  • COMMAND:执行进程的命令名称或命令行。

除了原始的top,还有一些使用更方便的同类工具(htopbtop),有更加丰富的功能,但是通常需要额外下载,而且对旧系统可能有兼容性问题。

cat /proc/cpuinfo命令可以直接获取CPU的信息,使用lscpu命令也可以获取CPU信息,可读性更高。

硬盘监控

lsblk命令(list block)可以列出所有块设备及其挂载点

1
lsblk

输出内容形如

1
2
3
4
5
6
7
8
9
10
11
12
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda 8:0 0 3.7T 0 disk
├─sda1 8:1 0 1M 0 part
├─sda2 8:2 0 1G 0 part /boot
└─sda3 8:3 0 3.7T 0 part
├─centos-root 253:0 0 300G 0 lvm /
├─centos-swap 253:1 0 31.4G 0 lvm
└─centos-home 253:2 0 17.9T 0 lvm /home
sdb 8:16 0 14.6T 0 disk
└─centos-home 253:2 0 17.9T 0 lvm /home
sr0 11:0 1 1024M 0 rom
sr1 11:1 1 1024M 0 rom

使用df命令(disk free)可以展示文件系统的硬盘空间使用情况

1
df -h

输出内容形如

1
2
3
4
5
6
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs 32G 0 32G 0% /dev
/dev/sda3 560G 194G 338G 37% /
/dev/sda1 477M 291M 157M 65% /boot
/dev/sdb1 16T 12T 3.0T 80% /home
...

这里的输出表明根目录/对应560G空间,已经使用了 37% 的空间, 用户目录/home对应16T空间,已经使用了 80% 的空间。

使用du命令(disk usage)可以展示test/目录下所有子项的硬盘空间使用情况

1
du -h test/

如果显示子项太多,可用使用-s选项则会进行汇总

1
du -sh test/

可以对输出结果按照大小进行排序

1
du -sh test/ | sort -hr