:star:
"一位优秀的系统管理员不需要知道一切,但他们应该能够针对不可能的项目提出惊人的解决方案。" - cwheeler33 (ServerFault)
:star:
"我的技能是让事情运转起来,而不是知道十亿个事实。[...] 如果我需要修复一个系统,我会识别问题,检查日志并查找错误。如果我需要实施一个解决方案,我会研究正确的方案,实施并记录它,之后除非我经常与它互动,否则只会有一个大致的了解……这就是为什么要有文档。" - Sparcrypt (Reddit)
ℹ️ 该项目包含 284 个测试问题和答案,可用于测试您的知识或在 Linux (*nix) 系统管理员等职位的面试/考试中使用。
✔️ 答案仅为示例,并未涵盖全部主题。大多数答案包含有用的资源以加深理解。
⚠️ 标记为 *** 的问题尚无答案或答案不完整——请提交拉取请求来补充它们!
🚥 如果您发现任何不合理或看起来不正确的内容,请提交拉取请求,并请附上有效且理由充分的解释或评论。
📚 为了提高您的知识/技能,请参阅 devops-interview-questions。看起来非常有趣。
» 欢迎提出所有建议 «
我最喜欢的 Linux 发行版:
有用的资源:
GNU 本身不是一个操作系统。它更像一套规范自由软件的规则或哲学,同时也在尝试创建操作系统的过程中催生了一批工具。因此,GNU 工具基本上是已有工具的开源版本,但为了符合开源软件的原则而重新实现。GNU/Linux 是这些工具与 Linux 内核的融合,形成一个完整的操作系统,但也存在其他 GNU 系统,例如 GNU/Hurd。
Unix 和 BSD 是“较老”的 POSIX 实现,具有不同程度的“闭源”。Unix 通常完全闭源,但 Unix 的变体数量与 Linux 一样多(如果不是更多的话)。BSD 通常不被视为“开源”,但在发布时被认为是非常开放的。其许可证也允许商业使用,且限制远少于当时其他更“开放”的许可证。
Linux 是这四个中最新的。严格来说,它“只是一个内核”;然而,通常认为它与 GNU 工具和其他几个核心组件结合后就是一个完整的操作系统。
这些系统之间的主要区别在于其理念。Unix、Linux 和 BSD 有着不同的理念。它们都符合 POSIX,并且基本上可以互换。它们在解决某些相同问题时采用了不同的方式。因此,除了理念和它们如何实现 POSIX 标准之外,差异很小。
更多信息,我建议你阅读一篇关于 GNU、OSS、Linux、BSD 和 UNIX 创建过程的简短文章。这些文章可能会偏向于各自的理念,但应该能让你更好地理解差异。
有用的资源:
CLI 是 Command Line Interface(命令行界面)或 Command Language Interpreter(命令语言解释器)的缩写。命令行是控制系统/计算机最强大的方式之一。
在类 Unix 系统中,CLI 是用户输入命令供系统执行的接口。CLI 非常强大,但对错误的容忍度不高。
CLI 允许你以更精细的方式对系统内部和代码进行操作。无论使用何种操作系统,它都比 GUI 提供更大的灵活性和控制力。你希望在软件中使用的许多程序(例如托管在 Github 上的程序)也需要在 CLI 上运行一些命令才能运行。
我最喜欢的工具
screen - 免费的终端复用器,我可以启动一个会话,即使连接断开,我的终端也会保留,因此我可以在稍后或从家中恢复ssh - 最值得学习的全能命令,我可以用它来做一些惊人的事情:
sshfs 挂载网络上的文件系统vi/vim - 最流行且最强大的文本编辑器,通用性强,即使在处理大文件时也速度飞快bash-completion - 包含许多预定义的 shell 补全规则技巧与窍门
CTRL + R 搜索命令历史popd/pushd 以及其他允许操作目录栈的 shell 内建命令CTRL + U、CTRL + E!* - 上一条命令的所有参数BASH 是我最喜欢的。这其实是个人偏好问题,我喜欢它的语法,而且它对我来说非常“顺手”。输入/输出重定向语法(>>、<< 2>&1、2>、1> 等)与 C++ 类似,这让我更容易识别。
我也喜欢 ZSH shell,因为它比 BASH 可定制性更强。它拥有 Oh-My-Zsh 框架、强大的基于上下文的 Tab 补全、强大的模式匹配/通配符功能、可加载模块等。
有用的资源:
man [命令名] 可用于查看命令的描述(例如:man less、man cat)-h 或 --help 某些程序在传递此参数时会打印使用说明(例如:python -h 和 python --help)w - 包含大量有用信息,如服务器运行时间top - 可以查看所有正在运行的进程,然后按 CPU、内存使用率等进行排序netstat - 了解服务器正在监听哪些端口和 IP,以及哪些进程在使用它们df - 报告文件系统已使用的磁盘空间量history - 告诉你当前连接的用户之前运行过哪些命令有用的资源:
ls -al 输出中的字段分别代表什么?按输出顺序:```bash -rwxrw-r-- 1 root root 2048 Jan 13 07:11 db.dump
- 文件权限,
- 链接数,
- 所有者名称,
- 所有者组,
- 文件大小,
- 最后修改时间,
- 文件/目录名称
文件权限显示如下:
- 第一个字符是 `-` 或 `l` 或 `d`,`d` 表示目录,`-` 表示文件,`l` 是符号链接(或软链接)——一种特殊类型的文件
- 三组字符,每组三个,分别表示所有者、组和其他用户的权限:
- `r` = 可读
- `w` = 可写
- `x` = 可执行
在你的例子 `-rwxrw-r--` 中,该行表示:
- 一个普通文件(显示为 `-`)
- 所有者可读、可写、可执行(`rwx`)
- 组用户可读、可写,但不可执行(`rw-`)
- 其他用户仅可读,不可写也不可执行(`r--`)
有用的资源:
- [ls -al 输出中各字段的含义是什么?(原文)](https://unix.stackexchange.com/questions/103114/what-do-the-fields-in-ls-al-output-mean)
</details>
<details>
<summary><b>如何获取已登录用户的列表?</b></summary><br>
要获取已登录用户的摘要,包括每个用户名的每次登录、用户所连接的终端、登录的日期/时间,以及可能的连接来源计算机,请输入:```bash
# It uses /var/run/utmp and /var/log/wtmp files to get the details.
who
要获取详细信息,包括用户名、终端、源计算机的IP地址、登录开始时间、空闲时间、进程CPU周期、作业CPU周期以及当前运行的命令,请输入:```bash
w
同样重要的是显示最近登录用户列表,输入:```bash
# It uses /var/log/wtmp.
last
有用资源:
将正在运行的进程放在后台执行的最大优点是,你可以在后台运行其他进程的同时做任何其他任务。因此,当你处理不同进程时,可以在后台完成更多进程。这可以通过在命令末尾添加特殊字符 & 来实现。
通常,那些执行时间过长且不需要用户交互的应用程序会被放到后台,这样我们就可以在终端继续我们的工作。
例如,如果你想在后台下载东西,你可以:```bash wget https://url-to-download.com/download.tar.gz &
当您运行上述命令时,您将获得以下输出:```bash
[1] 2203
这里 1 是作业的序列号,2203 是该作业的 PID。
你可以使用以下命令查看在后台运行的作业:```bash jobs
当你在后台执行作业时,它会给你一个作业的PID,你可以使用以下命令杀死在后台运行的作业:```bash
kill PID
将PID替换为任务的PID。如果你只有一个任务在运行,你可以使用以下命令将其带到前台:```bash fg
如果你在后台运行了多个作业,你可以使用以下命令将任意作业带到前台:```bash
fg %#
将 # 替换为任务的序列号。
有用的资源:
待补充。
(所有操作)都以 root 身份运行是不好的,因为:
愚蠢:没有什么能阻止你犯粗心的错误。如果你试图以任何可能有害的方式更改系统,你需要使用 sudo,这能确保在输入密码时有一个暂停,以确保你没有要犯错。
安全:如果你不知道管理员用户的登录账户,就更难被黑。root 意味着你已经拥有了管理员凭证的一半工作集合。
你并不真正需要它:如果你需要以 root 身份运行多个命令,并且厌烦了在 sudo 过期后多次输入密码,你只需要执行 sudo -i 就能成为 root。想要使用管道运行一些命令?那么使用 sudo sh -c "command1 | command2"。
你总可以在恢复控制台中使用它:恢复控制台允许你从重大错误中恢复,或者修复由应用程序引起的问题(你仍然需要以 sudo 运行该应用程序)。在这种情况下,Ubuntu 没有 root 账户的密码,但你可以在网上搜索如何更改——这会让任何物理接触你电脑的人更难造成危害。
有用的资源:
你可以使用 top/htop 来检查两者。通过 free 和 vmstat 命令,我们可以分别显示物理内存和虚拟内存统计信息。借助 sar 命令,我们可以查看 CPU 利用率和其他统计信息(但大多数系统中甚至没有安装 sar)。
有用的资源:
Linux 负载平均值是“系统负载平均值”,它显示系统上正在运行的线程(任务)需求,以正在运行加上等待线程的平均数量表示。这衡量的是需求,可能大于系统当前正在处理的数量。大多数工具显示三个平均值,分别为 1、5 和 15 分钟。
这三个数字并不是不同 CPU 的数字。它们是给定时间段内(过去 1、5 和 15 分钟)负载数字的平均值。
负载平均值通常被描述为“运行队列的平均长度”。因此,少数 CPU 密集型进程或线程可能会使负载平均值超过 1。如果负载平均值小于 CPU 核心总数,则没有问题。但如果它超过了 CPU 的数量,则意味着一些线程/进程将停留在队列中,准备运行,但等待空闲 CPU。
它的目的是让你了解系统的状态,并在多个时间段内取平均值。由于它是平均值,在系统承受高负载后,它需要一段时间才能恢复到 0。
一些解释:
有用的资源:
密码并不存储在系统的任何地方。存储在 /etc/shadow 中的是所谓的密码哈希值。
文本的哈希值是通过对文本(密码)执行所谓的单向函数而创建的,从而生成一个用于检查的字符串。根据设计,反向这个过程是“不可能”的(计算上不可行)。
旧的 Unix 变体将加密后的密码存储在 /etc/passwd 中,以及每个账户的其他信息。
较新的变体只是在 /etc/passwd 的相关字段中放置一个 *,并使用 /etc/shadow 来存储密码,部分原因是为了确保当其他人只需要其他信息时,无法读取密码(shadow 通常比 passwd 受到更强的保护)。
更多信息请参考 man crypt、man shadow、man passwd。
有用的资源:
要将所有目录更改为 755(drwxr-xr-x):```bash
find /opt/data -type d -exec chmod 755 {} ;
要更改所有文件,例如改为 **644** (`-rw-r--r--`):```bash
find /opt/data -type f -exec chmod 644 {} \;
有用的资源:
command not found。如何追踪错误的来源并解决它?看起来在某些时候,默认的 PATH 环境变量被覆盖了。你遇到的错误类型表明 PATH 中没有包含例如 /bin(命令包括 bash 所在的位置)这样的目录。
调试你的 bash 脚本或命令的一种方法是使用 -x 选项启动一个子 shell:```bash
bash --login -x
这将显示启动该 shell 时执行的每个命令及其参数。同样很有帮助的是显示 `PATH` 变量值:```bash
echo $PATH
如果你运行这个:```bash PATH=/bin:/sbin:/usr/bin:/usr/sbin
大多数命令应该开始正常工作——然后你可以编辑 `~/.bash_profile` 而不是 `~/.bashrc`,并修复其中重置 `PATH` 的任何设置。**root** 和其他用户的默认 `PATH` 变量值位于 `/etc/profile` 文件中。
实用资源:
- [如何正确地将路径添加到 PATH?](https://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path)
</details>
<details>
<summary><b>你按了 <code>CTRL + C</code> 但脚本仍在运行。如何停止它?</b></summary><br>
大多数情况下,你可以使用 `CTRL + C` 键盘组合键来停止正在运行的脚本。这会向脚本发送一个中断信号 (SIGINT),从而终止其执行。如果这种方法无效且脚本仍在运行,你可以尝试使用 `CTRL + \` 组合键,它会向脚本发送一个退出信号 (SIGQUIT),可能立即终止脚本。
或者,如果你使用的是终端或命令行界面,可以尝试使用 `kill` 命令向脚本进程发送信号。你可以通过 `ps` 或 `top` 命令找到脚本的进程 ID (PID),然后使用 `kill` 加上该 PID 来停止脚本。
在某些情况下,你可能需要使用 `kill -9` 命令强制停止脚本,因为如果脚本卡住或无响应,常规的 kill 命令可能无效。`-9` 选项发送 SIGKILL 信号,强制进程立即停止。
</details>
<details>
<summary><b>什么是 <code>grep</code> 命令?如何匹配同一行中的多个字符串?</b></summary><br>
`grep` 工具是 Unix 工具家族的一部分,包括 `egrep` 和 `fgrep`。
`grep` 用于搜索文件中的模式。如果你在查找另一个命令输出中的特定模式,`grep` 会高亮显示相关行。使用此 grep 命令来搜索日志文件、特定进程等。
匹配多个字符串:```bash
grep -E "string1|string2" filename
如果你希望每个命令仅在前一个命令成功时才执行,那么使用 && 运算符将它们组合起来:```bash
cd /my_folder && rm *.jar && svn co path to repo && mvn compile package install
如果其中一个命令失败,则其后的所有其他命令将不会被执行。
如果你想无论之前的命令是否失败都执行所有命令,请用分号分隔它们:```bash
cd /my_folder; rm *.jar; svn co path to repo; mvn compile package install
在你的情况下,我认为你需要的是第一种情况,即下一个命令的执行依赖于上一个命令的成功。
你也可以将所有命令放入一个脚本中,然后执行该脚本:```bash
#! /bin/sh
cd /my_folder
&& rm *.jar
&& svn co path to repo
&& mvn compile package install
有用资源:
- [在一行中执行组合多个 Linux 命令(原文)](https://stackoverflow.com/questions/13077241/execute-combine-multiple-linux-commands-in-one-line)
</details>
<details>
<summary><b>你可以向 <code>chmod</code> 传递什么符号表示法,以便在不影响其他权限的情况下授予所有用户对文件的执行权限?</b></summary><br>```bash
chmod a+x /path/to/file
a - 针对所有用户x - 执行权限r - 读取权限w - 写入权限有用资源:
要在同一系统上将 dir1 的内容同步到 dir2,请输入:```bash rsync -av --progress --delete dir1/ dir2
- `-a`, `--archive` - 归档模式
- `--delete` - 从目标目录中删除多余文件
- `-v`, `--verbose` - 详细模式(增加详细程度)
- `--progress` - 显示传输进度
有用资源:
- [如何同步两个本地目录?(原帖)](https://unix.stackexchange.com/questions/392536/how-can-i-sync-two-local-directories)
- [使用rsync同步文件夹](https://www.jveweb.net/en/archives/2010/11/synchronizing-folders-with-rsync.html)
</details>
<details>
<summary><b>许多基本维护任务需要你编辑配置文件。请解释撤销所做更改的方法。</b></summary><br>
- 手动在编辑前备份文件(使用花括号扩展,如:`cp filename{,.orig}`)
- 手动复制文件所在的目录结构(例如 `cp`、`rsync` 或 `tar`)
- 在编辑器中备份原始文件(例如,在编辑器配置文件中设置规则)
- 最佳解决方案是使用 `git`(或其他任何版本控制)来跟踪配置文件(例如,用于 `/etc` 目录的 `etckeeper`)
有用资源:
- [在文件扩展名前使用 .bak 备份文件](https://unix.stackexchange.com/questions/66376/backup-file-with-bak-before-filename-extension)
- [使用git进行配置文件版本控制是个好主意吗?](https://superuser.com/questions/1037211/is-it-a-good-idea-to-use-git-for-configuration-file-version-controlling)
</details>
<details>
<summary><b>你必须找到所有大于20MB的文件。你如何做到?</b></summary><br>```bash
find / -type f -size +20M
实用资源:
sudo su - 而不是 sudo su?在大多数现代 Linux 发行版中,sudo 是常用的(但并非总是如此),root 用户被禁用且没有设置密码。因此,你无法使用 su 切换到 root 用户(你可以尝试)。你需要通过 sudo 以 root 权限调用:sudo su。
su 仅切换用户,提供一个与旧用户环境几乎相同的普通 shell。
su - 在切换用户后会启动一个登录 shell。登录 shell 会重置大多数环境变量,提供一个干净的基础。
实用资源:
它们对于调查系统问题至关重要。日志管理对IT安全绝对关键。
服务器、防火墙和其他IT设备会保留日志文件,记录重要事件和事务。这些信息可以提供有关网络内外敌对活动的重要线索。日志数据还可以提供用于识别和排除设备问题(包括配置问题和硬件故障)的信息。
这是您的服务器记录谁访问了您的网站、何时访问以及他们具体查看了哪些内容。它非常详细,显示:
需要考虑的因素:
通过收集和分析日志,您可以了解网络内发生的事情。每个日志文件都包含许多宝贵的信息,尤其是如果您知道如何阅读和分析它们。
实用资源:
RAID(廉价磁盘冗余阵列)是一种用于提高数据存储性能和/或可靠性的技术。
实用资源:
如果未指定,useradd 的行为将取决于 /etc/login.defs 中的 USERGROUPS_ENAB 变量。默认行为(USERGROUPS_ENAB yes)是创建一个与用户名同名的组,其 GID 等于 UID。
有用的资源:
待完成。
待完成。
关于 OSI(或任何其他)模型,最重要的理解要点是:
有用的资源:
VLAN 和 子网 解决不同的问题。VLAN 工作在第二层,从而改变广播域(例如)。而 子网 在当前上下文中是第三层概念。
子网 — 是由部分地址(通常称为网络地址)和子网掩码(netmask)确定的 IP 地址范围。例如,如果子网掩码为 255.255.255.0(简写为 /24),网络地址为 192.168.10.0,那么它定义了 IP 地址范围 192.168.10.0 到 192.168.10.255。简写表示为 192.168.10.0/24。
VLAN — 一个很好的理解方式是“交换机分区”。假设你有一台支持 VLAN 的 8 端口交换机。你可以将 4 个端口分配给一个 VLAN(比如 VLAN 1),另外 4 个端口分配给另一个 VLAN(比如 VLAN 2)。VLAN 1 看不到 VLAN 2 的任何流量,反之亦然;从逻辑上讲,你现在有了两个独立的交换机。通常,在交换机上,如果交换机没有看到某个 MAC 地址,它会将流量“泛洪”到所有其他端口。VLAN 可以防止这种情况。
子网不过是 IP 地址的一个范围,帮助主机在第二层和第三层通信。每个子网并不需要拥有自己的 VLAN。VLAN 用于隔离(是第二层通信的沙箱,属于不同 VLAN 的两个系统不能通信,但可以通过 VLAN 间路由 实现)、易于管理和安全性。
有用的资源:
POP 和 IMAP 都是用于从邮件服务器向邮件客户端检索消息的协议。
POP(邮局协议)使用从邮件服务器到客户端的单向推送。默认情况下,这会将消息发送到 POP 邮件客户端并将其从邮件服务器中删除,但也可以配置邮件服务器保留所有消息。你在邮件客户端中对消息执行的任何操作(标记、删除、移动到文件夹)都不会反映在邮件服务器上,因此其他从邮件服务器拉取的邮件客户端无法访问这些操作。POP 在邮件服务器上占用很少的存储空间,并且可以被认为更安全,因为消息只存在于一个邮件客户端上,而不是邮件服务器和多个客户端。
IMAP(互联网消息访问协议)使用邮件服务器和客户端之间的双向通信。在配置了 IMAP 的邮件客户端中删除或标记消息,也会在邮件服务器上删除或标记该消息。IMAP 允许在不同客户端或设备上访问邮件时获得类似体验,因为消息可以在多个设备上以相同状态存在。IMAP 还可以通过选择性同步消息、从邮件客户端删除较旧的消息(因为之后可以从邮件服务器按需同步)来节省邮件客户端的磁盘空间。
如果你需要在多个设备上访问消息,并且想在客户端设备上节省磁盘空间,请选择 IMAP。如果你想在邮件服务器上节省磁盘空间,只从一个客户端设备访问消息,并确保消息不会存在于多个系统上,请选择 POP。
使用命令 netstat -nr、route -n 或 ip route show 可以查看默认路由和路由表。
有用的资源:
嗯,最有可能的区别是,你仍然需要在某处实际查找 localhost。
如果你使用 127.0.0.1,那么(智能的)软件会直接将其转换为 IP 地址并使用。某些 gethostbyname 的实现会检测点分格式(以及推测的 IPv6 格式)而不进行任何查找。
否则,需要解析该名称。并且不能保证你的 hosts 文件一定会被用于该解析(优先或完全使用),因此 localhost 可能会变成一个完全不同的 IP 地址。
我的意思是,在某些系统上,本地 hosts 文件可能会被绕过。host.conf 文件在 Linux(以及许多其他 Unix 系统)上控制这一点。
如果你使用 Unix 域套接字,它会比使用 TCP/IP 稍快(因为开销更少)。Windows 默认使用 TCP/IP,而 Linux 如果选择 localhost 则尝试使用 Unix 域套接字,如果选择 127.0.0.1 则使用 TCP/IP。
有用的资源:
ping 命令使用哪个端口?ping 使用 ICMP,具体来说是 ICMP 回显请求 和 ICMP 回显应答 数据包。ICMP 没有关联的“端口”。端口与两个 IP 传输层协议 TCP 和 UDP 相关联。ICMP、TCP 和 UDP 是“同级”关系;它们不依赖于彼此,而是运行在 IP 之上的三个独立协议。
ICMP 数据包通过 IP 数据报头中的“协议”字段进行标识。ICMP 不使用 UDP 或 TCP 通信服务,它使用原始 IP 通信服务。这意味着 ICMP 消息直接承载在 IP 数据报的数据字段中。raw 来源于它在软件中的实现方式:要创建并发送 ICMP 消息,你需要打开一个原始套接字,构建一个包含 ICMP 消息的缓冲区,然后将包含该消息的缓冲区写入原始套接字。
ICMP 的 IP 协议值为 1。协议字段是 IP 头部的一部分,用于标识 IP 数据报数据部分的内容。
不过,你可以使用 nmap 来检查端口是否开放:```bash
nmap -p 80 example.com
Useful resources:
- [Ping Port Number](https://networkengineering.stackexchange.com/questions/42463/ping-port-number)
- [Is it possible to ping an address:port?](https://superuser.com/questions/769541/is-it-possible-to-ping-an-addressport)
</details>
<details>
<summary><b>服务器A无法与服务器B通信。请分几个步骤描述可能的原因。</b></summary><br>
要排查服务器之间的通信问题,最好遵循TCP/IP协议栈:
1. **应用层**:两台服务器上的服务是否已启动并正常运行?配置是否正确(例如,绑定正确的IP和端口)?应用程序和系统日志是否显示有意义的错误?
2. **传输层**:应用程序使用的端口是否已开放(尝试telnet!)?能否ping通服务器?
3. **网络层**:网络或操作系统上的防火墙配置是否正确?IP协议栈是否配置正确(IP、路由、DNS等)?交换机和路由器是否正常工作(检查ARP表!)?
4. **物理层**:服务器是否连接到网络?是否存在丢包?
</details>
<details>
<summary><b>为什么服务器上的主机名无法解析?请修复此问题。 ***</b></summary><br>
待完成。
</details>
<details>
<summary><b>如何使用CLI(通过外部DNS)解析域名?能否将IP地址解析为域名?</b></summary><br>
将IP地址解析为域名的示例:```bash
# with host command:
host domain.com 8.8.8.8
# with dig command:
dig @9.9.9.9 google.com
# with nslookup command:
nslookup domain.com 8.8.8.8
telnet 或 nc 测试端口连通性?nc -vz code42.example.com 5432
</details>
<details>
<summary><b>为什么应该避免使用 <code>telnet</code> 远程管理系统?</b></summary><br>
现代操作系统默认已关闭所有潜在不安全的服务。另一方面,一些网络设备厂商仍允许使用 telnet 协议建立通信。
**Telnet** 使用最不安全的通信方法。它以明文格式通过网络传输数据,任何人都可以轻易使用网络工具找到密码。
在 **Telnet** 的情况下,这包括以明文形式传递登录凭据,这意味着任何在网络上运行嗅探器的人都可以通过窃听 **Telnet** 登录会话,在几秒钟内找到控制设备所需的信息。
实用资源:
- [Telnet 和 SSH 作为安全替代方案](https://www.ssh.com/ssh/telnet)
- [如何 telnet 到特定端口的 IP 地址?](https://superuser.com/questions/339107/how-to-telnet-to-an-ip-address-on-a-specific-port)
</details>
<details>
<summary><b><code>wget</code> 和 <code>curl</code> 有什么区别?</b></summary><br>
主要区别在于:`wget` 相比 `curl` 的主要优势是其递归下载能力。`wget` 仅支持命令行。`curl` 支持 FTP、FTPS、HTTP、HTTPS、SCP、SFTP、TFTP、TELNET、DICT、LDAP、LDAPS、FILE、POP3、IMAP、SMTP、RTMP 和 RTSP。
实用资源:
- [curl 和 wget 有什么区别?(原版)](https://unix.stackexchange.com/questions/47434/what-is-the-difference-between-curl-and-wget)
</details>
<details>
<summary><b>什么是 SSH,它如何工作?</b></summary><br>
**SSH** 代表 **Secure Shell**。它是一种协议,允许你从服务器 "A" 进入服务器 "B" 的 shell 会话。它让你能够与服务器 "B" 进行交互。
要建立 **SSH** 连接,远程机器(服务器 A)必须运行一个称为 **SSH** 守护进程的软件,而用户的计算机(服务器 B)必须有一个 **SSH** 客户端。
**SSH** 守护进程和 **SSH** 客户端监听特定网络端口(默认 22)上的连接,对连接请求进行身份验证,并在用户提供正确凭据时生成适当的环境。
实用资源:
- [理解 SSH 加密和连接过程](https://www.digitalocean.com/community/tutorials/understanding-the-ssh-encryption-and-connection-process)
</details>
<details>
<summary><b>大多数教程建议使用 SSH 密钥认证而不是密码认证。为什么这被认为更安全?</b></summary><br>
**SSH 密钥**是 SSH 协议中的访问凭证。其功能类似于用户名和密码,但密钥主要用于自动化流程以及系统管理员和高级用户实现单点登录。
无需用户密码,可以通过使用公钥和私钥的非对称加密算法来确认客户端身份。
如果 SSH 服务只允许公钥认证,攻击者需要获取与服务器上存储的公钥对应的私钥副本。
如果 SSH 服务允许基于密码的认证,那么你连接到互联网的 SSH 服务器将日夜受到僵尸网络的攻击,尝试猜测用户名和密码。僵尸网络不需要任何信息,只需尝试流行的用户名和密码。除此之外,这还会堵塞你的日志。
实用资源:
- [基于密钥的认证(公钥认证)](http://www.crypto-it.net/eng/tools/key-based-authentication.html)
- [SSH 密码 vs. 密钥认证](https://security.stackexchange.com/questions/33381/ssh-password-vs-key-authentication)
</details>
<details>
<summary><b>什么是数据包过滤器,它如何工作?</b></summary><br>
**数据包过滤**是一种防火墙技术,通过监控出站和入站数据包,并根据源和目的 IP 地址、协议和端口允许或阻止它们,从而控制网络访问。
数据包过滤适用于安全需求适中的环境。许多组织的内部(私有)网络并未高度分段。隔离组织内不同部分不需要高度复杂的防火墙。
然而,将生产网络与实验室或实验网络隔离开来是谨慎的做法。数据包过滤设备非常适合隔离不同子网。
它在 TCP/IP 协议栈的网络层和传输层工作,每个数据包在进入协议栈时都会被检查。网络和传输头部被仔细检查以下信息:
- **协议(IP 头部,网络层)** - 在 IP 头部中,字节 9(记住字节计数从零开始)标识数据包的协议。大多数过滤设备能够区分 TCP、UDP 和 ICMP。
- **源地址(IP 头部,网络层)** - 源地址是创建数据包的主机的 32 位 IP 地址。
- **目的地址(IP 头部,网络层)** - 目的地址是数据包要发送到的主机的 32 位 IP 地址。
- **源端口(TCP 或 UDP 头部,传输层)** - TCP 或 UDP 网络连接的每一端都绑定到一个端口。TCP 端口与 UDP 端口是分开且不同的。编号低于 1024 的端口是保留的——它们有特定的定义用途。编号高于或等于 1024 的端口称为临时端口。它们可以按供应商的选择使用。关于“知名端口”列表,请参考 RFP1700。源端口是伪随机分配的临时端口号,因此基于源端口进行过滤通常不太有用。
- **目的端口(TCP 或 UDP 头部,传输层)** - 目的端口号指示数据包发送到的端口。目的主机上的每个服务都监听一个端口。一些可能被过滤的知名端口包括 20/TCP 和 21/TCP(FTP 连接/数据)、23/TCP(telnet)、80/TCP(HTTP)和 53/TCP(DNS 区域传输)。
- **连接状态(TCP 头部,传输层)** - 连接状态指示数据包是否是网络会话的第一个数据包。如果这是会话中的第一个数据包,TCP 头部中的 ACK 位被设置为“false”或 0。通过拒绝或丢弃任何 ACK 位设置为“false”或 0 的数据包,可以简单地禁止主机建立连接。
实用资源:
- [构建互联网防火墙 - 数据包过滤](http://web.deu.edu.tr/static/oreily/networking/firewall/ch06_01.htm)
</details>
<details>
<summary><b>使用反向代理服务器有哪些优势?</b></summary><br>
**隐藏后端服务器的拓扑和特性**
**反向代理服务器**可以隐藏源服务器的存在和特性。它充当互联网云和 Web 服务器之间的中间层。出于安全原因,特别是当你使用 Web 托管服务时,它非常有用。
**允许透明的后端服务器维护**
你对运行在反向代理后面的服务器所做的更改,对最终用户来说是完全透明的。
**负载均衡**
反向代理会强制执行某种负载均衡算法,如轮询、加权轮询、最少连接、加权最少连接或随机,以在集群中的服务器之间分配负载。
当服务器宕机时,系统会自动故障转移到下一个可用的服务器,用户可以继续进行其安全的文件传输活动。
**SSL 卸载/终止**
处理传入的 HTTPS 连接,解密请求并将未加密的请求传递给 Web 服务器。
**IP 掩码**
使用单个 IP 但不同的 URL 路由到不同的后端服务器。
实用资源:
- [反向代理的好处](https://dzone.com/articles/benefits-reverse-proxy)
</details>
<details>
<summary><b>路由器和网关有什么区别?什么是默认网关?</b></summary><br>
**路由器**描述通用的技术功能(三层转发)或用于该目的的硬件设备,而**网关**描述本地网段的功能(提供到其他地方的连接)。你也可以说“你将路由器设置为网关”。另一个术语是跳,它描述子网之间的转发。
**默认网关**一词用来指你局域网上的路由器,它负责作为离开局域网流量的第一联系点。
这只是视角问题,设备是相同的。
实用资源:
- [路由器和网关的区别(原版)](https://networkengineering.stackexchange.com/questions/51426/difference-between-router-and-gateway)
</details>
<details>
<summary><b>解释以下 DNS 记录的功能:SOA、PTR、A、MX 和 CNAME。</b></summary><br>
**DNS 记录**基本上是映射文件,告诉 DNS 服务器每个域关联的 IP 地址,以及如何处理发送到每个域的请求。一些几乎在所有 DNS 记录配置中常用的 **DNS 记录**语法包括 `A`、`AAAA`、`CNAME`、`MX`、`PTR`、`NS`、`SOA`、`SRV`、`TXT` 和 `NAPTR`。
- **SOA** - 起始授权记录
- **A** - 地址映射记录
- **AAAA** - IPv6 地址记录
- **CNAME** - 规范名称记录
- **MX** - 邮件交换记录
- **NS** - 名称服务器记录
- **PTR** - 反向查找指针记录
实用资源:
- [DNS 记录类型列表](https://en.wikipedia.org/wiki/List_of_DNS_record_types)
</details>
<details>
<summary><b>为什么不能使用 MAC 地址代替 IPv4/6 进行网络通信?</b></summary><br>
**OSI** 模型解释了为什么基于物理的**第 2 层**机制来做出路由(**第 3 层**概念)决策是没有意义的。
现代网络被分成许多不同的层来完成端到端的通信。你的网卡(由 MAC 地址寻址——物理地址)只需要负责与其物理网络上的对等方通信。
使用 **MAC** 地址可以完成的通信仅限于与你的机器物理接触范围内的其他设备。例如,在互联网上,你并非与每台机器都物理连接。这就是为什么当我们需要与没有物理连接的机器通信时,我们会使用 **TCP/IP**(**第 3 层**,逻辑地址)机制。
**IP** 是一种任意编号方案,以分层方式施加在一组计算机上,以便在逻辑上将它们区分为一个组(这就是子网)。这些组之间的消息传递由路由表完成,路由表本身又分为多个层级,这样我们就不必跟踪每一个子网。
也很容易将其与另一对系统联系起来。你有一个国家颁发的身份证号码,如果这个号码对你来说已经是唯一的,为什么还需要邮寄地址?你需要邮寄地址,因为它是一个任意的系统,描述了将通信发送到你的独特目的地的位置。
另一方面,整个网络中 **MAC** 地址的分布是随机的,与拓扑完全无关。路由分组是不可能的,每个路由器都需要跟踪通过它转发流量的每个设备的路由。这就是**第 2 层**交换机所做的,而这种方式在超过一定数量的主机后无法良好扩展。
实用资源:
- [为什么不能使用 MAC 地址代替 IPv4|6 进行网络通信?(原版)](https://serverfault.com/questions/410626/why-couldnt-mac-addresses-be-used-instead-of-ipv46-for-networking)
</details>
<details>
<summary><b>包含最多 30 台设备的网络可以应用的最小 IPv4 子网掩码是什么?</b></summary><br>
无论你是使用标准的 `/24` VLAN 给最终用户,还是使用 `/30` 进行点对点链路,或者是介于两者之间且必须包含最多 30 台设备的子网,结果都是 `/27`——或者子网掩码 `255.255.255.224`。
实用资源:
- [如何计算前缀、网络、子网和主机号?](https://networkengineering.stackexchange.com/questions/7106/how-do-you-calculate-the-prefix-network-subnet-and-host-numbers)
- [IP 地址后的斜杠 - CIDR 表示法](https://networkengineering.stackexchange.com/questions/3697/the-slash-after-an-ip-address-cidr-notation)
- [为什么有 3 个私有 IPv4 地址范围?](https://networkengineering.stackexchange.com/questions/32119/why-are-there-3-ranges-of-private-ipv4-addresses)
- [IP 计算器](http://jodies.de/ipcalc)
</details>
<details>
<summary><b>常见的 HTTP 状态码有哪些?</b></summary><br>
- **1xx** - 信息响应 - 传达传输协议级别的信息
- **2xx** - 成功 - 表示客户端的请求已成功接受
- **3xx** - 重定向 - 表示客户端必须采取一些额外操作才能完成请求
- **4xx** - 客户端错误 - 此类错误状态码指向客户端
- **5xx** - 服务器端错误 - 服务器对这些错误状态码负责
实用资源:
- [HTTP 状态码](https://httpstatuses.com/)
</details>
###### DevOps 问题 (5)
<details>
<summary><b>什么是 DevOps?对于任何 DevOps 社区的成功,人们如何沟通比选择部署的工具更重要? ***</b></summary><br>
**DevOps** 是一个同时参与开发和运维任务的协作团队,或者是紧密合作的单独运维和开发团队。它更多是一种与其他部门协作实现共同目标的“方式”。
</details>
<details>
<summary><b>什么是版本控制?你的提交消息看起来是否良好?</b></summary><br>
它是一个记录文件或文件集随时间变化的系统,以便你以后可以召回特定版本。版本控制系统包含一个中央共享仓库,团队成员可以向其中提交对文件或文件集的更改。然后你可以提及版本控制的用途。
版本控制允许你:
- 将文件恢复为以前的状态
- 将整个项目恢复为以前的状态
- 比较随时间的变化
- 查看谁最后修改了可能导致问题的内容
- 谁引入了问题以及何时引入
优秀提交消息的七条规则:
- 用空行分隔主题和正文
- 将主题行限制在 50 个字符内
- 主题行首字母大写
- 主题行末尾不要加句号
- 在主题行中使用祈使语气
- 将正文行长度限制在 72 个字符
- 使用正文解释“什么”和“为什么”,而不是“如何”
实用资源:
- [入门 - 关于版本控制(原版)](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control)
</details>
<details>
<summary><b>解释一些基本的 <code>git</code> 命令。</b></summary><br>
- `git init` - 创建一个新的本地仓库
- `git commit -m "message"` - 将更改提交到头部
- `git status` - 列出你通过 `git add` 添加的文件,并显示自那时起已更改的任何文件
- `git push origin master` - 将更改发送到远程仓库的 master 分支
</details>
<details>
<summary><b>解释一个简单的持续集成流水线。</b></summary><br>
- 克隆仓库
- 部署阶段(QA)
- 测试环境(QA)
- 部署阶段(PROD)
</details>
<details>
<summary><b>解释一些基本的 <code>docker</code> 命令。</b></summary><br>
- `docker ps` - 显示运行中的容器
- `docker ps -a` - 显示所有容器
- `docker images` - 显示 Docker 镜像
- `docker logs <container-id|container-name>` - 获取容器日志
- `docker network ls` - 显示所有 Docker 网络
- `docker volumes ls` - 显示所有 Docker 卷
- `docker exec -it <container-id|container-name> bash` - 在容器中执行 bash 并打开交互式 shell
</details>
###### 网络安全问题 (1)
<details>
<summary><b>什么是安全配置错误?</b></summary><br>
**安全配置错误**是一种漏洞,当设备/应用程序/网络以某种方式配置,使得攻击者可以利用它时发生。这可能简单到保持默认用户名/密码不变,或对设备账户等使用过于简单的密码。
</details>
### :diamond_shape_with_a_dot_inside: <a name="regular-sysadmin">常规系统管理员</a>
###### 系统问题 (60)
<details>
<summary><b>请谈谈你在生产环境中的经验? ***</b></summary><br>
待补充。
</details>
<details>
<summary><b>你会选择哪种发行版来运行一个主要的 Web 服务器? ***</b></summary><br>
待补充。
</details>
<details>
<summary><b>简要说明 Linux 系统的引导过程。</b></summary><br>
**BIOS**:BIOS 的全称是基本输入输出系统,它执行完整性检查,搜索、加载并执行引导加载程序。
**引导加载程序**:由于早期阶段与操作系统无关,基于 BIOS 的 x86 和 x86-64 架构引导过程被认为始于主引导记录(MBR)代码在实模式下执行并加载第一阶段引导加载程序。在 UEFI 系统中,可以直接执行 payload,如 Linux 内核,因此不需要引导加载程序。一些流行的引导加载程序包括:**GRUB**、**Syslinux/Isolinux** 或 **Lilo**。
**内核**:Linux 内核处理所有操作系统进程,如内存管理、任务调度、I/O、进程间通信和整体系统控制。它分两个阶段加载:第一阶段,内核(作为压缩镜像文件)被加载到内存并解压缩,并设置一些基本功能,如基本内存管理。
**Init**:它是系统上所有进程的父进程,由内核执行,负责启动所有其他进程。
- `SysV init` - init 的工作是“在内核完全运行后,让一切以应有的方式运行”。本质上它建立并操作整个用户空间。这包括检查和挂载文件系统,启动必要的用户服务,最终在系统启动完成时切换到用户环境。
- `systemd` - systemd 的开发人员旨在替换继承自 Unix System V 的 Linux init 系统。与 init 一样,systemd 是一个管理其他守护进程的守护进程。所有守护进程,包括 systemd,都是后台进程。Systemd 是第一个启动(在引导期间)和最后一个终止(在关机期间)的守护进程。
- `runit` - runit 是一种用于类 Unix 操作系统的 init 方案,它在整个操作系统生命周期中初始化、监控和终止进程。它是 daemontools 进程监督工具包在 Linux、Mac OS X、\*BSD 和 Solaris 操作系统上的重新实现。
实用资源:
- [分析 Linux 引导过程](https://opensource.com/article/18/1/analyzing-linux-boot-process)
- [Systemd 引导过程:Linux 中的深入观察](https://linoxide.com/linux-how-to/systemd-boot-process/)
</details>
<details>
<summary><b>Linux 守护进程如何以及为何降低权限?为什么某些守护进程需要 root 权限才能启动?请解释。 ***</b></summary>
待补充。
</details>
<details>
<summary><b>为什么单核机器上负载 1.00 并不理想?</b></summary><br>负载为1.00的问题在于你没有余量。实际上,许多系统管理员会把警戒线划在0.70。
**“需要调查”的经验法则:0.70**
如果你的负载平均值持续高于>0.70,那么在情况变得更糟之前,是时候开始调查了。
**“立即修复”的经验法则:1.00**
如果你的负载平均值持续高于1.00,找到问题并立即修复。否则,你会在半夜被叫醒,而且那可不是什么好体验。
**经验法则:5.0**
如果你的负载平均值高于5.00,你可能陷入了严重的麻烦,你的机器要么挂起要么变得极慢,而且这(莫名其妙地)会发生在最糟糕的时刻,比如半夜或者你在做会议演示的时候。不要让它发展到那一步。
有用的资源:
- [在4核8线程处理器上解释系统负载的正确方式](https://serverfault.com/questions/618130/proper-way-of-interpreting-system-load-on-a-4-core-8-thread-processor)
- [理解Linux CPU负载——什么时候应该担心?](http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages)
</details>
<details>
<summary><b>当有效用户是root,但真实用户ID仍然是你的名字时,这意味着什么?</b></summary><br>
**真实用户ID**是你真实的身份(拥有该进程的用户),而**有效用户ID**是操作系统在做决策时查看的标识,用于判断你是否被允许执行某个操作(大多数情况下,但也有例外)。
当你登录时,登录shell会将**真实和有效用户ID**都设置为与密码文件中提供的值相同的值(你的**真实用户ID**)。
例如,如果你执行了setuid,并且除了以另一个用户(如**root**)身份运行外,该setuid程序还需要代表你执行某些操作。
在setuid执行后,它将拥有你的**真实ID**(因为你是进程所有者)和文件所有者(例如**root**)的有效用户ID(因为它是setuid)。
以`passwd`为例:```bash
-rwsr-xr-x 1 root root 45396 may 25 2012 /usr/bin/passwd
使用 logrotate 是处理日志文件的常用方法。但不要将内容添加到 /etc/logrotate.conf,而应该将自己的任务添加到 /etc/logrotate.d/,否则在版本升级时你将不得不检查更多的配置文件差异。
如果日志文件正在被持续写入,你能做的截断操作其实很有限。唯一的选择是截断文件:```bash : >/var/log/massive-logfile
这非常有用,因为它能截断文件而不中断进程。
有用资源:
- [如何使用 logrotate 管理日志文件](https://www.linode.com/docs/uptime/logs/use-logrotate-to-manage-log-files/)
- [系统日志](https://www.ibm.com/developerworks/library/l-lpic1-108-2/index.html)
</details>
<details>
<summary><b>Linux 内核如何创建、管理和删除系统中的进程?***</b></summary><br>
待完成。
有用资源:
- [Linux 进程](https://www.tldp.org/LDP/tlk/kernel/processes.html)
</details>
<details>
<summary><b>解释在 `top` 和 `htop` 中可以看到的选定信息。如何使用这些工具诊断负载、高用户时间和内存不足问题?***</b></summary><br>
待完成。
有用资源:
- [top 可视化解释](https://www.svennd.be/top-explained-visually/)
- [htop 可视化解释](https://codeahoy.com/2017/01/20/hhtop-explained-visually/)
- [Linux 上 htop/top 中所有内容的解释](https://peteris.rocks/blog/htop/)
</details>
<details>
<summary><b>如何识别一个占用资源的进程?</b></summary><br>
`top` 效果相当不错,只要您查看正确的数字。
- **M** 按当前常驻内存使用量排序
- **T** 按总(或累计)CPU 使用量排序
- **P** 按当前 CPU 使用量排序(这是默认刷新方式)
- **?** 显示所有 top 命令的使用摘要
在排查计算机进程运行缓慢的原因以及决定要终止哪些进程/卸载哪些软件时,获取这些信息非常重要。
有用资源:
- [如何查找占用机器的进程](https://superuser.com/questions/326300/how-to-find-the-processes-which-are-hogging-the-machine)
</details>
<details>
<summary><b>您需要在 200 台服务器上升级 `ntpd` 服务。将所有服务器升级到最新版本的最佳方法是什么?</b></summary><br>
通过使用**基础设施即代码**方法,有几种好方法:
1. **配置同步变更管理模型**:有配置管理工具(Ansible、Chef、Puppet、Saltstack 等)可用于自动更新所有服务器上的 `ntpd` 服务。为了保持系统稳定,服务器上的系统包通常只通过安全更新自动更新。包的主要或次要版本通常在配置定义中进行版本锁定,以防止服务配置错误。然后通过更改配置定义中的 `ntpd` 版本来部署变更。采用这种方法时,在大规模部署变更到基础设施时需要小心。部署流水线应包括单元测试、集成测试和系统测试,并最终首先部署到预发布环境以验证配置。如果测试证明配置正确,则应通过增量发布进行部署,并在出现错误或失败时具备回滚能力。
2. **不可变服务器模型**:在不可变服务器模型中,整个单元(服务器、容器)被新的更新镜像取代,而不是对运行中的服务器进行更改(这消除了配置漂移)。采用这种方法时,您通常使用 Packer 或 Docker 与 Dockerfile 等工具构建服务器镜像。然后对该镜像进行测试和部署,类似于上述选项 (1.),但现在使用金丝雀发布等技术,这些技术也具备增量发布和回滚的能力。
有用资源:
- [基础设施即代码 - 第 8 章:更新和更改服务器的模式](http://shop.oreilly.com/product/0636920039297.do)
</details>
<details>
<summary><b>如何在 Linux/Unix 上永久设置 `$PATH`?为什么这个变量如此重要?***</b></summary>
待完成。
</details>
<details>
<summary><b>当您的服务器启动时,控制台会出现一些错误。如何检查启动消息以及它们存储在哪里?</b></summary><br>
您的控制台有两种类型的消息:
- **由内核生成**(通过 printk)
- **由用户空间生成**(通常是您的初始化系统)
内核消息始终存储在 **kmsg** 缓冲区中,可通过 `dmesg` 命令查看。它们也经常被复制到您的 **syslog** 中。这也适用于写入 `/dev/kmsg` 的用户空间消息,但这种情况相当罕见。
与此同时,当用户空间将其花哨的启动状态文本写入 `/dev/console` 或 `/dev/tty1` 时,这些内容根本不会存储在任何地方。它们只是显示在屏幕上,仅此而已。
`dmesg` 用于查看内核环形缓冲区中包含的启动消息。环形缓冲区是一种固定大小的缓冲区,其中添加的任何新数据都会覆盖其中的最旧数据。
它显示启动过程完成后的操作,例如传递给内核的命令行选项;检测到的硬件组件;添加新 USB 设备时的事件;或 NIC(网络接口卡)故障等错误以及驱动程序报告网络上未检测到链路活动等。
如果系统日志记录是通过 journal 组件完成的,则应使用 `journalctl`。它显示的消息包括内核和启动消息;来自 syslog 或各种服务的消息。
启动问题/错误要求系统管理员结合特定命令查看某些重要文件(不同 Linux 版本的处理方式不同):
- `/var/log/boot.log` - 系统启动日志,包含系统启动期间展开的所有内容
- `/var/log/messages` - 存储全局系统消息,包括系统启动期间记录的消息
- `/var/log/dmesg` - 包含内核环形缓冲区信息
有用资源:
- [启动后如何在 Linux 中查看所有启动消息?(原文)](https://superuser.com/questions/1188407/how-to-view-all-boot-messages-in-linux-after-booting)
- [/var/log/{syslog,dmesg,messages} 日志文件的区别](https://superuser.com/questions/565927/differences-in-var-log-syslog-dmesg-messages-log-files)
- [如何稍后查看 Debian 系统启动时滚动的消息?](https://serverfault.com/questions/516411/all-debian-boot-messages)
</details>
<details>
<summary><b>交换使用率过高。可能的原因是什么?如何解决交换问题?</b></summary><br>
**交换**空间是一部分受限的物理内存,分配用于在可用内存已完全利用时由操作系统使用。这是一种内存管理方式,涉及将内存部分与物理存储之间进行交换。
如果系统需要更多内存资源且 RAM 已满,内存中的非活动页面会被移至交换空间。虽然交换空间可以帮助 RAM 较小的机器,但不应将其视为更多 RAM 的替代品。**交换**空间位于硬盘上,其访问时间比物理内存慢。
工作负载增加了您的 RAM 需求。您正在运行需要更多内存的工作负载。整个交换区的使用表明了这一点。此外,将 `swappiness` 更改为 **1** 可能不是一个明智的决定。将 `swappiness` 设置为 **1** 并不意味着不会进行交换。它只是表明内核在交换方面的积极程度,并不会消除交换。如果需要,交换仍会发生。
- **增加交换空间的大小** - 首先,您会增加磁盘使用。如果您的磁盘速度不够快,那么您的系统可能会最终出现颠簸,并且随着数据在内存中交换进出,您会体验到速度变慢。这会导致瓶颈。
- **添加更多 RAM** - 真正的解决方案是添加更多内存。RAM 无法替代,如果您有足够的内存,交换就会减少。
用于监控交换空间使用情况:
- `cat /proc/swaps` - 查看总交换大小和已用交换大小
- `grep SwapTotal /proc/meminfo` - 显示总交换空间
- `free` - 显示空闲和已用系统内存量(也包括交换)
- `vmstat` - 检查交换统计信息
- `top`, `htop` - 检查交换空间使用情况
- `atop` - 显示您的系统是否过度提交内存
- 或使用单行 shell 命令列出所有应用程序以及它们使用的交换空间大小(以千字节为单位):```bash
for _fd in /proc/*/status ; do
awk '/VmSwap|Name/{printf $2 " " $3}END{ print ""}' $_fd
done | sort -k 2 -n -r | less
在 Linux 和其他类 Unix 操作系统上,新文件以一组默认权限创建。具体来说,通过应用一个称为 umask 的权限“掩码”,可以以特定方式限制新文件的权限。umask 命令用于设置此掩码,或显示其当前值。
永久更改(例如设置 umask 02):
~/.profile~/.bashrc~/.zshrc~/.cshrc实用资源:
在文件系统底层,文件由 inode 表示(或者可能是多个 inode,不确定)。
当删除一个文件时,它移除对底层 inode 的一个链接。只有当所有指向该 inode 的链接都被删除后,该 inode 才会被删除(或可删除/可覆盖)。
一旦创建了硬链接,该链接就指向 inode。删除、重命名或移动原始文件不会影响硬链接,因为它链接到底层 inode。对 inode 数据的任何更改都会反映在所有指向该 inode 的文件上。
注意:硬链接仅在同一个文件系统内有效。符号链接可以跨文件系统,因为它们只是另一个文件的名称。
区别:
实用资源:
SUID/GUID 是一样的吗?这可能是最让我恼火的事情之一,因为人们总是把它搞混。SUID/GUID 位和粘滞位是完全不同的两件事。
如果执行 man chmod,你可以阅读关于 SUID 和粘滞位的内容。
SUID/GUID
上述手册页试图说明的是,在 rwxrwxrwx 中,用户八进制(第一组 rwx)和组八进制(第二组 rwx)中 x 位占据的位置可以有一个额外的状态,即 x 变成 s。当这种情况发生时,文件在执行时(如果它是一个程序而不仅仅是 shell 脚本)将以其所有者或所在组的权限运行。
所以,如果文件归 root 所有,并且启用了 SUID 位,那么程序将以 root 身份运行,即使你以普通用户身份执行它。GUID 位同理。
示例:
无 suid/guid - 仅设置了权限位 rwxr-xr-x。```bash
ls -lt b.pl
-rwxr-xr-x 1 root root 179 Jan 9 01:01 b.pl
**suid 且用户的可执行位已启用(小写 s)** - 设置了 `rwsr-x-r-x` 位。```bash
chmod u+s b.pl
ls -lt b.pl
-rwsr-xr-x 1 root root 179 Jan 9 01:01 b.pl
SUID 已启用且可执行位已禁用(大写S) —— 设置权限位为 rwSr-xr-x。```bash
chmod u-x b.pl
ls -lt b.pl
-rwSr-xr-x 1 root root 179 Jan 9 01:01 b.pl
**guid & group 的可执行位已启用(小写 s)** - 设置了 `rwxr-sr-x` 位。```bash
chmod g+s b.pl
ls -lt b.pl
-rwxr-sr-x 1 root root 179 Jan 9 01:01 b.pl
guid启用且可执行位被禁用(大写S) - 设置了权限位 rwxr-Sr-x。```bash
chmod g-x b.pl
ls -lt b.pl
-rwxr-Sr-x 1 root root 179 Jan 9 01:01 b.pl
**粘滞位 (sticky bit)**
另一方面,粘滞位用 `t` 表示,例如在 `/tmp` 目录中:```bash
ls -l /|grep tmp
drwxrwxrwt. 168 root root 28672 Jun 14 08:36 tmp
LC_ALL=C有什么作用?在什么情况下它会有用?LC_ALL 是覆盖所有其他本地化设置的环境变量。它一次性将所有 LC_ 类型的变量设置为指定的区域设置。
在命令前设置LC_ALL=C的主要原因是,可以简单地获得英文输出(通常更改命令使用的区域设置)。
另一方面,同样重要的是使用LC_ALL=C可以提高命令执行速度,例如grep或fgrep。使用LC_ALL=C区域设置可以提高性能并减少命令执行时间。
例如,如果你设置LC_ALL=en_US.utf8,你的系统会从/usr/lib/locale目录打开多个文件。而对于LC_ALL=C,只执行最少的打开和读取操作。
如果你想恢复会话的所有正常(原始)区域设置:```bash LC_ALL=
如果 `LC_ALL` 不起作用,请尝试使用 `LANG`(如果仍然不起作用,请尝试 `LANGUAGE`):```bash
LANG=C date +%A
Monday
有用资源:
待补充。
1) 主要要求 - 记住这一点
/var/www/app01/html)umask 值以及 suid/sgid(仅适用于特定情况)2) 应用目录
/var/www 包含每个网站的目录(应用的隔离),例如 /var/www/app01、`/var/www/app02````bash
mkdir /var/www/{app01,app02}
**3) 应用所有者和组**
每个应用都有指定的**所有者**(例如 **u01-prod**、**u02-prod**)和**组**(例如 **g01-prod**、**g02-prod**),这些被设置为网站目录中所有文件和目录的所有者:```bash
chown -R u01-prod:g01-prod /var/www/app01
chown -R u02-prod:g02-prod /var/www/app02
4) 开发者所有者与组
所有维护网站的用户都有自己的组,并且它们附加到应用程序组:```bash id alice uid=2000(alice) gid=4000(alice) groups=8000(g01-prod) id bob uid=2001(bob) gid=4001(bob) groups=8000(g01-prod),8001(g02-prod)
因此,**alice** 用户对 `/var/www/app01` 拥有标准权限,而 **bob** 用户对 `/var/www/app01` 和 `/var/www/app02` 拥有标准权限。
**5) Web 服务器所有者与组**
任何需要由 Web 服务器写入的文件或目录都有其所有者。如果 Web 服务器是 Apache,默认所有者/组为 **apache:apache** 或 **www-data:www-data**;对于 Nginx,则为 **nginx:nginx**。请勿更改这些设置。
如果应用程序使用诸如 **uwsgi** 或 **php-fpm** 之类的应用服务器,则应在特定配置文件中设置适当的用户和组(例如,对于 **app01**,应设置为 **u01-prod:g01-prod**)。
**6) 权限**
使用 **访问控制列表(ACL)** 正确设置权限:```bash
# For web server
setfacl -Rdm "g:apache:rwx" /var/www/app01
setfacl -Rm "g:apache:rwx" /var/www/app01
# For developers
setfacl -Rdm "g:g01-prod:rwx" /var/www/app01
setfacl -Rm "g:g01-prod:rwx" /var/www/app01
在类 Unix 系统中设置内核参数,首先编辑文件 /etc/sysctl.conf,做出更改后保存文件并运行命令 sysctl -p,这条命令会永久应用更改而无需重启机器。
有用的资源:
/proc 文件系统。/proc 是一个虚拟文件系统,提供关于内核、硬件和正在运行的进程的详细信息。
由于 /proc 包含虚拟文件,因此被称为虚拟文件系统。这些虚拟文件具有独特的性质。大部分显示为零字节大小。
诸如 /proc/interrupts、/proc/meminfo、/proc/mounts 和 /proc/partitions 的虚拟文件提供了系统硬件的实时快照。其他:/proc/filesystems 文件和 /proc/sys/ 目录提供系统配置信息和接口。
有用的资源:
待完成。
在 ext3/ext4 文件系统中有三种可用的日志记录类型:
inode 是 Linux 及其他类 Unix 操作系统上文件系统的一种数据结构,它存储了关于文件的所有信息,除了文件名和实际数据。数据结构是一种存储数据的方式,以便能高效使用。
Unix 文件存储在磁盘的两个不同部分——数据块和 inode。我不会深入讨论超级块和其他深奥的信息。数据块包含文件的“内容”。关于文件的信息存储在其他地方——即 inode 中。
使用 ls 命令可以轻松找到文件的 inode 编号,该命令默认会列出当前目录(用户当前工作目录)中的对象(即文件、链接和目录),配合 -i 选项使用。例如,以下命令将显示当前目录中每个对象的名称及其 inode 编号:```bash
ls -i
`df's` `-i` 选项指示它提供每个文件系统上 inode 的信息,而不是可用空间。具体来说,它告诉 `df` 为每个挂载的文件系统返回 inode 总数、空闲 inode 数、已用 inode 数以及 inode 使用百分比。该选项可以与 `-h` 选项一起使用,如下所示,以使输出更易于阅读:```bash
df -hi
通过inode查找文件
如果你知道inode,你可以使用find命令找到它:```bash find . -inum 435304 -print
**删除具有奇怪名称的文件**
有时候文件会以包含奇怪字符的文件名创建。Unix 文件系统允许文件名中包含除空字符(ASCII 000)或 "/" 之外的任何字符。所有其他字符都是允许的。
用户可以创建带有难以查看目录或文件的字符的文件。例如,他们可以创建以空格结尾的目录 ".. ",或者使用以下方式创建一个在名称中带有退格键的文件:```bash
touch `printf "aa\bb"`
那么当你使用 ls 命令时会发生什么呢:```bash
ls
aa?b
ls | grep 'a'
ab
注意,当 `ls` 将结果发送到终端时,它会在文件名中放置一个 "**?**" 来表示不可打印的字符。
你可以使用 `rm -i *` 来删除这个文件,它在删除每个文件前会提示你。但你也可以使用 `find` 来移除文件,一旦你知道了 inode 编号。```bash
ls -i
435304 aa?b
find . -inum 435304 -delete
有用的资源:
ls -l 显示文件属性为问号。这意味着什么,你将采取哪些步骤来删除未使用的“僵尸”文件?这个问题可能更难解决,因为可能需要几个步骤——有时你可能会遇到 test/file: Permission denied、test/file: No such file or directory 或 test/file: Input/output error。
当用户无法对文件执行 stat()(需要执行权限),但可以读取目录条目(需要对目录具有读取权限)时,就会发生这种情况。因此,你会在目录中看到文件列表,但由于无法读取文件而无法获取有关文件的任何信息。如果你有一个具有读取权限但没有执行权限的目录,你将看到这种情况。
某些进程(如 rsync)会生成临时文件,这些文件创建和删除速度很快,如果你尝试调用其他简单的文件管理命令(如 rm、mv 等),则会导致错误。
输出示例:```bash ?????????? ? ? ? ? ? sess_kee6fu9ag7tiph2jae
1) 更改权限:`chmod 0777 sess_kee6fu9ag7tiph2jae` 并尝试删除
2) 更改所有者:`chown root:root sess_kee6fu9ag7tiph2jae` 并尝试删除
3) 更改目录的权限和所有者:`chmod -R 0777 dir/ && chown -R root:root dir/` 并尝试删除
4) 重新创建文件:`touch sess_kee6fu9ag7tiph2jae` 并尝试删除
5) 注意服务器上运行的其他进程,例如 `rsync`,有时当 NFS 服务器负载过高时,你可能会看到这是一个临时错误
6) 查找文件的 inode:`ls -i`,并尝试删除:`find . -inum <inode_num> -delete`
7) 重新挂载(如果可能)你的文件系统
8) 以单用户模式启动系统并用 `fsck` 修复文件系统
实用资源:
- [ls 目录时显示问号。还有 IO 错误。](https://serverfault.com/questions/65616/question-marks-showing-in-ls-of-directory-io-errors-too)
</details>
<details>
<summary><b>使用 LVM 还是不使用 LVM?它提供了什么好处?</b></summary><br>
- LVM 使得移动文件系统变得非常容易
- 你可以将卷组扩展到新的物理卷上
- 将任意数量的逻辑卷从旧物理卷上移走
- 从卷组中移除该卷,无需卸载任何分区
- 你还可以创建逻辑卷的快照用于备份
- LVM 内置镜像支持,因此你可以在多个物理卷上镜像一个逻辑卷
- LVM 甚至支持 TRIM
实用资源:
- [什么是 LVM,它有什么用途?](https://askubuntu.com/questions/3596/what-is-lvm-and-what-is-it-used-for)
</details>
<details>
<summary><b>如何增加 LVM 分区的大小?</b></summary><br>
使用 `lvextend` 命令来调整 LVM 分区的大小。
- 将大小扩展 500MB:```bash
lvextend -L +500M /dev/vgroup/lvolume
例如(使用 visudo 命令):```bash
user1 ALL=(user2) NOPASSWD: /opt/scripts/bin/generate.sh
命令路径必须是绝对路径!然后从一个 user1 shell 中调用 `sudo -u user2 /opt/scripts/bin/generate.sh`。
</details>
<details>
<summary><b>如何在 bash 脚本中检查是否以 root 身份运行?需要注意什么?</b></summary><br>
在 bash 脚本中,有几种方法可以检查运行用户是否是 root。
警告:不要通过 root 用户名来检查用户是否为 root。没有任何保证用户 ID 为 0 的用户被称为 root。这是一个广泛遵循的强约定,但任何人都可以将超级用户重命名为其他名称。
我认为在使用 bash 时最好的方法是使用 `$EUID`,因为 `$UID` 可能会被更改,从而无法反映实际运行脚本的用户。```bash
if (( $EUID != 0 )); then
echo "Please run as root"
exit
fi
nobody账号吗?请告诉我以nobody和www-data账号运行httpd服务的区别。在许多Unix变体中,nobody是一个惯例用户名,该用户不拥有任何文件,不属于任何特权组,仅具有其他每个用户都拥有的基本权限。
将守护进程(尤其是服务器)以nobody身份运行很常见,目的是限制恶意用户获得控制权后可能造成的损害。
但是,如果多个守护进程都以此方式运行,该技术的有效性会降低,因为控制其中一个守护进程意味着可以控制所有守护进程。原因是nobody拥有的进程能够相互发送信号,甚至调试对方,从而读取或修改彼此的内存。
何时应该使用nobody账号?
当程序的运行不需要任何权限时。最典型的情况是程序永远不会涉及磁盘活动。
一个现实中的例子是memcached(一种键值内存缓存/数据库/类似物)。在我的电脑和服务器上,它就是以nobody账号运行的。为什么?因为它根本不需要任何权限,如果给它一个具有文件写入权限的账号,只会带来不必要的风险。
Web服务器也是个好例子。想象一下如果Apache以root身份运行,而有人找到通过Apache向控制台发送自定义命令的方法,那么他将能够访问你的整个系统。
nobody账号还用作受限shell,让用户能够访问文件系统,但不提供类似bash的实际shell。这应能阻止用户执行任意操作。
httpd (Apache) 应使用nobody还是www-data
Apache启动时需要root权限,但随后会迅速放弃该权限,转而以非特权用户身份运行。这个用户可以是nobody、或。
你需要的命令是 tee:
foo | tee output.file
例如,如果你只关心标准输出:
ls -a | tee output.file
如果你想包含标准错误,使用:
program [arguments...] 2>&1 | tee outfile
2>&1 将通道2(stderr/标准错误)重定向到通道1(stdout/标准输出),这样两者都会以标准输出形式写入。通过 tee 命令,它们也会被定向到指定的输出文件。
此外,如果你想追加到日志文件,使用 tee -a,例如:
program [arguments...] 2>&1 | tee -a outfile
./script或bash script执行文件有什么区别?你应该使用 #!/usr/bin/env bash 以实现可移植性:不同的 *nix 系统将 bash 放在不同位置,使用 /usr/bin/env 是一种变通方法,可以运行 PATH 中找到的第一个 bash。
运行 ./script 正是执行该操作,需要文件具有执行权限,但不关心它是什么类型的程序。它可以是 bash脚本、sh脚本、Perl、Python、awk、expect脚本 或实际的 二进制可执行文件。而运行 bash script 则强制它以 sh 身份运行,而不是其他解释器。
有用的资源:
使用 nohup 让进程忽略挂断信号:```bash
nohup long-running-process &
exit
或者你想要使用 **GNU Screen**:```bash
screen -d -m long-running-process
exit
有用资源:
要了解中间 CA 的主要目的,您首先应该了解 根 CA、中间 CA 以及 SSL 证书链信任。
根 CA 是主要的 CA,通常不直接签署最终实体/服务器证书。它们颁发根证书,这些证书通常预安装在所有浏览器、移动设备和应用程序中。这些证书的私钥用于签署其他后续证书,称为中间证书。根 CA 通常保持“离线”状态,并置于高度安全的环境中,访问权限受到严格限制。
中间 CA 是根 CA 下属的一个或多个级别的 CA,受根 CA 信任代其签署证书。创建和使用中间 CA 的主要目的是安全,因为如果中间私钥被泄露,根 CA 可以撤销中间证书并使用新的加密密钥对创建新证书。
SSL 证书链信任 是从根证书到最终实体/服务器证书的 SSL 证书列表。要使 SSL 证书受信任,它必须由受信任的 CA 颁发,并且该 CA 包含在连接设备(浏览器、移动设备和应用程序)的受信任 CA 列表中。因此,连接设备将测试链信任中每个 SSL 证书的可信度,直到匹配到由受信任 CA 颁发的证书。
每个主要 CA 都创建了根-中间 CA 结构,以防止根密钥泄露带来的灾难性后果。如果根密钥被泄露,将导致根证书及其所有下属证书不可信。因此,创建中间 CA 是确保严格保护主根密钥的最佳实践。
有用资源:
解决方案 1:```bash systemctl reload postgresql
解决方案2:```
su - postgres
/usr/bin/pg_ctl reload
解决方案3:``` SELECT pg_reload_conf();
</details>
<details>
<summary><b>你向 <code>.profile</code> 添加了几个别名。如何在不退出的情况下重新加载 shell?</b></summary><br>
最佳方式是 `exec $SHELL -l`,因为 `exec` 会用新进程替换当前进程。另一个不错的(但不同的)方案是 `. ~/.profile`。
实用资源:
- [如何从命令行重新加载 .bash_profile?](https://stackoverflow.com/questions/4608187/how-to-reload-bash-profile-from-the-command-line)
</details>
<details>
<summary><b>如何在不保存 shell 历史的情况下退出?</b></summary><br>```bash
kill -9 $$
或```bash unset HISTFILE && exit
有用资源:
- [如何在不保存历史记录的情况下关闭终端?](https://unix.stackexchange.com/questions/25049/how-do-i-close-a-terminal-without-saving-the-history)
</details>
<details>
<summary><b>什么是 UID 0 toor 账户?我是否被入侵了?</b></summary><br>
**toor** 是一个替代超级用户账户,toor 是 root 的倒拼。它的目的是与一个非标准 shell 一起使用,这样就不需要更改 root 的默认 shell。
这一点很重要,因为不属于基础发行版,而是从 ports 或 packages 安装的 shell,会被安装在 `/usr/local/bin` 中,默认情况下,该目录位于不同的文件系统上。如果 root 的 shell 位于 `/usr/local/bin`,而包含 `/usr/local/bin` 的文件系统没有被挂载,那么 root 将无法登录来修复问题,而必须重启进入单用户模式,以便手动指定 shell 的路径。
有些人使用 toor 配合非标准 shell 进行日常的 root 操作,而将 root(使用标准 shell)保留给单用户模式或紧急情况使用。默认情况下,用户无法使用 toor 登录,因为它没有密码,因此需要先以 root 身份登录,并为 toor 设置密码后才能使用 toor 登录。
有用资源:
- [root 账户(以及 toor)](https://administratosphere.wordpress.com/2007/10/04/the-root-account-and-toor/)
</details>
<details>
<summary><b>有没有一种简单的方法可以在复杂的目录结构中搜索数千个文件,找到包含特定字符串的文件?</b></summary><br>
例如使用 `fgrep`:```bash
fgrep * -R "string"
很容易陷入关于克隆环境的细节争论而忽略真正要点:
每次部署时,你都在测试部署代码、软件和环境的独特组合。
偶尔一个好的解决方案是定期克隆生产服务器来创建测试服务器。你可以通过快照在开发/测试环境中创建与生产环境完全一致的实例,例如:
当然,你可以启动各种系统组件或整个系统的克隆,并捕获真实流量进行离线重放(系统测试的黄金标准)。但许多系统过于庞大、复杂且成本高昂,无法克隆。
在环境同步之前,一个好的方法是记录你对测试环境所做的每一次更改,并提供一种将这些更改传播到生产环境的方法,这样你就不会跳过任何步骤,并能尽可能平滑地完成。
另外,结构对比工具或从生产环境更新测试环境的部署脚本也是一个好的解决方案。
同步前任务
首先,通知开发人员和客户端不要在测试环境上进行更改(如果可能,禁用指向该环境的测试域名,或设置包含同步信息的静态页面)。
同时,对两个环境进行备份/快照也很重要。
数据库服务器
Web/应用服务器
其他任务
有用的资源:
待完成。
如果你可以 telnet 到该端口,说明监听该端口的服务正在运行,并且你可以连接上(这不是网络问题)。最好通过域名解析的 IP 地址以及使用相同的域名来测试连接。
首先,从其他位置检查你的网站是否在线。这样你就可以知道网站是全局宕机,还是只有你的网络无法访问。同时也建议检查 Web 浏览器返回的内容。
如果只有 IP 连接正常
whois www.example.comdig 或 host 等工具测试 DNS,检查主机名是否解析:host www.example.org dns.example.orghost www.example.com 9.9.9.9如果域名未解析,问题可能出在 DNS 服务器上。
如果域名解析正常
nginx -t -c </path/to/nginx.conf>),也许其他系统管理员修改了域名的配置?待完成。
待完成。
HTTP/2 支持查询复用、头部压缩、优先级以及更智能的数据包流管理。这减少了延迟并加速了现代网页上的内容下载。
与 HTTP/1.1 的主要区别:
有用的资源:
POST http://ws.int/api/v1/Submit/ 导致 413 Request Entity Too Large。出了什么问题?修改域名的 NGINX 配置文件
设置正确的 client_max_body_size 变量值:```bash
client_max_body_size 20M;
重新启动 Nginx 以应用更改。
**修改 php.ini 文件以设置上传限制**
并非所有配置都需要此操作,但您可能也需要修改 PHP 上传设置,以确保 PHP 配置不会导致任何内容超出限制。
现在逐一找到以下指令:```bash
upload_max_filesize
post_max_size
并将其限制增加到20M,默认情况下它们是8M和2M:```bash upload_max_filesize = 20M post_max_size = 20M
最后保存并重启PHP。
有用资源:
- [413 Request Entity Too Large in Nginx with client_max_body_size set](https://serverfault.com/questions/814767/413-request-entity-too-large-in-nginx-with-client-max-body-size-set)
</details>
<details>
<summary><b>什么是握手机制,为什么我们需要三次握手?</b></summary><br>
**握手**开始于一个设备向另一个设备发送消息,表明它想要建立通信信道。然后两个设备来回发送若干消息,使它们能够就通信协议达成一致。
**三次握手**是一种在TCP/IP网络中用于在本地主机/客户端和服务器之间创建连接的方法。它是一个三步方法,要求客户端和服务器在实际数据通信开始之前交换`SYN`和`ACK`(`SYN`、`SYN-ACK`、`ACK`)包。
有用资源:
- [为什么我们需要三次握手?为什么不是两次?](https://networkengineering.stackexchange.com/questions/24068/why-do-we-need-a-3-way-handshake-why-not-just-2-way)
</details>
<details>
<summary><b>为什么UDP比TCP快?</b></summary><br>
**UDP**比**TCP**快,简单原因在于它不存在的确认包(`ACK`)允许连续的数据包流,而TCP则需要通过TCP窗口大小和往返时间(`RTT`)计算来确认一组包。
有用资源:
- [UDP vs TCP,到底快多少?](https://stackoverflow.com/questions/47903/udp-vs-tcp-how-much-faster-is-it)
</details>
<details>
<summary><b>您认为哪5个OpenSSH参数对于提高安全性最重要?***</b></summary><br>
待完成。
有用资源:
- [OpenSSH安全与加固](https://linux-audit.com/audit-and-harden-your-ssh-configuration/)
</details>
<details>
<summary><b>什么是NAT?它有什么用途?</b></summary><br>
它使使用未注册IP地址的私有IP网络能够连接到互联网。**NAT**运行在路由器上,通常连接两个网络,在包被转发到另一个网络之前,将内部网络中的私有(非全局唯一)地址转换为合法地址。
需要特殊访问网络外部的工作站或其他计算机可以通过**NAT**分配特定的外部IP,使它们能够与需要唯一公共IP地址的计算机和应用程序通信。**NAT**也是防火墙安全的一个非常重要的方面。
有用资源:
- [网络地址转换(NAT)概念](http://www.firewall.cx/networking-topics/network-address-translation-nat/227-nat-concepts.html)
</details>
<details>
<summary><b>生成树协议的目的是什么?</b></summary><br>
该协议工作在OSI模型的第二层,目的是防止网络中的环路。没有**STP**,冗余的交换机部署会产生广播风暴,甚至削弱最强大的网络。有多个基于原始IEEE 802.1D标准的迭代版本;每个版本的操作略有不同,但大多实现相同的无环路目标。
</details>
<details>
<summary><b>如何检查我的Linux服务器上哪些端口在监听?</b></summary><br>
使用:
- `lsof -i`
- `ss -l`
- `netstat -atn` - 用于tcp
- `netstat -aun` - 用于udp
- `netstat -tulapn`
</details>
<details>
<summary><b>连接到远程主机时出现<code>Host key verification failed</code>是什么意思?你会自动接受它吗?</b></summary><br>
`Host key verification failed` 表示远程主机的主机密钥已更改。当连接到一台其`/etc/ssh`中的主机密钥已更改的计算机时(如果该计算机升级时未复制其旧的主机密钥),就容易发生这种情况。这里的主机密钥是当你通过ssh重新连接到远程计算机时,证明你正在与第一次访问时连接到的同一台计算机通信的证据。
每当你通过SSH连接到服务器时,该服务器的公钥会存储在你的主目录(如果是Mac或Windows桌面,可能存储在本地账户设置中)的一个名为**known_hosts**的文件中。当你重新连接到同一台服务器时,SSH连接会验证当前公钥是否与你保存在**known_hosts**文件中的公钥匹配。如果自上次连接以来服务器密钥发生了变化,你将收到上述错误。
不要像某些人建议的那样删除整个**known_hosts**文件,这会完全抵消警告的意义。这是一个安全特性,用于警告你可能发生了中间人攻击。
在接受新的主机密钥之前,请与你的/其他系统管理员联系进行验证。
有用资源:
- [Git错误:连接远程仓库时出现“Host Key Verification Failed”](https://stackoverflow.com/questions/13363553/git-error-host-key-verification-failed-when-connecting-to-remote-repository)
</details>
<details>
<summary><b>如何使用<code>telnet</code>发送HTTP请求?</b></summary><br>
例如:```bash
telnet example.com 80
Trying 192.168.252.10...
Connected to example.com.
Escape character is '^]'.
GET /questions HTTP/1.0
Host: example.com
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...
列出监听80端口的任何进程:```bash
lsof -i:80
fuser 80/tcp
要终止任何监听端口80的进程:```bash
kill $(lsof -t -i:80)
或更暴力地:```bash kill -9 $(lsof -t -i:80)
或者使用`fuser`命令:```bash
fuser -k 80/tcp
有用资源:
curl: (56) TCP connection reset by peer。您将采取哪些步骤来解决此问题?www 或正确设置 Host: 标头?还要检查协议(http 或 https)--trace-ascii curl.dump 启用调试跟踪。 Recv failure 是一个非常通用的错误,因此很难获取更多信息--proxy 外部代理从外部IP调试连接tcpdump)在较低的TCP/IP层调试连接curl 参数检查SSL版本有用资源:
例如:```bash /sbin/iptables -A INPUT -p tcp -s XXX.XXX.XXX.XXX -j ACCEPT /sbin/iptables -A OUTPUT -p tcp -d XXX.XXX.XXX.XXX -j ACCEPT
</details>
<details>
<summary><b>如何在OpenBSD中使用<code>pf</code>阻止滥用IP地址?</b></summary><br>
最好的方法是在`pf.conf`中定义一个表格并创建一条规则来阻止这些主机:```bash
table <badhosts> persist
block on fxp0 from <badhosts> to any
然后动态地对其添加/删除IP地址:```bash pfctl -t badhosts -T add 1.2.3.4 pfctl -t badhosts -T delete 1.2.3.4
</details>
<details>
<summary><b>像 Apache 或 Nginx 这样的 Web 服务器何时将信息写入日志文件?在提供服务请求之前还是之后?</b></summary><br>
两款服务器都提供了非常全面和灵活的日志记录功能——用于记录服务器上发生的一切,从初始请求,经过 URL 映射过程,到最终连接解析,包括过程中可能出现的任何错误。
**Apache**
Apache 服务器访问日志记录服务器处理的所有请求(在请求完成后)。
**Nginx**
NGINX 在处理请求后立即将客户端请求的信息写入访问日志。
有用资源:
- [Apache 何时记录到 access.log - 在提供服务请求之前还是之后?](https://webmasters.stackexchange.com/questions/65566/when-does-apache-log-to-access-log-before-or-after-serving-the-request)
- [nginx 在处理前记录请求](https://serverfault.com/questions/693049/nginx-log-request-before-processing)
</details>
<details>
<summary><b>分析 Web 服务器日志并仅显示 <code>5xx</code> HTTP 状态码。您使用哪些外部工具?</b></summary><br>```bash
tail -n 100 -f /path/to/logfile | grep "HTTP/[1-2].[0-1]\" [5]"
举例http/https日志管理工具:
实用资源:
你拥有个人账户的私钥。服务器需要你的公钥,以便验证你尝试使用的账户的私钥是否被授权。
| 章节类型 | 问题数量 | 简要描述 |
|---|
| 引言 | ||
| 🔸 简单问题 | 14 个问题 | 轻松、有趣且简单——非常适合开始一切。 |
| 通用知识 | ||
| 🔸 初级系统管理员 | 65 个问题 | 基于基础知识,相当简单直接。 |
| 🔸 常规系统管理员 | 94 个问题 | 中级问题,假设您有扎实的知识。 |
| 🔸 高级系统管理员 | 99 个问题 | 难题和谜题。如果您想成为高手,请检查一下。 |
| 秘传知识 | ||
| 🔸 大师级系统管理员 | 12 个问题 | 真正深入的问题,以了解大师级系统管理员。 |
!! - 上一条命令的全部!ssh - 上一条以 ssh 开头的命令有用的资源:
或```bash grep -e "string1" -e "string2" filename
有用的资源:
- [什么是grep,以及如何使用它?(原文)](https://kb.iu.edu/d/afiy)
</details>
<details>
<summary><b>解释文件内容命令及其描述。</b></summary><br>
- `head`:检查文件的开头。
- `tail`:检查文件的结尾。与 head 命令相反。
- `cat`:用于查看、创建、连接文件。
- `more`:用于在终端窗口中分页显示文本。
- `less`:用于向后查看文本,并允许逐行移动。
有用的资源:
- [从 Shell 提示符查看文本文件](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/4/html/Step_by_Step_Guide/s1-viewingtext-terminal.html)
</details>
<details>
<summary><b>SIGHUP、SIGINT、SIGKILL 和 SIGTERM POSIX 信号。解释。</b></summary><br>
- **SIGHUP** - 当进程的控制终端关闭时发送给该进程。它最初设计用于通知进程串行线路断开(挂断)。许多守护进程在收到此信号时会重新加载配置文件并重新打开日志文件,而不是退出。
- **SIGINT** - 当用户希望中断进程时,由控制终端发送给该进程。通常通过按下 `Ctrl+C` 触发,但在某些系统上,也可以使用“删除”字符或“中断”键。
- **SIGKILL** - 发送给进程以使其立即终止(杀死)。与 **SIGTERM** 和 **SIGINT** 不同,该信号不能被捕获或忽略,接收进程在收到此信号时无法执行任何清理操作。
- **SIGTERM** - 发送给进程以请求其终止。与 **SIGKILL** 信号不同,它可以被捕获、解释或忽略。这使得进程能够进行优雅的终止,释放资源并保存状态(如果合适)。**SIGINT** 与 **SIGTERM** 几乎相同。
有用的资源:
- [POSIX 信号](https://dsa.cs.tsinghua.edu.cn/oj/static/unix_signal.html)
- [Unix 信号编程简介](http://titania.ctie.monash.edu.au/signals/)
</details>
<details>
<summary><b><code>kill</code> 命令做什么?</b></summary><br>
在 Unix 及类 Unix 操作系统中,`kill` 是一个用于向进程发送信号的命令。默认情况下,发送的消息是终止信号,请求进程退出。但 `kill` 这个名称有些误导;发送的信号可能与杀死进程无关。
有用的资源:
- [掌握 Linux 中的“Kill”命令](https://www.maketecheasier.com/kill-command-in-linux/)
</details>
<details>
<summary><b><code>rm</code> 和 <code>rm -rf</code> 之间的区别是什么?</b></summary><br>
`rm` 只删除指定的文件(不删除目录)。使用 `-rf` 参数时:
- `-r`, `-R`, `--recursive` 递归删除目录的内容,包括隐藏文件和子目录
- `-f`, `--force` 忽略不存在的文件,从不提示
有用的资源:
- [`rm -r` 和 `rm -f` 之间的区别是什么?](https://superuser.com/questions/1126206/what-is-the-difference-between-rm-r-and-rm-f)
</details>
<details>
<summary><b>如何递归使用 <code>grep</code>?通过多个示例进行解释。***</b></summary>
待完成。
</details>
<details>
<summary><b><code>archive.tgz</code> 大约有 30 GB。如何列出其内容并只提取一个文件?</b></summary><br>```bash
# list of content
tar tf archive.tgz
# extract file
tar xf archive.tgz filename
有用的资源:
| 服务 | 端口 |
|---|---|
| SMTP | 25 |
| FTP | 20 用于数据传输,21 用于建立连接 |
| DNS | 53 |
| DHCP | 67/UDP 用于 DHCP 服务器,68/UDP 用于 DHCP 客户端 |
| SSH | 22 |
有用的资源:
您有时可以将 IP 地址反向解析为主机名。IP 地址可以存储为 PTR 记录。然后您可以执行:```bash dig A
要查找主机的IPv4地址,或者:```bash
dig AAAA <hostname>
要查找主机的IPv6地址,或者:```bash dig PTR ZZZ.YYY.XXX.WWW.in-addr.arpa.
查找IPv4地址`WWW.XXX.YYY.ZZZ`的主机名(注意八位字节是反转的),或者:```bash
dig PTR b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
有用的资源:
当 user2 想要更改自己的密码时,他们会执行 /usr/bin/passwd。
该进程的 RUID 将是 user2,但 EUID 为 root。
user2 只能使用 passwd 更改自己的密码,因为 passwd 内部会检查 RUID,如果不是 root,其操作将仅限于真实用户的密码。
对于 passwd 来说,EUID 必须成为 root,因为该进程需要写入 /etc/passwd 和/或 /etc/shadow。
有用资源:
实用资源:
| Umask | 文件结果 | 目录结果 |
|---|---|---|
| 000 | 666 rw- rw- rw- | 777 rwx rwx rwx |
| 002 | 664 rw- rw- r-- | 775 rwx rwx r-x |
| 022 | 644 rw- r-- r-- | 755 rwx r-x r-x |
| 027 | 640 rw- r-- --- | 750 rwx r-x --- |
| 077 | 600 rw---- --- | 700 rwx --- --- |
| 277 | 400 r-- --- --- | 500 r-x --- --- |
实用资源:
这个位本应一直被称为_受限删除位_,因为这才是它真正表达的含义。当这个模式位启用时,它使得目录中的用户只能删除自己拥有的文件和子目录。
实用资源:
如果您使用 SELinux,请注意安全上下文:```bash chcon -R system_u:object_r:httpd_sys_content_t /var/www/app01
**7) 安全错误**
- **root** 拥有文件和目录
- **root** 永远不会在网站目录中执行任何文件,也不应在此创建文件
- 权限过于宽泛,如 **777**,导致某些关键文件可能被全局可写和可读
- 避免创建带有 suid root 的维护脚本或其他关键文件
如果你允许站点修改构成运行站点代码的文件,会让攻击者更容易接管你的服务器。
文件上传工具允许用户上传任意名称和任意内容的文件。这使得用户可以上传一个邮件中继 PHP 脚本到你的站点,他们可以将其放置在任何位置,将你的服务器变成转发垃圾邮件的机器。此脚本还可用于从数据库中读取所有电子邮件地址或其他个人信息。
如果恶意用户可以上传任意名称的文件但无法控制内容,那么他们可以轻松上传一个覆盖 `index.php`(或其他关键文件)的文件,从而破坏站点。
有用资源:
- [如何为 WWW 文件夹设置 Linux 权限?](https://serverfault.com/questions/124800/how-to-setup-linux-permissions-for-the-www-folder)
- [在 Linux Web 服务器上,我的网站文件/文件夹应该有什么权限?](https://serverfault.com/questions/357108/what-permissions-should-my-website-files-folders-have-on-a-linux-webserver)
- [setgid 程序的安全陷阱](https://www.agwa.name/blog/post/security_pitfalls_of_setgid_programs)
</details>
<details>
<summary><b>当你从运行级别 3 执行 <code>telinit 1</code> 时,init 将采取哪些步骤?最终结果是什么?如果你使用 <code>telinit 6</code> 而不是 <code>reboot</code> 命令,你的服务器会重启吗?***</b></summary><br>
待完成。
有用资源:
- [如果我使用 “telinit 6” 而不是 “reboot” 命令重启计算机,会有什么不同?](https://unix.stackexchange.com/questions/434560/what-differences-it-will-make-if-i-use-telinit-6-instead-of-reboot-command)
</details>
<details>
<summary><b>我忘记了 root 密码!在 BSD 中该怎么办?进入单用户模式的目的是什么?</b></summary><br>
重启系统,在 `Boot:` 提示符处输入 `boot -s` 进入**单用户模式**。
在询问使用的 shell 时,按 `Enter` 键,会显示 `#` 提示符。
输入 `mount -urw /` 以读写方式重新挂载根文件系统,然后运行 `mount -a` 重新挂载所有文件系统。
运行 `passwd root` 更改 root 密码,然后运行 `exit` 继续启动。
**单用户模式**基本上允许你以 root 身份登录并更改几乎任何内容。例如,当你恢复损坏的主数据库或系统数据库,或者更改服务器配置选项(如密码恢复)时,可能会用到单用户模式。
有用资源:
- [FreeBSD 重置或恢复 root 密码](https://www.cyberciti.biz/tips/howto-freebsd-reset-recover-root-password.html)
- [单用户模式定义](http://www.linfo.org/single_user_mode.html)
</details>
<details>
<summary><b>如何在不调用文本编辑器的情况下修改文本文件?</b></summary><br>
例如:<br>```bash
# cat >filename ... - overwrite file
# cat >>filename ... - append to file
cat > filename << __EOF__
data
__EOF__
以及使用 `resize2fs` 或 `xfs_growfs` 来调整文件系统大小:
- 对于 ext 文件系统:```bash
resize2fs /dev/vgroup/lvolume
有用的资源:
- [扩展逻辑卷](https://www.tldp.org/HOWTO/LVM-HOWTO/extendlv.html)
</details>
<details>
<summary><b>什么是僵尸/已失效进程?</b></summary><br>
是一个已完成执行(通过 `exit` 系统调用)但在进程表中仍有条目的进程:它是一个处于“**终止状态**”的进程。
标记为 **defunct** 的进程是已死亡的进程(所谓的“僵尸”),因为它们未被其父进程正确销毁。如果父进程退出,这些进程将被 init 销毁。
有用的资源:
- [什么是 <defunct> 进程,为什么它不会被杀死?](https://askubuntu.com/questions/201303/what-is-a-defunct-process-and-why-doesnt-it-get-killed)
</details>
<details>
<summary><b>在生产环境中升级/更新系统的正确方法是什么?你是否自动化这些过程?是否设置停机时间?请写出建议。***</b></summary><br>
待完善。
</details>
<details>
<summary><b>你的一位朋友在配置 MySQL 服务器时问你:<i>安装 MySQL 后,我应该运行 <code>sudo mysql_secure_installation</code> 吗?</i> 你怎么看?</b></summary><br>
最好运行该命令,因为它提供了许多安全选项,例如:
- 可以为 root 账户设置密码
- 可以移除可从本地主机外部访问的 root 账户
- 可以移除匿名用户账户
- 可以移除 test 数据库(默认情况下匿名用户可访问该数据库)
有用的资源:
- [使用 mysql_secure_installation 的目的是什么?](https://stackoverflow.com/questions/20760908/what-is-purpose-of-using-mysql-secure-installation)
</details>
<details>
<summary><b>提出并解释使用 <code>kill</code> 命令的正确方法。</b></summary><br>
谈到杀死进程,除非绝对必要,否则不要使用 `kill -9/SIGKILL`。这种 kill 方式因其暴力性可能引发问题。
始终尝试使用以下简单步骤:
- 首先,发送 **SIGTERM** (`kill -15`) 信号,该信号告诉进程关闭,通常被认为是正常关闭时应使用的信号(但请注意,此信号可能被忽略)。
- 接下来,尝试发送 **SIGHUP** (`kill -1`) 信号,该信号常用来通知进程关闭并重启,此信号也可能被进程捕获并忽略。
绝大多数情况下,这已经足够了,而且更加干净。
有用的资源:
- [什么时候不应使用 kill -9 杀死进程?](https://unix.stackexchange.com/questions/8916/when-should-i-not-kill-9-a-process)
- [SIGTERM vs. SIGKILL](https://major.io/2010/03/18/sigterm-vs-sigkill/)
</details>
<details>
<summary><b><code>strace</code> 命令是什么?应如何使用?举例说明如何连接到一个正在运行的进程。</b></summary><br>
`strace` 是一个强大的命令行工具,用于在 Unix-like 操作系统(如 Linux)中调试和排查程序问题。它捕获并记录进程发出的所有系统调用以及进程收到的信号。
**Strace 概述**
`strace` 可视为一个轻量级调试器。它允许程序员/用户快速了解程序如何与操作系统交互。这是通过监控系统调用和信号实现的。
**用途**
适用于没有源代码或不想仔细查看源代码的情况。同样,如果你不想打开 **GDB**,但只对了解外部交互感兴趣,它对你的代码也很有用。
**附加到进程的示例**
`strace -p <PID>` - 将进程附加到 strace。
`strace -e trace=read,write -p <PID>` - 通过此方式,你还可以追踪进程/程序的特定事件,例如读取和写入(在此例中)。因此,它将打印所有包含进程读取和写入系统调用的事件。
其他类似示例:
- `-e trace=network` - 追踪所有网络相关的系统调用。
- `-e trace=signal` - 追踪所有信号相关的系统调用。
- `-e trace=ipc` - 追踪所有 IPC 相关的系统调用。
- `-e trace=desc` - 追踪所有文件描述符相关的系统调用。
- `-e trace=memory` - 追踪所有内存映射相关的系统调用。
有用的资源:
- [应如何使用 strace?(原文)](https://stackoverflow.com/questions/174942/how-should-strace-be-used)
- [strace 如何连接到已在运行的进程?(原文)](https://stackoverflow.com/questions/7482076/how-does-strace-connect-to-an-already-running-process)
- [strace:乐趣、盈利与调试](http://timetobleed.com/hello-world/)
</details>
<details>
<summary><b>何时应使用访问控制列表而非 <code>chmod</code> 命令,或与其结合使用?***</b></summary><br>
待完善。
</details>
<details>
<summary><b><code>/etc/shadow</code> 文件支持哪些算法?</b></summary><br>
当前常见的算法有:
- MD5
- SHA-1(也称为 SHA)
两者均不应再用于加密/安全目的!!
- SHA-256
- SHA-512
- SHA-3(KECCAK 于 2012 年 10 月被宣布为新的联邦核准哈希算法竞赛获胜者)
有用的资源:
- [Linux 密码加密使用的是什么算法?](https://crypto.stackexchange.com/questions/40841/what-is-the-algorithm-used-to-encrypt-linux-passwords)
- [如何找到用于混淆密码的哈希算法?](https://unix.stackexchange.com/questions/430141/how-to-find-the-hashing-algorithm-used-to-obfuscate-passwords)
</details>
<details>
<summary><b>Unix-like 系统中 ulimit 的用途是什么?</b></summary><br>
大多数 Unix-like 操作系统(包括 Linux 和 BSD)都提供了限制和控制每个进程及每个用户系统资源使用量的方法,例如线程、文件和网络连接。这些“**ulimits**”可防止单个用户占用过多系统资源。
</details>
<details>
<summary><b>什么是软限制和硬限制?</b></summary><br>
**硬限制** 是允许用户使用的最大值,由超级用户或 root 设置。该值在文件 `/etc/security/limits.conf` 中设置。用户可以在需要更多资源时自行提高 **软限制**,但不能将 **软限制** 设置为高于 **硬限制**。
</details>
<details>
<summary><b>在配置 HAProxy 与 Redis 配合使用时,你从日志中收到 <code>General socket error (Permission denied)</code>。SELinux 已启用。请解释 CLI 中基本的 SELinux 故障排查。***</b></summary><br>
有用的资源:
- [CLI 中基本的 SELinux 故障排查](https://access.redhat.com/articles/2191331)
</details>
<details>
<summary><b>你已配置了 RSA 密钥登录,但你的服务器显示 <code>Server refused our key</code>(如预期)。你会去哪里查找问题原因?</b></summary><br>
**服务器端**
在文件 `/etc/ssh/sshd_config` 中设置 `LogLevel VERBOSE` 可能正是你需要的,尽管还有更高的级别:
SSH 身份验证失败会记录在 `/var/log/auth.log`、`/var/log/secure` 或 `/var/log/audit/audit.log` 中。
以下命令应该只显示与 SSH 相关的日志行(例如):```bash
grep 'sshd' /var/log/auth.log
接下来,列出所有失败SSH登录的最简单命令如下所示:```bash grep "Failed password" /var/log/auth.log
也很有用:```bash
grep "Failed\|Failure" /var/log/auth.log
在较新的 Linux 发行版中,你可以通过 journalctl 命令查询由 Systemd 守护进程维护的运行时日志文件(ssh.service 或 sshd.service)。例如:```bash
journalctl _SYSTEMD_UNIT=ssh.service | egrep "Failed|Failure"
**Client side**
你还应该使用 `-v|--verbose` 参数运行SSH客户端——这属于第一级别的详细输出。接下来,你可以启用额外(第2和第3级别)的详细输出,以获得更多调试信息,例如使用 `-vv`。
有用的资源:
- [Enable Debugging Mode in SSH to Troubleshoot Connectivity Issues](https://www.tecmint.com/enable-debugging-mode-in-ssh/)
</details>
<details>
<summary><b>为什么大多数发行版使用ext4,而不是XFS或其他文件系统?为什么会有这么多文件系统?***</b></summary><br>
待完成。
</details>
<details>
<summary><b>项目经理需要一个新的SQL Server。你会问她/他什么问题?***</b></summary><br>
我希望数据库管理员(DBA)能问如下问题:
- 数据库会有多大?(是否能将数据库添加到现有服务器上)
- 数据库的关键性如何?(关于集群、灾难恢复、高可用性)
</details>
<details>
<summary><b>创建一个包含100行随机值的文件。</b></summary><br>
例如:```bash
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 100 > /path/to/file
apachewww-data许多应用程序默认使用用户nobody。例如,你可能永远不希望Apache服务覆盖属于bind的文件。为每个服务分配单独的账号通常是个好主意。
让Apache以nobody:nobody身份运行很容易,只需更新用户和组设置即可。但正如我上面提到的,我不太推荐使用这个特定的用户/组。完全有可能你将来会在系统上添加另一个也以nobody身份运行的服务,而你会忘记已经将文件系统的写权限授予了用户nobody。
如果nobody账号被入侵,它可能比一个应用隔离用户(如www-data)造成更大的影响。当然,这很大程度上取决于文件和组权限。nobody使用其他(others)的权限,而特定于应用的用户可以配置为允许文件读取,但其他用户仍被拒绝。
有用的资源:
或:```bash grep -insr "pattern" *
- `-i` 忽略大小写差异,同时适用于**PATTERN**和输入文件
- `-n` 为输出每一行加上它在输入文件中的1-based行号前缀
- `-s` 禁止关于不存在或不可读文件的错误消息
- `-r` 递归读取每个目录下的所有文件
有用资源:
- [如何在LINUX中递归搜索目录及其子目录文件中的字符串?](https://stackoverflow.com/questions/15622328/how-to-grep-a-string-in-a-directory-and-all-its-subdirectories-files-in-linux)
</details>
<details>
<summary><b>如何找出可执行文件运行时加载的动态库?</b></summary><br>
你可以使用`ldd`命令做到:```bash
ldd /bin/ls