分类 技术 下的文章

这篇面向初学者的文章探讨了在 Linux 中如何在普通视图中隐藏文件和文件夹。图形用户界面和命令行方法都有所涉猎。

有时你需要在 Linux 中隐藏文件。

不要误会,我不是指那些你不想让你的家人看到的“特殊文件”。尽管你可以隐藏这些特殊文件,但更好的办法还是用密码锁定它们以提供额外的保护。

回到隐藏文件的话题。名称以 . 开头的任何文件或文件夹在 Linux 中是“隐藏的”。

Linux 有很多这样的文件和文件夹,在普通视图中它们是隐藏的。这些主要是系统和程序所需的配置文件。

用户通常不需要理会它们,因此它们在普通视图中是隐藏的,这样一来你就不会被许多看起来很奇怪的而不是你所创建的文件所淹没。

下图展示了我的主目录中隐藏的文件和文件夹。

linux 普通视图

linux 显示隐藏文件

如果你使用的是桌面版 Linux,你可以通过在文件管理器中按 Ctrl+H 快捷键来轻松 查看隐藏文件。在终端中,你可以使用 ls -a 命令显示隐藏文件和普通文件。

那么,如何在 Linux 中创建隐藏文件呢?你只需用一个在命名的时候加一个 . 前缀。就是这样。

在桌面版 Linux 里创建隐藏文件和文件夹(GUI 方法)

如果你使用的是文件管理器,在文件或文件夹上右键并选择重命名选项。现在你所要做的就是在文件名的开头添加一个 .

当你以这种方式创建隐藏文件时,GNOME 的 Nautilus 文件管理器也会显示一个警告。

ubuntu linux 隐藏文件

你可以以相同的方式隐藏文件夹及其所有内容。

你可以按 Ctrl+H 键来显示隐藏文件。哦!我是多么的喜欢 Ubuntu 中的键盘快捷键 和我使用的任何其他程序或操作系统!

要使隐藏文件变回普通文件,只需再次重命名这些文件删掉文件名前缀的 . 即可。

在 Linux 终端创建隐藏文件和文件夹(CLI 方法)

如果你热衷于终端,你可以 使用 mv 命令 重命名文件。你只需在原始文件名的开头添加一个 .

mv filename .filename

你可以使用以下命令显示隐藏文件:

ls -la

你也可以使用 ls -lA。这条命令不会显示点文件(...)。

额外提示:用非重命名的方法隐藏文件和文件夹(仅适用于 GUI)

你刚刚学了在 Linux 中隐藏文件。问题是你必须重命名文件,而这种操作不适用于所有的场合。

例如,在 Ubuntu 中,你会在目录中看到一个名为 snap 的文件夹。你不会使用它,但如果重命名它,你的 Snap 应用程序将无法按预期工作。类似的情况是,在 Ubuntu 22.04(安装有 Snap 版本的 Firefox)的 Downloads 目录下有一个 firefox.tmp 文件夹。

有一个巧妙的技巧可以在 Linux 桌面中使用。它应该可以在 Nemo、Thunar、Dolphin 等各种文件管理器下工作,但我不能保证。它确实适用于 GNOME 的 Nautilus 文件管理器。

因此,你在这里所做的是在你想要隐藏的文件或文件所在的目录中创建一个名为 .hidden 的新文件。

在 Linux 中隐藏文件的另一种方法

Ctrl+H 显示隐藏文件并 打开 .hidden 文件 进行编辑。在单独的行中添加文件或文件夹的名称。注意不能使用绝对或相对路径。你想要隐藏的 文件和文件夹应与此特殊 .hidden 文件 位于同一路径下。

这是我以不重命名的方式隐藏 cpufetch 目录和 pcloud 文件的示例:

pcloud
cpufetch

Ctrl+H 以再次隐藏 .hidden 文件。

现在,关闭你的文件资源管理器并重新启动它。你将不会再看到 .hidden 文件中提到的文件和目录。

如果你想再次查看它们,请按 Ctrl+H 键。

如果你不想再隐藏文件,请从 .hidden 文件中删除其名称或完全删除 .hidden 文件。

额外琐事:隐藏文件“功能”实际上是一个 bug

你知道吗?在文件名的开头添加一个 . 来隐藏文件的“功能” 实际上是一个 bug

在早期的 UNIX 时代,当创建文件系统时,添加了 .(当前目录)和 ..(父目录)文件以方便导航。

