# Linux 系统的使用
TIP
这里以 Ubuntu 20.04 系统为基础,其他系统的操作可能会有不同。
webmin -- web 服务器管理工具
# Linux 启动流程
# 系统初始化
init 进程运行以后将陆续执行系统中的其他程序,不断生成新的进程,这些进程称为 init 进程的子进程,反过来说,init 进程是这些进程的父进程,当然,这些子进程也可以进一步生成各自的子进程,依次不断繁衍下去,最终构成一棵枝繁叶茂的进程树,共同为用户提供服务。
init 进程正是维持整个 Linux 操作系统运行的所有进程的“始祖”,因此 init 进程是不允许被轻易终止的,需要切换不同的系统运行状态时,可以向 init 进程发送正确的执行参数,由 init 自身来完成相关操作。
# Systemd
Systemd,即 system daemon,是 Linux 操作系统的一种 init 软件(最新的),作用是提高系统的启动速度,尽可能启动较少的进程,尽可能更多进程并发启动。
作为 init 进程,Systemd 进程自然永远是 1 号进程
Systemd 对应的进程管理命令有:
systemctl
,主命令,用于管理系统和服务单元。journalctl
,用于访问 Systemd 日志。systemd-analyze
,用于查看启动耗时。hostnamectl
,于查看当前主机的信息。localectl
,用于查看本地化设置。timedatectl
,用于查看当前时区设置。loginctl
,用于查看当前登录的用户。localectl
,用于查看本地化设置。- ...
# 添加 Unit
使用包管理器(如 apt)安装某些软件的时候,包管理器会帮我们将这些软件服务添加到 Systemd(即创建 xxx.service 文件),但如果是源码安装的软件,就不会有人帮我们去添加服务单元,这时候就需要我们手动添加服务单元到 Systemd 进行管理。
以 .service
为后缀的单元文件,封装了一个被 Systemd 监视与控制的进程。
添加步骤:
- 在
/etc/lib/systemd/[username]/
中添加 xxx.service 文件。- 这里可以把 .service 文件放在自定义位置,然后软链到 Systemd 扫描目录。
- 执行
systemctl enable xxx.service
(设置开机启动:下次开机时,该服务会被启动)
.service 服务文件
# 文件主要有 3 部分: Unit、Service、Install
# 控制单元,主要包括服务描述、启动顺序、依赖关系
[Unit]
Description=<description about service> # 描述服务
Before=<unit files> # 在什么服务之前启动
After=<unit files> # 在什么服务之后启动
# After 和 Before 字段只涉及启动顺序,不涉及依赖关系
Requires=<unit files> # 表示“强依赖”关系。列在其中的Uint模块会在这个服务启动的同时被启动,如果其中任意一个启动失败,这个服务会被终止。某服务停止运行或退出,该服务也必须停止运行。
Wants=<unit files> # 表示“弱依赖”关系。某服务停止运行或退出不影响该服务继续运行;
Conflicts=<unit files>
PartOf=<unit files> # 该参数仅用于单元的停止或重启。
Documentation=<url> # 文档位置
# 服务定义
[Service]
Type=<simple, exec, forking, oneshot, dbus, notify, idle>
ExecStart=<path to executable file> # 启动程序时执行的命令。
ExecReload=<path to executable file> # 重启服务执行的命令。
ExecStop=<path to executable file> # 停止服务时执行的命令。
ExecStartPre=<path to executable file> # 启动服务之前执行的命令。
ExecStartPost=<path to executable file> # 启动服务之后执行的命令。
ExecStopPost=<path to executable file> # 停止服务之后执行的命令。
User=<user> # 指定运行服务的用户
Restart=<condition>
# Restart,定义 sshd 退出后,systemd 的重启方式。默认值:no
RestartSec=<> # 重启服务之前需要等待的秒数。
Environment=<>
EnvironmentFile=<>
# 安装部分,用来定义如何启动以及是否开机启动
[Install]
WantedBy=multi-user.target
# WantedBy 表示该服务所在的Target。Target的含义是服务组,表示一组服务。“WantedBy=multi-user.target”指的是服务所在的Target是multi-user.target
# multi-user.target是systemd默认启动的Target,表示在这个组里的所有服务,都开机启动。
# Target 就是一个 Unit 组,包含许多相关的 Unit 。启动某个 Target 的时候,Systemd 就会启动里面所有的 Unit。
Alias=<alias> # 当前 Unit 可用于启动的别名。
Also=<> # 当前 Unit 被 enable/disable 时,会被同时操作的其他 Unit
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
30
31
32
33
34
35
36
37
38
Systemd 有系统和用户级别:
- 系统,
/usr/lib/systemd/system/
- 用户,
/etc/lib/systemd/[username]/
一般系统管理员手动创建的单元文件建议存放在 /etc/systemd/system/
目录下面。
# systemctl
系统服务控制,systemd control,它提供了一组子命令来管理单个的 unit,其命令格式为:
systemctl [command] [unit]
command 主要有:
start
:立刻启动后面接的 unit。stop
:立刻关闭后面接的 unit。restart
:立刻关闭后启动后面接的 unit,亦即执行 stop 再 start 的意思。reload
:不关闭 unit 的情况下,重新载入配置文件,让设置生效。enable
:设置下次开机时,后面接的 unit 会被启动。disable
:设置下次开机时,后面接的 unit 不会被启动。status
:目前后面接的这个 unit 的状态,会列出有没有正在执行、开机时是否启动等信息。is-active
:目前有没有正在运行中。is-enable
:开机时有没有默认要启用这个 unit。kill
:不要被 kill 这个名字吓着了,它其实是向运行 unit 的进程发送信号。show
:列出 unit 的配置。mask
:注销 unit,注销后你就无法启动这个 unit 了。unmask
:取消对 unit 的注销。
# 目录结构
# 挂载
hda1
、sda1
- hd(IDE 即 ATA 并行接口)/sd(scsi、SATA 串行接口),表示是硬盘
- a 磁盘序号 a-z,表示第一块硬盘
- 1 分区序号,表示第一个分区
# 理论先行
因为外存中的数据是不能直接和 CPU 进行交互的,所以需要将外存中的数据加载到内存中,Linux 内核在内存中预留了一个空目录,将块设备的根目录 /
与这个空目录绑定,这样根目录与内存就有了关联,发生在根目录以及在根目录下的操作,都会实际发生在块设备上。
每个块设备都有自己的文件系统,比如根目录下有一个简易系统组成:/
下包含 /home
、/usr
、/proc
、/dev
、/etc
等等。
如果你还有第二块硬盘(第一块硬盘已经绑定基本的文件系统),这时,你感觉你的 /home
需要扩大一下容量,那么你就可以将你的第二块硬盘挂载到第一块硬盘的文件系统中的 /home
目录,当你挂载上之后,后面你对 /home
目录的操作实际就会发生在第二块硬盘上。
当你在 /home
挂载了第二块硬盘,那么后面你对 /home
目录的操作实际就会发生在第二块硬盘上,挂载之前 /home
下的数据还在,只不过你使用不了了,如果你将第二块硬盘 umount,那么 /home
又重新关联到了第一块盘(之前的数据)。
# 磁盘挂载
磁盘分区: 在 Linux 中,磁盘是通过分区来使用的。分区是将一个硬盘划分成几个逻辑部分来使用,在每个分区中可以存储不同的文件系统。因此,挂载磁盘前,需要先对磁盘进行分区,磁盘分区的过程可以通过命令行工具或图形界面工具来完成。这里使用
fdisk
分区工具操作。
主要步骤为:
- 添加磁盘
- 添加后使用
fdisk -l
查看
- 添加后使用
- 创建分区
- 使用
fdisk /dev/sdxxx
对指定的磁盘执行分区操作,进入交互式操作(按m
打印所有菜单) - 创建步骤 -> n -> p ->
开始扇区大小
直接回车表示使用默认 ->结束扇区大小
直接回车 -> wq 保存并退出
- 使用
- 格式化分区,建立文件系统
mkfd.xxx [分区]
mkfs.ext4 /dev/sda1
或者mkfs -t ext4 /dev/sda1
将分区格式化为 ext4 文件系统 用这个!mkfs.xfs /dev/sdb1
将分区格式化为 XFS 文件系统。- 调用
mkfs -t ext4 /dev/sda1
会调用mkfs.ext4
命令,等同于直接执行mkfs.ext4 /dev/sda1
。
- 创建挂载点并挂载
- 自定义一个挂载点然后挂载,
mount /dev/sdb1 /mydir
- 自定义一个挂载点然后挂载,
- 自动挂载
- 新增内容到
/etc/fstab
- 新增内容到
# 挂载相关命令
# fdisk 命令
fdisk (opens new window),固定磁盘(Fixed Disk) 或 格式化磁盘(Format Disk),它是命令行下允许用户对分区进行查看、创建、调整大小、删除、移动和复制的工具。它支持 MBR、Sun、SGI、BSD 分区表,但是它不支持 GUID 分区表(GPT)。它不是为操作大分区设计的。
fdisk
允许我们在每块硬盘上创建最多四个主分区。它们中的其中一个可以作为扩展分区,并下设多个逻辑分区。1-4 扇区作为主分区被保留,逻辑分区从扇区 5 开始。
-l
list all 分区信息。fdisk /dev/sdb
对指定的磁盘进行分区m
查看菜单n
新建分区d
删除分区
# lsblk 命令
lsblk
,list block devices,展示所有块设备信息、分区情况、挂载点等。
blkid
,查看块设备的 UUID、名称、文件系统等。
# mount
mount /dev/sdb1 /mydir
,将分区挂载到指定挂载点上。
umount
是卸载,可以通过挂载点或者设备参数进行卸载 umount /mydir
or umount /dev/sda1
# /etc/fstab
dev/sdb1 /mnt/sdb ext4 defaults 0 0
# 参数解释:
# 第1列: 挂载设备
# (1) /dev/sda5
# (2) UUID=设备的uuid rhel6/7的默认写法 同一台机器内唯一的一个设备标识
# 第2列: 挂载点
# 第3列: 文件系统类型
# 第4列: 文件系统属性
# 第5列: 是否对文件系统进行磁带备份:0 不备份
# 第6列: 是否检查文件系统:0 不检查
2
3
4
5
6
7
8
9
10
# 配置 JDK
安装
sudo add-apt-repository ppa:openjdk-r/ppa sudo apt-get update # 有的系统这一句即可。 sudo apt-get -y install openjdk-8-jdk
1
2
3
4
5配置环境变量
# 打开配置文件 sudo vi /etc/profile # 在文件最末尾追加以下内容: export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib export PATH=.:${JAVA_HOME}/bin:$PATH
1
2
3
4
5
6
7
# 环境变量
执行 export
返回系统中所有的环境变量。
# PATH
为什么使用 rm、rmdir、ls 等命令时,无论当前位于哪个目录,都可以直接使用, 而无需指明命令的执行文件所在的位置(绝对路径)呢?其实,这是 PATH 环境变量在起作用。
首先,执行 echo $PATH
,会返回 PATH 环境变量的所有值。
➜ ~ echo $PATH
/usr/java/jdk8/bin:/home/user/.gvm/pkgsets/go1.16.5/global/bin:/home/...
2
PATH 环境变量的内容是由一堆目录组成的,各目录之间用冒号 :
隔开。
当执行某个命令时,Linux 会依照 PATH 中包含的目录依次搜寻该命令的可执行文件,
一旦找到,即正常执行;反之,则提示无法找到该命令。
如果在 PATH 包含的目录中,有多个目录都包含某命令的可执行文件,那么会 执行先搜索到的 可执行文件。
换言之:你的
rm
命令实际上是在/usr/bin/rm
这个位置,但是你可以在任何目录下使用它, 这是因为/usr/bin/
目录已经存在于环境变量 PATH 中,当你运行rm
命令的时候,系统会去直接去 PATH 中去查找, 找到就执行,找不到就报错。先找到的就直接执行,不再继续查找了。
➜ ~ which rm
/usr/bin/rm
2
注意
只要你的命令(脚本)在 PATH
声明的路径内,就可以全局使用。这时候,你可能会选择 ln -s <your_script> <一个已经声明的 PATH 路径>
,这样就可以不用配置环境变量,从而使得你的脚本全局可用。比如,你可能会将你下载的一个第三方脚本软链到 /usr/bin
目录,因为该目录已经配置到 PATH
,所以你将脚本软链过去,就可以实现命令全局可用。
但是,软链接一定要用 绝对路径 !!!
# 修改 PATH
// TODO
# crond
Linux 中有些服务以
d
结尾,d
是daemon
的缩写,说明它自己是个守护进程(daemon
) ,它在后台运行,一般都是用来做服务端程序(服务 service)。 如mysqld
代表是mysql
数据库服务的守护进程。
crond
是 Linux
下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与 Windows 下的计划任务类似,当安装完成操作系统后,默认会安装此服务工具并自动启动crond
进程,crond
进程每分钟会定期检查是否有要执行的任务,如果有要执行的任务,则自动执行该任务。
crond
的最小粒度是分钟,该服务每分钟会去检查一下任务列表文件,然后执行需要执行的脚本。对应的 cron 表达式只有 5 级:* * * * *
,分别是 minute hour day month week command
。
# crontab
crond
服务的命令是 crontab
,常用参数如下:
crontab -e
,编辑任务文件。常用crontab -l
,查看任务文件。crontab -r
,删除任务文件。crontab -i
,删除任务文件(交互性的,简单说就是会让确认)。crontab -u
,编辑任务文件,使用-u
指定用户,如果不加这个参数,默认操作的是当前用户的文件。
注意:任务文件中存放了某个用户下配置的所有 cron 任务,如果只是移除某个任务,只需要使用 crontab -e
移除要删除的任务就行了。
# 执行日志
/var/log/cron
# crontab 文件
系统级别 crontab 文件在
/etc/crontab
,用户自定义 crontab 文件在/var/spool/cron/
下,名字和用户名一致。
# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h dom mon dow command
* * * * * date >> /opt/time.txt # 每一分钟执行一次
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 用户管理
添加新用户
格式:
useradd [选项] [username]
删除用户
格式:
userdel [选项] [username]
修改账号
格式:
usermod [选项] [username]
修改密码
格式:
passwd
# /proc
在 Linux 系统中,/proc
(process,进程) 目录是一个特殊的文件系统,用于存储有关系统内核和进程的信息。在 /proc
目录下存储了大量的系统信息文件,其中包括表示进程的文件夹、文件以及符号链接等。
另外,在 Linux 系统中,每个进程都会有一个数字标识符,称为进程ID(PID
)。而在 /proc
目录中,每个进程的信息都会被存储在以进程ID命名的文件夹下。
# fd文件描述符
TIP
首先,再次明确,Linux 中一切皆文件。
即使是一个设备,比如键盘、显示器等在 Linux 系统中都只是一个文件。
/proc
目录下有个子目录叫做fd
,也就是文件描述符,主要用来了解进程使用的文件和网络连接等信息。
文件描述符,即 fd
-> file descriptor, fd
是 Linux 系统中对已打开文件的一个抽象标记,所有 I/0 系统调用对已打开文件的操作都要用到它。这里的“文件”仍然是广义的,即除了普通文件和目录外,还包括管道、FIFO(命名管道)、Socket、终端、设备等。
文件描述符是一个与打开文件或资源相关联的较小的非负整数,并且 0、1、2 三个描述符总是默认分配给标准输入、标准输出和标准错误。这就是常用的 nohup./my script>my script.log 2>&1 &
命令里 2 和 1 的由来。
像 0、1、2 这种文件描述符,也可以理解为句柄,类似文件的指针的指针,可以简单理解为文件的指针(虽然不太恰当),就是根据这个能找到实际操作的文件。
当一个进程打开一个文件或创建一个网络连接时,系统会为这个打开的资源分配一个文件描述符。通过 /proc
目录中的 fd
文件夹,可以査看进程当前打开的文件描述符以及与之关联的文件或资源。
在进程的 fd
文件夹中,每个文件描述符会以符号链接的形式存在。这些符号链接会指向进程所打开的文件或资源的真实路径。通过查看这些符号链接,可以看到进程当前正在访问的文件或资源的详细信息。
# 重定向
# 前言
例子理解:
# test.sh 文件内容:
read name
echo "name inputed by you is" $name
# 执行 test.sh
bash test.sh
# 首先程序会让你输入一个值,保存到变量 name 中,比如输入 xiaoming,然后回车,
# 然后就会输出 name inputed by you is xiaoming
2
3
4
5
6
7
8
在执行上述脚本的过程中,你可以简单的理解为从你键盘输入的内容到了标准输入(stdin)文件中,然后将标准输入文件的内容复制到了标准输出(stdout)文件中,然后标准输出文件一般对应的是你的显示器文件,所以内容就在显示器中输出了,当然,实际比这复杂得多。
标准错误则是用来输出错误信息用的,比如你输入一个不存在的命令,这时候错误信息就会输出到标准错误(stderr)文件中,它一般对应的也是显示器文件,所以错误信息就输出到显示器了。
# 重定向
重定向就是将本该输出到你的显示器的内容,输出到你指定的位置。
一般来说,默认标准输入(0)对应你的键盘,标准输出(1)对应你的显示器,标准错误(2)也对应你的显示器。
比如你输入一个命令 ls /test
,这种情况下,默认就是将 ls /test
命令的执行结果输出到了你的显示器(默认的),但是当你使用 ls /test > a.txt
命令时,这表示你重新定义了命令执行结果的输出位置,即将命令执行结果重定向到 a.txt 文件中,而不是输出到显示器了。
>
- 将命令执行结果的 标准输出 重定向到一个位置,如果不存在则创建,如果存在,则直接覆盖之前的内容。
2>
- 将命令执行结果的 标准错误 重定向到一个位置,如果不存在则创建,如果存在,则直接覆盖之前的内容。
>>
- 将命令执行结果的 标准输出 重定向到一个位置,如果不存在则创建,如果存在,则追加到原来内容的后面。
2>>
- 将命令执行结果的 标准错误 重定向到一个位置,如果不存在则创建,如果存在,则追加到原来内容的后面。
&>
或&>>
- 将命令执行得到的标准输出和标准错误都重定向到一个位置
注意:>
等同于 1>
,即将标准输出重定向到指定位置,因为默认操作的是标准输出,所以 1>
可以简写为 >
。2>
则必须写成 2>
,不可以简写为 >
,同理,>>
等于 1>>
,2>>
只能是 2>>
。
# 守护进程 daemon
- 前台任务(foreground job),它会独占命令行窗口,只有运行完了或者手动中止,才能执行其他命令。
jobs
显示当前暂停的进程- 在一个命令后面加上
&
,可以将一个前台任务变成后台任务。 - 如果想将一个正在运行的任务改成后台任务
CTRL + Z
,强制当前进程转为后台,并使之挂起(暂停)jobs -l
查看所有的后台进程。bg
命令(让最近一个暂停的"后台任务"继续执行),bg %<job 号>
继续执行指定 job。fg
可以将命令转到前台执行。
# 使用 nohup 启动后台进程
nohup <command>
,no hang up,不挂起。
这个命令不会将启动的任务变成一个后台任务,所以在命令的最后要加一个 &
符号,使启动的任务变成一个后台任务。
nohup java -jar classwork-0.0.1-SNAPSHOT.jar &> classwork.text &
nohup java -jar classwork-0.0.1-SNAPSHOT.jar > classwork.text 2>&1 &
- 上面两种方式一样效果。
# root 用户密码
Ubuntu 默认 root 密码是随机的,即每次开机都有一个新的 root 密码。我们可以在终端输入命令 sudo passwd
,然后输入当前用户的密码。终端会提示我们输入新的密码并确认,此时的密码就是 root 新密码。修改成功后,输入命令 su root
,再输入新的密码就 ok 了。
# 允许普通用户使用 sudo
Ubuntu 下普通用户用 sudo
执行命令时报 "xxx is not in the sudoers file.This incident will be reported" 错误,
解决方法就是在 /etc/sudoers
文件里给该用户添加权限。如下:
切换到 root 用户下。
/etc/sudoers
文件默认是只读的,对 root 来说也是,因此需先添加 sudoers 文件的写权限,命令是:chmod u+w /etc/sudoers
。编辑 sudoers 文件:
vi /etc/sudoers
。 找到这行root ALL=(ALL) ALL
,在他下面添加xxx ALL=(ALL) ALL
(这里的 xxx 是你的用户名)ps: 这里说下你可以 sudoers 添加下面四行中任意一条:
youuser ALL=(ALL) ALL %youuser ALL=(ALL) ALL youuser ALL=(ALL) NOPASSWD: ALL %youuser ALL=(ALL) NOPASSWD: ALL
1
2
3
4第一行: 允许用户 youuser 执行 sudo 命令(需要输入密码). 第二行: 允许用户组 youuser 里面的用户执行 sudo 命令(需要输入密码). 第三行: 允许用户 youuser 执行 sudo 命令,并且在执行的时候不输入密码. 第四行: 允许用户组 youuser 里面的用户执行 sudo 命令,并且在执行的时候不输入密码.
撤销 sudoers 文件写权限,命令:
chmod u-w /etc/sudoers
# SSH
Secure Shell 的缩写,即安全外壳协议。
它是一种专为远程登录会话和其他网络服务提供安全性的协议,利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。
从客户端来看,SSH 支持两种级别的安全验证:
# 密码口令
- 远程主机收到用户请求,将自己的公钥发送给用户。
- 用户使用这个公钥加密自己的密码,发送到远程主机。
- 远程主机使用自己的私钥解密密码并验证。
风险: 因为 SSH 不像 HTTPS,SSH 的公钥是没有证书中心(CA)公证的,是自己签发的,所以可能会有被别人截获你的登录请求,并冒充远程主机的风险。 即:口令登录是只要你知道自己帐号和口令,就可以登录到远程主机。所有传输的数据都会被加密,但是不能保证你正在连接的服务器就是你想连接的服务器。 可能会有别的服务器在冒充真正的服务器,也就是受到“中间人”这种方式的攻击。
解决方式: know_hosts
# 公钥私钥登录
大概原理如下,并非完全一致,但主要思想是一样的
- 客户端生成公钥和私钥
- 用户将自己的公钥放到远程主机
- 用户在客户端向远程主机发起连接请求(携带自己的公钥),远程主机查看该公钥是否在自己的列表里,如果在,生成随机数(challenge),使用公钥加密,返回给客户端。
- 客户端使用私钥解密,发送解密后的随机数(challenge)给远程主机。
- 远程主机验证客户端返回的随机数(challenge)正确性。
# .ssh 目录
使用 ssh-keygen
在主机上生成公钥和私钥,默认会生成在 .ssh
目录里。
该目录会存在以下文件:
is_rsa
,私钥id_rsa.pub
,公钥- authorized_keys,远程主机的公钥,一行一个
- know_hosts ,被连接主机的公钥,下次连接时会核对公钥是否一致,如果不一致,会发出警报
# authorized_keys
客户端想要连接远程主机,需要将客户端生成的公钥放到远程主机,这里放的就是远程主机的 authorized_keys
目录。
只有这样,用户才可以使用自己的私钥免密登录远程主机。
使用 ssh-copy-id -i <file_path> user@hostname
将指定的公钥上传到待连接服务器的 authorized_keys
目录。
这里 ssh-copy-id
会自动给远程主机的相关目录配置权限。
# know_hosts
第一次登录远程主机的时候,系统会出现以下提示:
这里是说,无法确认 8.*.*.182
主机的真实性,只知道公钥指纹,是否继续连接?
公钥指纹:因为公钥长度较长,不方便比对,所以将其使用 MD5 摘要后得到一个 128 位的指纹,以方便比对。
如果选择继续连接的话,这个公钥就会保存在 .ssh/known_hosts
中,下次再连接这个主机的时候,系统在本地的 know_hosts
中检查,如果存在,就不会再弹出警告,直接提示输入密码。
除了每个用户都有自己的 know_hosts
文件外,系统也会有一个 /etc/ssh/ssh_known_hosts
(通常是),用来保存一些公用的可信赖主机公钥。
问题:
- 第一次连接远程主机时,仍可能会遭到“中间人”攻击。
- 由于
know_hosts
需要用户来选择是否继续连接,但是用户并不知道远程主机的公钥指纹,所以这就需要远程主机公开自己的公钥指纹,以便用户自行核对。 - 一些自动化脚本中,需要自动登录到远程主机,但是
know_hosts
机制必须手动输入 yes 确认,这就无法实现脚本自动化。这时,我们可以通过修改 ssh_config 配置文件,跳过know_hosts
的询问机制,将# StrictHostKeyChecking ask
改为StrictHostKeyChecking no
就可以了。
# SSH config
SSH 可以从以下途径获取配置参数:
- 命令行选项
- 用户配置文件
~/.ssh/config
- 系统配置文件
/etc/ssh/ssh_config
配置文件选项 (opens new window),也可以使用 man ssh config
命令去查看选项详情。
用户配置文件示例:
# gitee
Host gitee # 别名
HostName gitee.com # 真实地址
IdentityFile ~/.ssh/id_rsa_github # 使用哪个私钥文件
# gitlab
Host gitlab.xxx.com
HostName gitlab.xxx.com
IdentityFile ~/.ssh/id_rsa_gitlab
# github
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_github
# aliyun
Host ali
HostName *.*.*.* or hostName
User username
IdentityFile ~/.ssh/id_rsa_aliyun
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
配置别名以后就可以使用 ssh ali
直接进行服务器的登录。
注意: 配置了别名以后,要使用别名代替域名,没有配置别名的时候,才可以直接使用域名。否则会报错。
# SCP
scp,即 secure copy。
它是 linux 系统下基于 ssh 登陆进行安全的远程文件拷贝的命令,和它类似的命令有 cp, 不过 cp 只是在本机进行拷贝不能跨服务器,而且 scp 传输是加密的。
scp 是加密的,rcp 是不加密的,scp 是 rcp 的加强版。
格式: scp [参数] [原路径] [目标路径]
示例:将本机桌面的一张图片 aa.img 拷贝到远程主机的某个位置
scp /Desktop/aa.img user@8.*.*.112:/home/user/Desktop/
常用参数:
- -B 使用批处理模式(传输过程中不询问传输口令或短语)
- -C 允许压缩。(将 -C 标志传递给 ssh,从而打开压缩功能)
- -p 保留原文件的修改时间,访问时间和访问权限。
- -r 递归复制整个目录。
- -P port 注意是大写的 P, port是指定数据传输用到的端口号。
# SCP 和 SFTP
# SFTP
SSH 文件传输协议,SSH File Transfer Protocol。
也称 Secret File Transfer Protocol,安全文件传送协议,Secure FTP 或 SFTP。
和 scp 的作用一致,都是可以进行上传下载的命令。
sftp 无法一次性创建多级目录,只能一次创建一个目录。
- sftp 指定端口号
sftp -oPort=222 test@222.222.111.222
# SCP vs SFTP
- 速度: scp 比 sftp 快得多。这是因为scp实现了更高效的传输算法,不需要等待数据包确认。
- 安全: 两种协议都基于 ssh,提供相同的安全功能。
- 功能: scp 只提供文件传输的功能,但是 sftp 还提供了 cd、ls 等操作查找文件夹的功能,并且 sftp 还支持断点续传,功能比 scp 更强大。
- 传输文件大小: 都没有大小限制,但是 scp 更快。
# FTP
FTP(File Transfer Protocol)只使用 TCP 协议传输,服务传输的数据不会被加密(注意安全问题),所有传输通过明文进行的。分为主动模式和被动模式,一般运行在 20 和 21 两个端口:
主动/被动的参照物就是服务端,主动/被动都是客户端决定的。
主动模式
PORT
,就是服务器主动连接客户端 一般不用被动模式
PASSIVE
orPASV
,就是客户端主动连接服务端 一般用这个
- 数据端口 20 (默认)
- 命令端口 21 (默认)
注意: 当混入主动/被动模式的时候,数据端口可能就不是 20 了。
# 主动模式
客户端请求 服务器主动连接客户端
- 客户端命令端口与 FTP 服务器的命令端口建立连接,并发送命令
PORT 1027
。- 告诉服务端,我要使用主动模式,我的端口是 1027,你来连我。
- FTP 服务器给客户端的命令端口返回一个
ACK
(确认)。 - FTP 服务器发起一个从它自己的数据端口(20)到客户端先前指定的数据端口(1027)的连接。
- 最后客户端给服务器端返回一个
ACK
(确认)。
# 被动模式
客户端请求 主动去连接服务端
- 客户端命令端口与 FTP 服务器的命令端口建立连接,并发送命令
PASV
。- 告诉服务器我要用被动模式,告诉我你的端口号,我去连你。
- 服务器返回命令
PORT 2024
,告诉客户端 2024 端口侦听数据连接。 - 客户端初始化一个从自己的数据端口 1027 到服务器端指定的数据端口 2024 的数据连接。
- 最后服务器给客户端的数据端口返回一个
ACK
响应。
# FTP vs SFTP
- 端口占用
- SFTP 属于 SSH 协议中一个,只需要使用一个22 (TCP)端口。
- FTP 使用 2 个 FTP 连接,一个数据端口 20,一个命令端口 21。
- 安全
- SFTP 是加密数据,传输效率会低一些,因为有加解密过程。
- FTP 是明文传输数据,效率高。可以使用 SSL 实现加密(FTPS)
# FTP 命令
- 下载
get
从服务器下载指定文件到客户端mget
下载文件,模糊匹配newer
下载时,检测是不是新文件hash
显示#表示下载进度
- 上传
put
从客户端传送指定文件到服务器mput
上传文件,模糊匹配
- 删除
delete
删除远端ftp服务器上的文件mdelete
删除文件,模糊匹配
- 连接
open
连接ftp服务器close
在不结束ftp进程的情况下,关闭与ftp服务器的连接quit
断开连接并退出ftp服务器bye
退出ftp命令状态
- 目录操作
pwd
显示当前目录ls
显示服务器上的目录cd <directory>
改变服务器的当前目录为directorylcd <directory>
改变本地的当前目录为directorycdup
上一层目录mkdir
在远端ftp服务器上,建立文件夹
- 其他
ascii
设置文件传输方式为ASCII模式binary
设置文件传输方式为二进制模式!
执行本地主机命令prompt
关闭交互模式
# 科学上网
利用 V2ray + Qv2Ray(可视化界面)。
下载 v2ray-core
下载 Qv2Ray(v2ray 的图形化界面软件)
配置 qv2ray 内核,也就是 v2ray-core
- 执行文件路径: v2ray 的可执行文件
- 资源目录: v2ray 解压后的根目录
# Terminator
使用 Terminator 替换系统自带的终端。
# 端口范围
端口范围一般是 0-65535
,其中 0
不使用, 1-1023
为系统端口,也叫 BSD 保留端口。1024-65535
为用户端口。
0-1023
,BSD 保留端口,也叫系统端口,这些端口只有系统特许的进程才能使用。1024-65535
,用户端口:1024-5000
,BSD 临时端口,一般的应用程序使用 1024 到 4999 来进行通讯。5001-65535
,BSD 服务器(非特权)端口,用来给用户自定义端口。
# ifconfig
ifconfig
是 linux 中用于显示或配置网络设备(网络接口卡)的命令,英文全称是 network interfaces configuring。
ifconfig
用于配置网络接口 Interface config。iwconfig
用于配置无线网络接口 Interface Wlan config。
使用该命令最常见的三项:
lo
(local)enp2s0
(en p2s0)- en 表示以太网(ethernet),p2s0 表示 PCI 接口位置:bus=2, slot=0。
- 旧版的都是
eth0
、eth1
这种,在 Ubuntu 16 后进行了升级(引入 systemd 参考 (opens new window))。
wlp3s0
(wl p3s0)- wl 表示 wlan(Wireless Local Area Network) 无线局域网。
小知识: PCI 外设部件互连标准(Peripheral Component Interconnect),PCI 接口的物理位置的坐标(bus, slot),其中 bus 表示总线,slot 表示插槽。
其他内容含义:
flags
表示网卡状态:UP
:表示“接口已启用”。BROADCAST
:表示“主机支持广播”。RUNNING
:表示“接口在工作中”。MULTICAST
:表示“主机支持多播”。
mtu
,Maximum Transmission Unit,最大传输单元,以字节为单位。inet
,网卡的 ip 地址,ipv4。inet6,ipv6 地址。ether
,链接方式为以太网,后面为硬件 mac 地址。txqueuelen
,网卡的传送队列长度。RX packets
,接收正确的数据包数。RX bytes
,接收的数据量。RX errors
,接收时,产生错误的数据包数。RX dropped
,接收时,丢弃的数据包数。RX overruns
,接收时,由于速度过快而丢失的数据包数。RX frame
,接收时,发生 frame 错误而丢失的数据包数。TX carrier
,发送时,发生 carrier(载体)错误而丢失的数据包数。collisions
,冲突信息包的数目。
# Firewall
防火墙就是一组规则,用于监控、控制进出系统的网络流量。
# 快速上手
防火墙是一组规则。当数据包进出受保护的网络区域时,进出内容(特别是关于其来源、目标和使用的协议等信息)会根据防火墙规则进行检测,以确定是否允许其通过。
防火墙的底层是 Netfilter,但是我们使用
iptables
或者firewalld
等工具进行操作。
防火墙真正通过 Netfilter 在 Linux 内核中实现,一开始使用 iptables
规则集进行管理。由于 iptables
语法晦涩难懂,所以后来又有了 firewalld
等防火墙规则工具(Netfilter 解释器),不过 iptables
并没有被弃用,更全面的功能还是要使用 iptables
。
Linux 防火墙主要工作在网络层,属于典型的包过滤防火墙。在 RHEL 中常用的有两种火墙工具iptables
和 firewalld
,但软件本身其实并不具备防火墙功能,他们的作用都是在用户空间中管理和维护规则,只不过规则结构和使用方法不一样罢了,真正利用规则进行过滤是由内核 Netfilter 完成的。
# Netfilter
Linux 防火墙是由 Netfilter 组件提供的,Netfilter 工作在内核空间,集成在 Linux 内核中, Netfilter 是 Linux 2.4.x 之后新一代的 Linux 防火墙机制,是 Linux 内核的一个子系统。Netfilter 采用模块化设计,具有良好的可扩充性,提供扩展各种网络服务的结构化底层框架。Netfilter 与 IP 协议栈是无缝契合,并允许对数据报进行过滤、地址转换、处理等操作。
Netfilter IP 信息包过滤系统是一种功能强大的工具,可用于添加、编辑和除去规则,这些规则是在做信息包过滤决定时,防火墙所遵循和组成的规则。这些规则存储在专用的信息包过滤表中,而这些表集成在 Linux 内核中。在信息包过滤表中,规则被分组放在我们所谓的链(chain)中。
在 RHEL7 里有几种防火墙共存:firewalld
、iptables
、ebtables
,默认是使用 firewalld
来管理 Netfilter 子系统,不过底层调用的命令仍然是 iptables
等。
如下图:
# Firewalld
Firewalld 从名字上就可以看出来是 Systemd 家族的一部分,Firewalld 可以安装在 Debian/Ubuntu 机器上,不过,它默认安装在 RedHat 和 CentOS 上。
Firewalld 的工具是 firewall-cmd
(命令行工具) 和 firewall-config
(图形界面)。
Firewalld 有两种状态:
运行时
runtime
,修改规则马上生效,但是临时生效持久配置
permanent
,修改后需要重载才会永久生效# --permanent 会将配置写入到 /etc/firewalld/{services,zones}/*.xml 文件中,配置完成后一定要 reload,否则只能待防火墙重启后这些配置才能生效。 firewall-cmd --permanent [RULE] firewall-cmd --reload
1
2
3
# 常用命令
- 查看开放的端口
firewall-cmd --list-ports
# iptables
// TODO
# 查看本机出口 IP
# 推荐前 2 个:
curl ifconfig.me
# 显示详细信息
curl cip.cc
curl icanhazip.com
curl http://members.3322.org/dyndns/getip
2
3
4
5
6
7
# /etc/hosts
局域网内主机名到 IP 的映射配置,本地配置之后就不会再找上级的 DNS 服务器。
该文件的作用只是先于 DNS 解析,如果在这个文件中能找到域名和 ip 的映射就直接用这里的,就不再去 DNS 进行查询了。
注意:
- 只在本地有用,只有在修改了这个文件所在主机可以使用配置的域名。
- 并不是设置 hostname 的地方,设置主机名的位置是
/etc/hostname
。
# 域名解析
以下三个命令都在 dnsutils
包内,可以使用 apt instal dnsutils
安装。
nslookup
已废弃dig
host
# nslookup
# dig
# host
host
命令是 dig
的更加简单的显示,只显示 dig
的 ANSWER SECTION。
# jq
jq 是一个命令行 JSON 工具,可以将一个 JSON 字符串格式化输出。
jq 中文手册 v1.5 (opens new window)
apt update
apt install jq
---
# 看下效果吧
echo `{"name": "xiaoming"}` | jq "."
2
3
4
5
6
# 包管理器
常见的包管理器主要有 apt
、rpm
、yum
。
# apt
# rpm
# yum
# 常见发行版
主要分为 2 大类型:
Debian
为代表(.deb
),社区组织维护的短发版本。- Debian、Ubuntu、Xandros、Linspire ...
Red Hat
为代表(.rpm
),商业公司维护的发行版本。- Fedora、CentOS、Red Hat Enterprise Linux(RHEL)、OpenSUSE、Mandriva、PCLinuxOS ...
# desktop 文件
设置代理 Exec=... --proxy-server="socks5://127.0.0.1:1089"
# Mono
Mono (opens new window) 是一个跨操作系统和硬件平台、跨编程语言,兼容于 .NET 的运行环境、框架、开发平台和工具集。
Mono 项目由著名 Linux 桌面 GNOME 创始人 Miguel de Icaza 发起,创建于 2001 年,先由其公司 Ximian 主持,后随 Ximian 并购于 Novell。
Mono 是一个开源软件平台,是符合 ECMA 标准的 .NET Framework 开源现实。它包括一个 C# 编译器,一个公用语言运行时环境,以及相关的基类库和 mono 类库。
Mono 可以让 .NET 程序跨平台运行在 Linux、BSD、Windows、MacOS、Sun Solaris、Wii、索尼 PlayStation、苹果 iPhone 等几乎所有常见的操作系统之上。
Mono 已经原生代码支持 86、X86-64、Ia64、PowerPC、SPARC(32)、ARM、S390、S390x(32-64) 等几乎所有存在的计算机系统,对于不能直接支持的计算机系统,也可以通过代码解释器支持。
Mono 的公用语言运行时支持编程语言的集成与互操作能力,有许多语言已经有提供了兼容于 Mono CLR 编译器,这些语言包括了:C#、Java、Boo、Nemerle、Visual Basic.NET、Python、Java Script、Oberon、Object Pascal、C、A#(ADA)、PHP、Kylix.NET、MonoLogo、Tachy(Scheme)等。
Mono 的优点不仅仅是跨平台,它更具有丰富的 API。除了 ECMA/ISO 标准的 CLI(Common Language Infrastructure)API 之外,Mono 也具有兼容于微软 Windows Forms、ADO.NET、ASP.NET 的 API,和 Mono 自己的 GUI API(Gtk#)。
许多人也纷纷加入 Mono 的阵营,以 Mono 为基础,将许多既有的动态链接库包装成 .NET 版,例如:GdaSharp(源自 GNOME Data Access,作用类似 ADO.NET)、Cocoa#(源自 MacOS X Cocoa)、X Sharp(源自 X Windows)、Qt#(源自 Qt)、Sharp WT(源自 Java SWT)、wx.NET(源自 wxWidgets)、CsGL(源自 Open GL)、C#-SDL(源自 SDL)、GeckoSharp(源自 Mozilla Gecko)。Mono 还有一个整合许多 API 的计划,称为 Tao Framework。Tao 整合了 Cg、DevIL、FreeGLUT、GLFW、GLU、OpenAL、OpenGL、SDL、WGL。
# ZShell
# 安装
安装 zsh
sudo apt update sudo apt install zsh
1
2配置 zsh 为默认 shell
cat /etc/shells # 查看所有 shell zsh --version # 查看 zsh 版本 sudo chsh -s /bin/zsh # 配置 zsh 为默认 shell ------------ 或者直接输入 chsh,然后回车,输入你的 zsh 地址: /bin/zsh 重启生效
1
2
3
4
5
6
7
8
9安装 oh my zsh
wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | sh # 或 git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh # 或 curl -L https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh | sh --- # 国内源 sh -c "$(curl -fsSL https://gitee.com/mirrors/oh-my-zsh/raw/master/tools/install.sh)" # or sh -c "$(wget -O- https://gitee.com/pocmon/mirrors/raw/master/tools/install.sh)"
1
2
3
4
5
6
7
8
9
10
11
12卸载 oh my zsh
uninstall_oh_my_zsh
# zsh 主题
oh my zsh 分为内置主题和自定义主题。
# 内置主题
oh my zsh 提供了很多主题可以选择,这些主题在安装 oh my zsh 的时候,就已经下载下来了,默认是 robbyrussell
。
在 home 目录下,打开 .zshrc
文件,找到一下内容:
...
# Set name of the theme to load --- if set to "random", it will
# load a random theme each time oh-my-zsh is loaded, in which case,
# to know which specific one was loaded, run: echo $RANDOM_THEME
# See https://github.com/ohmyzsh/ohmyzsh/wiki/Themes
ZSH_THEME="robbyrussell"
...
2
3
4
5
6
7
使用 ls ~/.oh-my-zsh/themes/
查看所有内置主题,也可以访问 https://github.com/ohmyzsh/ohmyzsh/wiki/Themes
这个地址,查看所有的主题以及效果。
也可以 ZSH_THEME="random"
设置主题为 random
以后,每次打开终端都会随机切换一个新主题,或者输入 zsh
重新激活终端,就会刷新主题,找到你喜欢的主题之后,记住主题名字,可以在 .zshrc
中将 ZSH_THEME="你喜欢的主题名"
就可以了。
# 自定义主题
自定义主题放置在 ~/.oh-my-zsh/custom/themes/
。
# zsh 插件
zsh 分为内置插件和自定义插件。
# 内置插件
自带插件是在安装了 oh my zsh
的时候,就已经下载下来了。
但是默认只启用了 git
:
# ~/.zshrc
...
plugins=(git)
...
2
3
4
查看自带的所有插件: ls ~/.oh-my-zsh/plugins
,将插件名设置到 .zshrc
文件中,就可以启用了。
开启插件后,当然你需要刷新配置文件,你可以执行 source .zshrc
立即刷新配置文件,这样配置立即生效。你也可以执行 zsh
这样会重新启动 zsh,它启动前会自动先加载配置文件,所以也起到了立即生效的效果。你也可以不做任何操作,关掉你的终端,重新打开,也是可以用的。
PS: 插件实际上就是一个脚本,配置了之后,其实就是打开你的程序之前,先去运行这个脚本(插件)。
推荐开启的插件:
sudo
- 开启这个插件之后,如果你执行了一个命令,忘记了加
sudo
,你只需要按两下 ESC,就会自动帮你给上一条命令添加sudo
前缀。
- 开启这个插件之后,如果你执行了一个命令,忘记了加
colored-man-pages
- 帮助手册高亮
# 自定义插件
安装一个自定义的插件,你只需要将插件源码放到 ~/.oh-my-zsh/custom/plugins/
,然后和自带插件一样将插件名配置到 .zshrc
,就可以用了。
推荐自定义插件:
zsh-syntax-highlighting
- 将你输入的命令高亮
zsh-autosuggestions
- 如果你之前输入过
cd /user
,开启这个插件后,当你再次输入cd
时,会推荐给你之前的命令,如果你想使用它,按下->
就可以了。
- 如果你之前输入过
zsh-syntax-highlighting
和 zsh-autosuggestions
的库 -> zsh users github (opens new window)
# 讨论区
由于评论过多会影响页面最下方的导航,故将评论区做默认折叠处理。
点击查看评论区内容,渴望您的宝贵建议~
← Linux 命令行常用 操作系统相关 →