由于这些特殊的 ... 文件中没有实际数据,因此给 ls 命令添加了一个新的“功能”:该功能是检查文件名的第一个字符,如果它是一个点(.),则不再使用 ls 命令显示它。

这对隐藏 ... 文件有效,但它引入了一个 “bug”:ls 命令的输出会隐藏任何文件名以 . 开头的文件。

这个 bug 变成了一个功能,因为程序员喜欢它来“隐藏”他们的配置文件。ls 命令可能是后来修改添加了一个显示隐藏点文件的选项。

Linux 遵循相同的约定,因为 Linux 是以 UNIX 为原型开发的。

结论

我讨论了如何从普通视图中创建隐藏文件。如果要创建让其他人无法访问的机密文件或文件夹,则应对其进行加密。我曾经写过 在 Linux 中使用密码锁定文件夹。这是一篇有点儿旧的文章,但它可能仍然有效。

我希望你喜欢这个简单的话题并学到新的东西。发布你的评论让我知道你的想法吧。


via: https://itsfoss.com/hide-files-folders-linux/

作者:Abhishek Prakash 选题:lkxed 译者:hanszhao80 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

你可能已经知道如何在 Linux 中获得你的系统的 IP 地址。

但是你怎么知道你的路由器的 IP 地址呢?

我说的不是你可以通过连接到 “Show My IP” 这样的网站或简单地在 DuckDuckGo搜索“what is my ip” 获得的公网 IP。

我说的是默认网关 IP,你的 Linux 桌面所连接的地址。

你为什么需要它?嗯,如果你需要改变你的 Wi-Fi/网络的 SSID、密码或其他配置,你必须连接到它。简单的方法是在网页浏览器中输入路由器的 IP 地址,然后使用路由器的用户名和密码。

虽然我不能帮助你获得路由器的用户名和密码,但我肯定可以告诉你如何获得它的 IP。

一如既往,我将展示 GUI 和命令行两种方法。

方法 1:在 Linux 中使用 GUI 获取路由器的 IP 地址

这其实很简单。我在这里使用的是 Ubuntu 的 GNOME 桌面。如果你使用一些 其他桌面环境,截图可能会有所不同。

打开“ 系统设置 System Settings ”:

go to settings

现在进入 Wi-Fi 或“ 网络 Network ”(如果你使用的是有线的以太网连接)。在这里,点击你当前使用的网络旁边的小设置符号。

access network settings ubuntu

它将打开一个新窗口,里面有关于你的连接的一些细节,如 IP 地址、DNS 和 Mac 地址。你还可以在“ 安全 security ”标签下看到 保存的 Wi-Fi 密码

你还会看到一个名为“ 默认路由 Default Route ”的条目。这就是你要找的东西。你的路由器的 IP 地址。

default gateway ip ubuntu

你的系统和网络上的所有其他设备都使用这个 IP 地址连接到路由器。这就是大多数家庭的设置。

现在我已经展示了 GUI 的方法,让我们去看看终端的路线。

方法 2:在 Linux 命令行中获取路由器的 IP 地址

打开一个终端,使用以下命令:

ip route

它将显示几个条目。

~$ ip route
default via 192.168.1.1 dev wlp0s20f3 proto dhcp metric 600 
169.254.0.0/16 dev wlp0s20f3 scope link metric 1000 
192.168.1.0/24 dev wlp0s20f3 proto kernel scope link src 192.168.1.34 metric 600

第一行,以 default via 开头,给出了你网关的 IP。这是你的路由器的 IP 地址。

default route linux terminal

你可以看到,192.168.1.1 是我的路由器的 IP 地址。通常情况下,路由器的 IP 地址是子网的第一个数字。然而,这并不是一个硬性规定。我也见过有 x.y.z.30 地址的路由器。

额外技巧

正如 Samir 在评论中所分享的,你也可以(在 Debian 上)使用 ping 命令来获得网关 IP:

ping _gateway

ping gateway

以防你不知道,你必须 在 Linux 中使用 Ctrl+C 来停止一个正在运行的命令

我希望你在需要的时候能发现这个技巧是有用的。


via: https://itsfoss.com/router-ip-address-linux/

作者:Abhishek Prakash 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

代码生成器是非常有用的工具。我有时使用 jinja2 的命令行版本来生成高度冗余的配置文件和其他文本文件,但它在转换数据方面功能有限。显然,Jinja2 的作者有不同的想法,而我想要类似于 列表推导 list comprehensions 或 D 语言的 可组合范围 composable range 算法之类的东西。

我决定制作一个类似于 Jinja2 的工具,但让我可以通过使用范围算法转换数据来生成复杂的文件。这个想法非常简单:一个直接用 D 语言代码重写的模板语言。因为它 就是 D 语言,它可以支持 D 语言所能做的一切。我想要一个独立的代码生成器,但是由于 D 语言的 mixin 特性,同样的模板语言可以作为嵌入式模板语言工作(例如,Web 应用程序中的 HTML)。有关该技巧的更多信息,请参阅 这篇 关于在编译时使用 mixins 将 Brainfuck 转换为 D 和机器代码的文章。

像往常一样,源码在 GitLab 上这篇文章中的例子也可以在这里找到

Hello world 示例

这是一个演示这个想法的例子:

Hello [= retro("dlrow") ]!
[: enum one = 1; :]
1 + 1 = [= one + one ]

[= some_expression ] 类似于 Jinja2 中的 {{ some_expression }},它在输出中呈现一个值。[: some_statement; :] 类似于 {% some_statement %} ,用于执行完整的代码语句。我更改了语法,因为 D 也大量使用花括号,并且将两者混合使模板难以阅读(还有一些特殊的非 D 指令,比如 include,它们被包裹在 [<>] 中)。

如果你将上面的内容保存到一个名为 hello.txt.dj 的文件中并运行 djinn 命令行工具,你会得到一个名为 hello.txt 的文件,其中包含你可能猜到的内容:

Hello world!
1 + 1 = 2

如果你使用过 Jinja2,你可能想知道第二行发生了什么。Djinn 有一个简化格式化和空格处理的特殊规则:如果源代码行包含 [: 语句或 [< 指令但不包含任何非空格输出,则整行都会被忽略输出。空行则仍会原样呈现。

生成数据

好的,现在来讲一些更实用的东西:生成 CSV 数据。

x,f(x)
[: import std.mathspecial;
foreach (x; iota(-1.0, 1.0, 0.1)) :]
[= "%0.1f,%g", x, normalDistribution(x) ]

一个 [=] 对可以包含多个用逗号分隔的表达式。如果第一个表达式是一个由双引号包裹的字符串,则会被解释为 格式化字符串。下面是输出结果:

x,f(x)
-1.0,0.158655
-0.9,0.18406
-0.8,0.211855
-0.7,0.241964
-0.6,0.274253
-0.5,0.308538
-0.4,0.344578
-0.3,0.382089
-0.2,0.42074
-0.1,0.460172
0.0,0.5
0.1,0.539828
0.2,0.57926
0.3,0.617911
0.4,0.655422
0.5,0.691462
0.6,0.725747
0.7,0.758036
0.8,0.788145
0.9,0.81594

制作图片

这个例子展示了一个图片的生成过程。经典的 Netpbm 图像库定义了一堆图像格式,其中一些是基于文本的。例如,这是一个 3 x 3 向量的图像:

P2 # PGM 格式标识
3 3 # 宽和高
7 # 代表纯白色的值(0 代表黑色)
7 0 7
0 0 0
7 0 7

你可以将上述文本保存到名为 cross.pgm 之类的文件中,很多图像工具都知道如何解析它。下面是一些 Djinn 代码,它以相同的格式生成 Mandelbrot 集 分形:

[:
import std.complex;
enum W = 640;
enum H = 480;
enum kMaxIter = 20;
ubyte mb(uint x, uint y)
{
    const c = complex(3.0 * (x - W / 1.5) / W, 2.0 * (y - H / 2.0) / H);
    auto z = complex(0.0);
    ubyte ret = kMaxIter;
    while (abs(z) <= 2 && --ret) z = z * z + c;
    return ret;
}
:]
P2
[= W ] [= H ]
[= kMaxIter ]
[: foreach (y; 0..H) :]
[= "%(%s %)", iota(W).map!(x => mb(x, y)) ]

生成的文件大约为 800 kB,但它可以很好地被压缩为 PNG:

$ # 使用 GraphicsMagick 进行转换
$ gm convert mandelbrot.pgm mandelbrot.png

结果如下:

解决谜题

这里有一个谜题:

一个 5 行 5 列的网格需要用 1 到 5 的数字填充,每个数字在每一行中限使用一次,在每列中限使用一次(即,制作一个 5 行 5 列的 拉丁方格 Latin square )。相邻单元格中的数字还必须满足所有 > 大于号表示的不等式。

几个月前我使用了 线性规划 linear programming (LP)。线性规划问题是具有线性约束的连续变量系统。这次我将使用 混合整数线性规划 mixed integer linear programming (MILP),它通过允许整数约束变量来归纳 LP。事实证明,这足以成为 NP 完备的,而 MILP 恰好可以很好地模拟这个谜题。

在上一篇文章中,我使用 Julia 库 JuMP 来帮助解决这个问题。这次我将使用 CPLEX:基于文本的格式,它受到多个 LP 和 MILP 求解器的支持(如果需要,可以通过现成的工具轻松转换为其他格式)。这是上一篇文章中 CPLEX 格式的 LP:

Minimize
  obj: v
Subject To
  ptotal: pr + pp + ps = 1
  rock: 4 ps - 5 pp - v <= 0
  paper: 5 pr - 8 ps - v <= 0
  scissors: 8 pp - 4 pr - v <= 0
Bounds
  0 <= pr <= 1
  0 <= pp <= 1
  0 <= ps <= 1
End

CPLEX 格式易于阅读,但复杂度高的问题需要大量变量和约束来建模,这使得手工编码既痛苦又容易出错。有一些特定领域的语言,例如 ZIMPL,用于以高级方式描述 MILP 和 LP。对于许多问题来说,它们非常酷,但最终它们不如具有良好库(如 JuMP)支持的通用语言或使用 D 语言的代码生成器那样富有表现力。

我将使用两组变量来模拟这个谜题:v_{r,c}i_{r,c,v}v_{r,c} 将保存 r 行 c 列单元格的值(从 1 到 5)。i_{r,c,v} 是一个二进制指示器,如果 r 行 c 列的单元格的值是 v,则该指示器值为 1,否则为 0。这两组变量是网格的冗余表示,但第一种表示更容易对不等式约束进行建模,而第二种表示更容易对唯一性约束进行建模。我只需要添加一些额外的约束来强制这两个表示是一致的。但首先,让我们从每个单元格必须只有一个值的基本约束开始。从数学上讲,这意味着给定行和列的所有指示器都必须为 0,但只有一个值为 1 的例外。这可以通过以下等式强制约束:

[i_{r,c,1} + i_{r,c,2} + i_{r,c,3} + i_{r,c,4} + i_{r,c,5} = 1]

可以使用以下 Djinn 代码生成对所有行和列的 CPLEX 约束:

\ 单元格只有一个值
[:
foreach (r; iota(N))
foreach (c; iota(N))
:]
    [= "%-(%s + %)", vs.map!(v => ivar(r, c, v)) ] = 1
[::]

ivar() 是一个辅助函数,它为我们提供变量名为 i 的字符串标识符,而 vs 存储从 1 到 5 的数字以方便使用。行和列内唯一性的约束完全相同,但在 i 的其他两个维度上迭代。

为了使变量组 i 与变量组 v 保持一致,我们需要如下约束(请记住,变量组 i 中只有一个元素的值是非零的):

[i_{r,c,1} + 2i_{r,c,2} + 3i_{r,c,3} + 4i_{r,c,4} + 5i_{r,c,5} = v_{r,c}]

CPLEX 要求所有变量都位于左侧,因此 Djinn 代码如下所示:

\ 连接变量组 i 和变量组 v
[:
foreach (r; iota(N))
foreach (c; iota(N))
:]
    [= "%-(%s + %)", vs.map!(v => text(v, ' ', ivar(r, c, v))) ] - [= vvar(r,c) ] = 0
[::]

不等符号相邻的和左下角值为为 4 单元格的约束写起来都很简单。剩下的便是将指示器变量声明为二进制,并为变量组 v 设置边界。加上变量的边界,总共有 150 个变量和 111 个约束 你可以在仓库中看到完整的代码

GNU 线性规划工具集 有一个命令行工具可以解决这个 CPLEX MILP。不幸的是,它的输出是一个包含了所有内容的体积很大的转储,所以我使用 awk 命令来提取需要的内容:

$ time glpsol --lp inequality.lp -o /dev/stdout | awk '/v[0-9][0-9]/ { print $2, $4 }' | sort
v00 1
v01 3
v02 2
v03 5
v04 4
v10 2
v11 5
v12 4
v13 1
v14 3
v20 3
v21 1
v22 5
v23 4
v24 2
v30 5
v31 4
v32 3
v33 2
v34 1
v40 4
v41 2
v42 1
v43 3
v44 5

real    0m0.114s
user    0m0.106s
sys     0m0.005s

这是在原始网格中写出的解决方案:

这些例子只是用来玩的,但我相信你已经明白了。顺便说一下,Djinn 代码仓库的 README.md 文件本身是使用 Djinn 模板生成的。

正如我所说,Djinn 也可以用作嵌入在 D 语言代码中的编译期模板语言。我最初只是想要一个代码生成器,得益于 D 语言的元编程功能,这算是一个额外获得的功能。


via: https://theartofmachinery.com/2021/01/01/djinn.html

作者:Simon Arneaud 选题:lujun9972 译者:hanszhao80 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

了解 Kubernetes 架构中不同组件是如何组合在一起的,这样你就可以更好地排查问题、维护一个健康的集群,以及优化工作流。

 title=

使用 Kubernetes 来编排容器,这种描述说起来简单,但理解它的实际含义以及如何实现它完全是另外一回事。如果你正在运行或管理 Kubernetes 集群,那么你就会知道 Kubernetes 由一台称为 “ 控制平面 control plane ” 的机器和许多其他 工作节点 worker node 机器组成。每种类型都有一个复杂但稳定的堆栈,这使编排成为可能,熟悉每个组件有助于理解它是如何工作的。

 title=

(Nived Velayudhan, CC BY-SA 4.0

控制平面组件

Kubernetes 安装在一个称为“ 控制平面 control plane ”的机器上,它会运行 Kubernetes 守护进程,并在启动容器和 容器组 pod 时与之通信。下面介绍控制平面的各个组件。

etcd

etcd 是一种快速、分布式一致性键值存储器,用作 Kubernetes 对象数据的持久存储,如容器组、副本控制器、密钥和服务。etcd 是 Kubernetes 存储集群状态和元数据的唯一地方。唯一与 etcd 直连的组件是 Kubernetes API 服务器。其他所有组件都通过 API 服务器间接的从 etcd 读写数据。

etcd 还实现了一个监控功能,它提供了一个基于事件的接口,用于异步监控键的更改。一旦你更改了一个键,它的监控者就会收到通知。API 服务器组件严重依赖于此来获得通知,并将 etcd 变更至期望状态。

为什么 etcd 实例的数量应该是奇数?

你通常会运行三个、五个或七个 etcd 实例实现高可用(HA)环境,但这是为什么呢?因为 etcd 是分布式数据存储,可以水平扩展它,但你需要确保每个实例中的数据是一致的。因此,需要为系统当前状态达成共识,etcd 为此使用 RAFT 共识算法

RAFT 算法需要经过选举(或仲裁)集群才能进入下一个状态。如果你只有两个 etcd 实例并且他们其中一个失败的话,那么 etcd 集群无法转换到新的状态,因为不存在过半这个概念。如果你有三个 etcd 实例,一个实例可能会失败,但仍有 2 个实例可用于进行选举。

API 服务器

API 服务器是 Kubernetes 中唯一直接与 etcd 交互的组件。Kubernetes 中的其他所有组件都必须通过 API 服务器来处理集群状态,包括客户端(kubectl)。API 服务器具有以下功能:

  • 提供在 etcd 中存储对象的一致方式。
  • 执行验证对象,防止客户端存储配置不正确的对象(如果它们直接写入 etcd 数据存储,可能会发生这种情况)。
  • 提供 RESTful API 来创建、更新、修改或删除资源。
  • 提供 乐观并发锁,在发生更新时,其他客户端永远不会有机会重写对象。
  • 对客户端发送的请求进行身份验证和授权。它使用插件提取客户端的用户名、ID、所属组,并确定通过身份验证的用户是否可以对请求的资源执行请求的操作。
  • 如果请求试图创建、修改或删除资源,则负责 权限控制。例如,AlwaysPullImages、DefaultStorageClass 和 ResourceQuota。
  • 实现了一种监控机制(类似于 etcd),用户客户端监控更改。这允许调度器和控制器管理器等组件以松耦合的方式与 API 服务器交互。

控制器管理器

在 Kubernetes 中,控制器持续监控集群状态,然后根据需要进行或请求更改。每个控制器都尝试将当前集群状态变更至期望状态。控制器至少跟踪一种 Kubernetes 资源类型,这些对象均有一个字段来表示期望的状态。

控制器示例:

  • 副本管理器(管理 副本控制器 ReplicationController 资源的控制器)
  • 副本集 ReplicaSet 、守护进程集DaemonSet 和任务控制器
  • 部署控制器
  • 有状态负载控制器
  • 节点控制器
  • 服务控制器
  • 接入点控制器
  • 命名空间控制器
  • 持久卷 PersistentVolume 控制器

控制器通过监控机制来获得变更通知。它们监视 API 服务器对资源的变更,对每次更改执行操作,无论是新建对象还是更新或删除现有对象。大多数时候,这些操作包括创建其他资源或更新监控的资源本身。不过,由于使用监控并不能保证控制器不会错过任何事件,它们还会定期执行一系列操作,确保没有错过任何事件。

控制器管理器还执行生命周期功能。例如命名空间创建和生命周期、事件垃圾收集、已终止容器组垃圾收集、级联删除垃圾收集 和节点垃圾收集。有关更多信息,参考 云控制器管理器

调度器

调度器是一个将容器组分配给节点的控制平面进程。它会监视新创建没有分配节点的容器组。调度器会给每个发现的容器组分配运行它的最佳节点。

满足容器组调度要求的节点称为可调度节点。如果没有合适的节点,那么容器组会一直处于未调度状态,直到调度器可以安置它。一旦找到可调度节点,它就会运行一组函数来对节点进行评分,并选择得分最高的节点,然后它会告诉 API 服务器所选节点的信息。这个过程称为绑定。

节点的选择分为两步:

  1. 过滤所有节点的列表,获得可以调度容器组的节点列表(例如,PodFitsResources 过滤器检查候选节点是否有足够的可用资源来满足容器组的特定资源请求)。
  2. 对第一步得到的节点列表进行评分和排序,选择最佳节点。如果得分最高的有多个节点,循环过程可确保容器组会均匀地部署在所有节点上。

调度决策要考虑的因素包括:

  • 容器组是否请求硬件/软件资源?节点是否报告内存或磁盘压力情况?
  • 节点是否有与容器组规范中的节点选择器匹配的标签?
  • 如果容器组请求绑定到特定地主机端口,该端口是否可用?
  • 容器组是否容忍节点的污点?
  • 容器组是否指定节点亲和性或反亲和性规则?

调度器不会指示所选节点运行容器组。调度器所做的就是通过 API 服务器更新容器组定义。然后 API 服务器通过监控机制通知 kubelet 容器组已被调度,然后目标节点上的 kubelet 服务看到容器组被调度到它的节点,它创建并运行容器组。

工作节点组件

工作节点运行 kubelet 代理,这允许控制平面接纳它们来处理负载。与控制平面类似,工作节点使用几个不同的组件来实现这一点。 以下部分描述了工作节点组件。

Kubelet

Kubelet 是一个运行在集群中每个节点上的代理,负责在工作节点上运行的所有事情。它确保容器在吊舱中运行。

kubelet服务的主要功能有:

  • 通过在 API 服务器中创建节点资源来注册它正在运行的节点。
  • 持续监控 API 服务器上调度到节点的容器组。
  • 使用配置的容器运行时启动容器组的容器。
  • 持续监控正在运行的容器,并将其状态、事件和资源消耗报告给 API 服务器。
  • 运行容器存活探测,在探测失败时重启容器,当 API 服务器中删除容器组时终止(通知服务器容器组终止的消息)。

服务代理

服务代理(kube-proxy)在每个节点上运行,确保一个容器组可以与另一个容器组通讯,一个节点可以与另一个节点对话,一个容器可以与另一个容器对话。它负责监视 API 服务器对服务和容器组定义的更改,以保持整个网络配置是最新的。当一项服务得到多个容器组的支持时,代理会在这些容器组之间执行负载平衡。

kube-proxy 之所以叫代理,是因为它最初实际上是一个代理服务器,用于接受连接并将它们代理到容器组。当前的实现是使用 iptables 规则将数据包重定向到随机选择的后端容器组,而无需通过实际的代理服务器。

关于它工作原理的高级视图:

  • 当你创建一个服务时,会立即分配一个虚拟 IP 地址。
  • API 服务器会通知在工作节点上运行的 kube-proxy 代理有一个新服务。
  • 每个 kube-proxy 通过设置 iptables 规则使服务可寻址,确保截获每个服务 IP/端口对,并将目的地址修改为支持服务的一个容器组。
  • 监控 API 服务器对服务或其端点对象的更改。

容器运行时

容器运行时有两类:

  • 较低级别的容器运行时: 它们主要关注运行中的容器并为容器设置命名空间和 控制组 cgroup
  • 更高级别的容器运行时(容器引擎): 它们专注于格式、解包、管理、共享镜像以及为开发人员提供 API。

容器运行时负责:

  • 如果容器镜像本地不存在,则从镜像仓库中提取。
  • 将镜像解压到写时复制文件系统,所有容器层叠加创建一个合并的文件系统。
  • 准备一个容器挂载点。
  • 设置容器镜像的元数据,如覆盖命令、用户输入的入口命令,并设置 SECCOMP 规则,确保容器按预期运行。
  • 通知内核将进程、网络和文件系统等隔离分配给容器。
  • 通知内核分配一些资源限制,如 CPU 或内存限制。
  • 将系统调用(syscall)传递给内核启动容器。
  • 确保 SElinux/AppArmor 设置正确。

协同

系统级组件协同工作,确保 Kubernetes 集群的每个部分都能实现其目和执行其功能。当你深入编辑 YAML 文件 时,有时很难理解请求是如何在集群中通信的。现在你已经了解了各个部分是如何组合在一起的,你可以更好地理解 Kubernetes 内部发生了什么,这有助于诊断问题、维护健康的集群并优化你的工作流。


via: https://opensource.com/article/22/2/kubernetes-architecture

作者:Nived Velayudhan 选题:lujun9972 译者:MjSeven 校对:turbokernel

本文由 LCTT 原创编译,Linux中国 荣誉推出

VLCLinux 和其他平台上最受欢迎的视频播放器之一。

它不仅仅是一个视频播放器。它提供了许多多媒体和网络相关的功能。你会惊讶地 了解 VLC 的能力

我将演示一个简单的 VLC 功能,即使用它下载 YouTube 视频。

是的。你可以在 VLC 中播放 YouTube 视频并下载它们。让我告诉你怎么做。(LCTT 校注:发布此文只探讨技术可行性。)

使用 VLC 媒体播放器下载 YouTube 视频

现在,有一些方法可以 下载 YouTube 视频。使用浏览器扩展或使用专门的网站或工具。

但是如果你不想使用任何额外的东西,已经安装的 VLC 播放器可以用于此目的。

**重要提示:**在从 YouTube 复制链接之前,请确保从 YouTube 播放器中选择所需的视频质量,因为我们将获得与复制链接时流式传输视频相同的质量。

步骤 1:获取所需视频的视频链接

你可以使用任何你喜欢的浏览器并从地址栏中复制视频链接。

copy youtube link

步骤 2:将复制的链接粘贴到网络流

网络流 Network Stream ”选项位于“ 媒体 Media ”菜单下,这是我们顶部菜单栏的第一个选项。你也可以使用快捷方式 CTRL + N 打开网络流 。

click on media and select network stream

现在,你只需粘贴复制的 YouTube 视频链接,然后单击播放按钮。我知道它只是在我们的 VLC 中播放视频,但还有一点额外的步骤可以让我们下载当前的流媒体视频。

paste video link

步骤 3:从编解码器信息中获取位置链接

在“ 编解码器信息 Codec Information ”下,我们会得到当前播放视频的位置链接。要打开编解码器信息,你可以使用快捷键 CTRL + J 或者你会在“ 工具 Tools ”菜单下找到编解码器信息选项。

click on tools and then codec information

它将带来有关当前流媒体视频的详细信息。但我们需要的是“ 位置 Location ”。你只需复制位置链接,我们的任务就完成了 90%。

copy location link

步骤 4:将位置链接粘贴到新选项卡

打开任何你喜欢的浏览器,并将复制的位置链接粘贴到新选项卡,它将开始在浏览器中播放该视频。

现在,右键单击播放视频,你将看到“将视频另存为”的选项。

click on save

它将打开文件管理器并询问你是否要在本地保存此视频。你还可以重命名该文件,默认情况下它将被命名为 “videoplayback.mp4”。

showing file in folder

结论

如果你有互联网连接问题,或者如果你想保存一些视频以供将来观看,下载 YouTube 视频是有意义的。

当然,我们不鼓励盗版。此方法仅用于合理使用,请确保视频的创建者已允许该视频进行合理使用,并确保在将其用于其他地方之前将其归属于视频的原始所有者。


via: https://itsfoss.com/download-youtube-videos-vlc/

作者:Community 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

(LCTT 校注:作者原文已经大篇幅进行了修订更新,本文据之前的版本翻译。)

今天我在推特上发布了一些关于 OSI 模型如何与 TCP/IP 工作原理的实际表现不相符的观点,这让我思考——OSI 模型到底是什么?通过阅读推特上的一些回复发现,似乎至少存在三种不同的思考方式:

  1. TCP/IP 工作原理的字面描述
  2. 一个可以用来描述和比较很多不同的网络协议的抽象模型
  3. 对 1980 年代的一些计算机网络协议的字面描述,这些协议如今大多已不再使用

在这篇文章中,我不打算试图争辩以上哪一个才是“真正”的 OSI 模型——似乎不同的人以所有这些方式思考它。这不重要。

OSI 模型有七层

在我们讨论 OSI 模型的含义之前,让我们大致地讨论一下它是什么。它是一个抽象模型,用于描述网络如何在七个编号的层上工作:

  • 第一层:物理层
  • 第二层:数据链路层
  • 第三层:网络层
  • 第四层:传输层
  • 第五层:会话层
  • 第六层:表示层
  • 第七层:应用层

我不会再费时地去解释每一层的含义,网上有上千种解释可供查询。

OSI 模型:TCP/IP 工作原理的字面描述

首先,我想谈谈人们在实践中使用 OSI 模型的一种常见方式:作为对 TCP/IP 工作原理的字面描述。OSI 模型的某些层非常容易映射到 TCP/IP:

  • 第二层对应以太网
  • 第三层对应 IP
  • 第四层对应 TCP 或 UDP(或 ICMP 等)
  • 第七层对应 TCP 或 UDP 包内的任何内容(例如 DNS 查询)

这种映射对第二、三、四层很有意义——TCP 数据包有三个 标头 header 对应于这三个层(以太网标头、IP 标头和 TCP 标头)。

用数字来描述 TCP 数据包中的不同标头非常有用——如果你说“第二层”,很显然它位于第三层“下方”,因为二比三小。

“OSI 模型作为字面描述”的古怪之处在于,第五层和第六层并不真正对应于 TCP/IP 中的任何内容——我听说过很多关于第五层或第六层可能是什么的不同解释(你可以说第五层是 TLS 或其他东西!)但它们没有像第二、三、四层那样“每一层在 TCP 数据包中都有相应的标头”这样的明确对应关系。

此外,TCP/IP 的某些部分即使在第二层到第四层也不能很好地适应 OSI 模型——例如,哪一层是 ARP 数据包?ARP 数据包发送一些带有以太网标头的数据,这是否意味着它们是第三层?或是第二层?列出不同 OSI 层的维基百科文章将其归类为“第 2.5 层”,这并不令人满意。

因为 OSI 模型有时用于教授 TCP/IP,若搞不清楚它的哪些部分可以映射到 TCP/IP,而哪些部分不能,则会令人困惑。这才是真的问题。

OSI 模型:用于比较网络协议的一个抽象

我听说过的另一种关于 OSI 的思考方式是,它是一种抽象,可以用来在许多不同的网络协议之间进行类比。例如,如果你想了解蓝牙协议的工作原理,也许你可以使用 OSI 模型来帮助你——这是我在 这个网页 上找到的一张图表,显示了蓝牙协议如何适配 OSI 模型。

另一个例子是,这篇维基百科文章) 有一个 OSI 层列表,详细划分了哪些特定的网络协议对应于这些 OSI 层。

OSI 模型:一些过时协议的字面描述

维基百科上的一些非常简短的研究表明,除了对这七层的抽象描述之外,OSI 模型还包含了 一组实现这些层的特定协议。显然,这发生在 70 年代和 80 年代的 协议战争 时期,OSI 模型失败了,TCP/IP 则取得了胜利。

这就解释了为什么 OSI 模型无法与 TCP/IP 很好地对应,因为如果当时“获胜”的是 OSI 协议,那么 OSI 模型 完全对应于互联网网络的实际工作方式。

结语

我写这篇文章的初衷是,当我最初学习 OSI 模型时,我发现它非常令人困惑(所有这些层是什么?它们是真实存在的吗?这是网络的实际工作原理吗?发生了什么?)我希望有人告诉我这个只使用 TCP/IP 网络协议的人,只需了解 OSI 模型第二、三、四和七层与 TCP/IP 的关系,然后忽略它的所有其他内容即可。所以我希望这篇文章对某些人能有所帮助!


via: https://jvns.ca/blog/2021/05/11/what-s-the-osi-model-/

作者:Julia Evans 选题:lujun9972 译者:hanszhao80 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出