mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-02-03 23:40:14 +08:00
commit
814af6ddbd
@ -0,0 +1,92 @@
|
||||
[#]: subject: (5 useful ways to manage Kubernetes with kubectl)
|
||||
[#]: via: (https://opensource.com/article/21/7/kubectl)
|
||||
[#]: author: (Alan Smithee https://opensource.com/users/alansmithee)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (turbokernel)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13676-1.html)
|
||||
|
||||
用 kubectl 管理 Kubernetes 的 5 种有用方法
|
||||
======
|
||||
|
||||
> 学习 kubectl,提升你与 Kubernetes 的互动方式。
|
||||
|
||||
![Ship captain sailing the Kubernetes seas][1]
|
||||
|
||||
Kubernetes 可以帮你编排运行有大量容器的软件。Kubernetes 不仅提供工具来管理(或者说 [编排][2])运行的容器,还帮助这些容器根据需要进行扩展。有了 Kubernetes 作为你的中央<ruby>控制面板<rt>control panel</rt></ruby>(或称 <ruby>控制平面<rt>control plane</rt></ruby>),你需要一种方式来管理 Kubernetes,而这项工作的工具就是 kubectl。`kubectl` 命令让你控制、维护、分析和排查 Kubernetes 集群的故障。与许多使用 `ctl`(“控制”的缩写)后缀的工具一样,如 `systemctl` 和 `sysctl`,`kubectl` 拥有大量的功能和任务权限,所以如果你正在运行 Kubernetes,你肯定会经常使用它。它是一个拥有众多选项的命令,所以下面是 `kubectl` 中简单易用的五个常见任务。
|
||||
|
||||
### 1、列出并描述资源
|
||||
|
||||
按照设计,容器往往会成倍增加。在某些条件下,它们可以快速增加。如果你只能通过 `podman ps`或 `docker ps` 来查看正在运行的容器,这可能会让你不知所措。通过 `kubectl get` 和 `kubectl describe`,你可以列出正在运行的<ruby>吊舱<rt>pod</rt></ruby>以及它们正在处理的容器信息。更重要的是,你可以通过使用 `--namespace` 或 `name` 或 `--selector`等选项,只列出所需信息。
|
||||
|
||||
`get` 子命令不仅仅对吊舱和容器有用。它也有关于节点、命名空间、发布、服务和副本的信息。
|
||||
|
||||
### 2、创建资源
|
||||
|
||||
如果你只通过类似 OpenShift、OKD 或 Kubernetes 提供的 Web 用户界面(UI)创建过发布,但你想从 Linux 终端控制你的集群,那么可以使用 `kubectl create`。`kubectl create` 命令并不只是实例化一个新的应用发布。Kubernetes 中还有很多其他组件可以创建,比如服务、配额和 [计划任务][3]。
|
||||
|
||||
Kubernetes 中的计划任务可以创建一个临时的吊舱,用来在你选择的时间表上执行一些任务。它们并不难设置。下面是一个计划任务,让一个 BusyBox 镜像每分钟打印 “hello world”。
|
||||
|
||||
```
|
||||
$ kubectl create cronjob \
|
||||
hello-world \
|
||||
--image=busybox \
|
||||
--schedule="*/1 * * * *" -- echo "hello world"
|
||||
```
|
||||
|
||||
### 3、编辑文件
|
||||
|
||||
Kubernetes 中的对象都有相应的配置文件,但在文件系统中查找相应的文件较为麻烦。有了 `kubectl edit`,你可以把注意力放在对象上,而不是定义文件上。你可以通过 `kubectl` 找到并打开文件(通过 `KUBE_EDITOR` 环境变量,你可以设置成你喜欢的编辑器)。
|
||||
|
||||
```
|
||||
$ KUBE_EDITOR=emacs \
|
||||
kubectl edit cronjob/hello-world
|
||||
```
|
||||
|
||||
### 4、容器之间的传输文件
|
||||
|
||||
初次接触容器的人往往对无法直接访问的共享系统的概念感到困惑。他们可能会在容器引擎或 `kubectl` 中了解到 `exec` 选项,但当他们不能从容器中提取文件或将文件放入容器中时,容器仍然会显得不透明。使用 `kubectl cp` 命令,你可以把容器当做远程服务器,使主机和容器之间文件传输如 SSH 命令一样简单:
|
||||
|
||||
```
|
||||
$ kubectl cp foo my-pod:/tmp
|
||||
```
|
||||
|
||||
### 5、应用变更
|
||||
|
||||
对 Kubernetes 对象进行修改,可以通过 `kubectl apply` 命令完成。你所要做的就是将该命令指向一个配置文件:
|
||||
|
||||
```
|
||||
$ kubectl apply -f ./mypod.json
|
||||
```
|
||||
|
||||
类似于运行 Ansible 剧本或 Bash 脚本,`apply` 使得快速“导入”设置到运行中的 Kubernetes 实例很容易。例如,GitOps 工具 [ArgoCD][4] 由于 `apply` 子命令,安装起来出奇地简单:
|
||||
|
||||
```
|
||||
$ kubectl create namespace argocd
|
||||
$ kubectl apply -n argocd \
|
||||
-f https://raw.githubusercontent.com/argoproj/argo-cd/vx.y.z/manifests/install.yaml
|
||||
```
|
||||
|
||||
### 使用 kubectl
|
||||
|
||||
Kubectl 是一个强大的工具,由于它是一个终端命令,它可以写成脚本,并能实现用众多 Web UI 无法实现的功能。学习 `kubectl` 是进一步了解 Kubernetes、容器、吊舱以及围绕这些重要的云计算创新技术的一个好方法。[下载我们的 kubectl 速查表][5],以获得快速参考,其中包括命令示例,以帮助你学习,并在为你提供注意细节。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/7/kubectl
|
||||
|
||||
作者:[Alan Smithee][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[turbokernel](https://github.com/turbokernel)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/alansmithee
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/ship_captain_devops_kubernetes_steer.png?itok=LAHfIpek (Ship captain sailing the Kubernetes seas)
|
||||
[2]: https://opensource.com/article/20/11/orchestration-vs-automation
|
||||
[3]: https://opensource.com/article/20/11/kubernetes-jobs-cronjobs
|
||||
[4]: https://argoproj.github.io/argo-cd/
|
||||
[5]: https://opensource.com/downloads/kubectl-cheat-sheet
|
@ -3,14 +3,14 @@
|
||||
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13681-1.html)
|
||||
|
||||
用 OneDriver GUI 工具在 Linux 中安装微软 OneDrive
|
||||
用 OneDriver GUI 工具在 Linux 中挂载微软 OneDrive
|
||||
======
|
||||
|
||||
在 Windows 上,微软提供了一个[免费云存储服务][1] OneDrive。它与 Windows 集成,你可以通过你的微软账户获得 5GB 的免费存储空间。
|
||||
在 Windows 上,微软提供了一个 [免费云存储服务][1] OneDrive。它与 Windows 集成,你可以通过你的微软账户获得 5GB 的免费存储空间。
|
||||
|
||||
这在 Windows 上很好用,但和谷歌一样,微软也没有在 Linux 桌面上提供 OneDrive 的本地客户端。
|
||||
|
||||
@ -24,17 +24,17 @@
|
||||
|
||||
![OneDrive Linux illustration][4]
|
||||
|
||||
[OneDriver][5] 是一个免费的开源工具,允许你在 Linux 系统上挂载 OneDrive 文件。
|
||||
[OneDriver][5] 是一个自由而开源的工具,允许你在 Linux 系统上挂载 OneDrive 文件。
|
||||
|
||||
请记住,它不会像 OneDrive 在 Windows 系统上那样同步文件。它将 OneDrive 文件挂载在本地的挂载点上。你通过网络访问这些文件。
|
||||
|
||||
然而,它确实提供了一种混合方法。你在挂载的 OneDrive 中打开的文件也被下载到系统中。这意味着,你也可以离线访问打开的文件。如果你没有连接到互联网,这些文件将成为只读。
|
||||
|
||||
如果你在本地对文件做任何修改,如果你连接到互联网,它就会反映到 OneDrive 上。
|
||||
如果你在本地对文件做任何修改,并且连接到互联网,它就会反映到 OneDrive 上。
|
||||
|
||||
我注意到,在 GNOME 上的 Nautilus 文件管理器中,它会自动下载当前文件夹中的图像。在我的印象中,它们只有在我打开它们时才会被下载。
|
||||
|
||||
另一件事是,Nautilus 最初建立了缩略图缓存。OneDriver 在开始的时候可能会觉得有点慢,有点耗费资源,但最终会好起来。
|
||||
另一件事是,Nautilus 一开始会建立缩略图缓存。OneDriver 在开始的时候可能会觉得有点慢,有点耗费资源,但最终会好起来。
|
||||
|
||||
哦!你也可以挂载多个 OneDrive 账户。
|
||||
|
||||
@ -48,7 +48,7 @@ sudo apt update
|
||||
sudo apt install onedriver
|
||||
```
|
||||
|
||||
对于 Ubuntu 21.04,你可以下载[其 PPA 中的 DEB 文件][6]来使用它。
|
||||
对于 Ubuntu 21.04,你可以下载 [其 PPA 中的 DEB 文件][6] 来使用它。
|
||||
|
||||
在 Fedora 上,你可以添加这个 COPR:
|
||||
|
||||
@ -63,7 +63,7 @@ Arch 用户可以在 AUR 中找到它。
|
||||
|
||||
![Search for OneDriver][7]
|
||||
|
||||
首次运行时,它会给出一个奇怪的空界面。点击 “+” 号,选择一个文件夹或创建一个新的文件夹,在那里你将挂载 OneDrive。在我的例子中,我在我的家目录下创建了一个名为 One_drive 的新文件夹。
|
||||
首次运行时,它会给出一个奇怪的空界面。点击 “+” 号,选择一个文件夹或创建一个新的文件夹,OneDrive 会挂载在那里。在我的例子中,我在我的家目录下创建了一个名为 `One_drive` 的新文件夹。
|
||||
|
||||
![Click on + sign to add a mount point for OneDrive][8]
|
||||
|
||||
@ -73,7 +73,7 @@ Arch 用户可以在 AUR 中找到它。
|
||||
|
||||
![one drive permission][10]
|
||||
|
||||
登陆后,你可以在挂载的目录中看到 OneDrive 的文件。
|
||||
登录后,你可以在挂载的目录中看到 OneDrive 的文件。
|
||||
|
||||
![OneDrive mounted in Linux][11]
|
||||
|
||||
@ -81,9 +81,9 @@ Arch 用户可以在 AUR 中找到它。
|
||||
|
||||
![Autostart OneDriver mounting][12]
|
||||
|
||||
总的来说,OneDriver 是一个可以在 Linux 上访问 OneDrive 的不错的免费工具。它可能无法像[高级 Insync 服务][13]那样提供完整的同步设施,但对于有限的需求来说,它做得不错。
|
||||
总的来说,OneDriver 是一个可以在 Linux 上访问 OneDrive 的不错的免费工具。它可能无法像 [高级 Insync 服务][13] 那样提供完整的同步设施,但对于有限的需求来说,它做得不错。
|
||||
|
||||
如果你使用这个漂亮的工具,请分享你的使用经验。如果你喜欢这个项目,也许可以给它一个 [GitHub 上的关注][5]。
|
||||
如果你使用这个漂亮的工具,请分享你的使用经验。如果你喜欢这个项目,也许可以给它一个 [GitHub 上的星标][5]。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -92,7 +92,7 @@ via: https://itsfoss.com/onedriver/
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
130
published/20210803 Set up a VPN server on your Linux PC.md
Normal file
130
published/20210803 Set up a VPN server on your Linux PC.md
Normal file
@ -0,0 +1,130 @@
|
||||
[#]: subject: (Set up a VPN server on your Linux PC)
|
||||
[#]: via: (https://opensource.com/article/21/8/openvpn-server-linux)
|
||||
[#]: author: (D. Greg Scott https://opensource.com/users/greg-scott)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (perfiffer)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13680-1.html)
|
||||
|
||||
如何在免费 WiFi 中保护隐私(一)
|
||||
======
|
||||
|
||||
> 第一步是安装一个“虚拟专用网络”服务器。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202108/13/213142rclc5htyfahotfas.jpg)
|
||||
|
||||
你是否连接到了不受信任的网络,例如酒店或咖啡馆的 WiFi,而又需要通过智能手机和笔记本电脑安全浏览互联网?通过使用虚拟专用网络,你可以匿名访问不受信任的网络,就像你在专用网络上一样安全。
|
||||
|
||||
“虚拟专用网络” 是保护私人数据的绝佳工具。通过使用 “虚拟专用网络”,你可以在保持匿名的同时连接到互联网上的专用网络。
|
||||
|
||||
可选的 “虚拟专用网络” 服务有很多,[0penVPN][2] 依然是很多人在使用不受信任的网络时保护私人数据的第一选择。
|
||||
|
||||
0penVPN 在两点之间创建一个加密通道,防止第三方访问你的网络流量数据。通过设置你的 “虚拟专用网络” 服务,你可以成为你自己的 “虚拟专用网络” 服务商。许多流行的 “虚拟专用网络” 服务都使用 0penVPN,所以当你可以掌控自己的网络时,为什么还要将你的网络连接绑定到特定的提供商呢?
|
||||
|
||||
### 搭建 Linux 服务器
|
||||
|
||||
首先,在备用 PC 上安装一份 Linux。本例使用 Fedora,但是不论你使用的是什么 Linux 发行版,步骤基本是相同的。
|
||||
|
||||
从 [Fedora 项目][3] 网站下载最新的 Fedora ISO 副本。制作一个 USB 启动盘,将其插入到你的 PC 并启动,然后安装操作系统。如果你从未制作过可引导的 USB 启动盘,可以了解一下 [Fedora Media Writer][4]。如果你从未安装过 Linux,请阅读 [三步安装 Linux][5]。
|
||||
|
||||
### 设置网络
|
||||
|
||||
安装完成 Fedora 操作系统后,登录到控制台或者 SSH 会话。
|
||||
|
||||
更新到最新并重新启动:
|
||||
|
||||
```
|
||||
$ sudo dnf update -y && reboot
|
||||
```
|
||||
|
||||
重新登录并关闭防火墙:
|
||||
|
||||
```
|
||||
systemctl disable firewalld.service
|
||||
systemctl stop firewalld.service
|
||||
```
|
||||
|
||||
你可能希望在此系统上为你的内部网络添加适当的防火墙规则。如果是这样,请在关闭所有防火墙规则后完成 0penVPN 的设置和调试,然后添加本地防火墙规则。想要了解更多,请参照 [在 Linux 上设置防火墙][6]。
|
||||
|
||||
### 设置 IP 地址
|
||||
|
||||
你需要在你的本地网络设置一个静态 IP 地址。下面的命令假设在一个名为 `ens3` 的设备上有一个名为 `ens3` 的<ruby>网络管理器<rt>Network Manager</rt></ruby>连接。你的设备和连接名称可能不同,你可以通过打开 SSH 会话或从控制台输入以下命令:
|
||||
|
||||
```
|
||||
$ sudo nmcli connection show
|
||||
NAME UUID TYPE DEVICE
|
||||
ens3 39ad55bd-adde-384a-bb09-7f8e83380875 ethernet ens3
|
||||
```
|
||||
|
||||
你需要确保远程用户能够找到你的 “虚拟专用网络” 服务器。有两种方法可以做到这一点。你可以手动设置它的 IP 地址,或者将大部分工作交给你的路由器去完成。
|
||||
|
||||
#### 手动配置一个 IP 地址
|
||||
|
||||
通过以下命令来设置静态 IP 地址、前缀、网关和 DNS 解析器,用来替换掉原有的 IP 地址:
|
||||
|
||||
```
|
||||
$ sudo nmcli connection modify ens3 ipv4.addresses 10.10.10.97/24
|
||||
$ sudo nmcli connection modify ens3 ipv4.gateway 10.10.10.1
|
||||
$ sudo nmcli connection modify ens3 ipv4.dns 10.10.10.10
|
||||
$ sudo nmcli connection modify ens3 ipv4.method manual
|
||||
$ sudo nmcli connection modify ens3 connection.autoconnect yes
|
||||
```
|
||||
|
||||
设置主机名:
|
||||
|
||||
```
|
||||
$ sudo hostnamectl set-hostname OVPNserver2020
|
||||
```
|
||||
|
||||
如果你运行了一个本地的 DNS 服务,你需要设置一个 DNS 条目,将主机名指向 “虚拟专用网络” 服务器的 IP 地址。
|
||||
|
||||
重启并确保系统的网络运行正常。
|
||||
|
||||
#### 在路由器中配置 IP 地址
|
||||
|
||||
在你的网络当中应该有一台路由器。你可能已经购买了它,或者从互联网服务提供商(ISP)那里获得了一台。无论哪种方式,你的路由器可能都有一个内置的 DHCP 服务,可以为连接到网络上的每台设备分配一个 IP 地址。你的新 “虚拟专用网络” 服务器也是属于网络的一台设备,因此你可能已经注意到它会自动分配一个 IP 地址。
|
||||
|
||||
这里的潜在问题是你的路由器不能保证每台设备都能在重新连接后获取到相同的 IP 地址。路由器确实尝试保持 IP 地址一致,但这会根据当时连接的设备数量而发生变化。
|
||||
|
||||
但是,几乎所有的路由器都会有一个界面,允许你为特定设备调停和保留 IP 地址。
|
||||
|
||||
![Router IP address settings][7]
|
||||
|
||||
路由器没有统一的界面,因此请在你的路由器接口中搜索 “DHCP” 或 “Static IP address” 选项。为你的服务器分配自己的预留 IP 地址,使其在网络中保持 IP 不变。
|
||||
|
||||
### 连接到服务器
|
||||
|
||||
默认情况下,你的路由器可能内置了防火墙。这通常很好,因为你不希望网络之外的人能够强行进入你的任何计算机。但是,你必须允许发往 “虚拟专用网络” 服务器的流量通过防火墙,否则你的 “虚拟专用网络” 将无法访问,这种情况下你的 “虚拟专用网络” 服务器将形同虚设。
|
||||
|
||||
你至少需要一个来自互联网服务提供商的公共静态 IP 地址。使用其静态 IP 地址设置路由器的公共端,然后将你的 0penVPN 服务器放在专用端,在你的网络中使用专用静态 IP 地址。 0penVPN 默认使用 UDP 1194 端口。配置你的路由器,将你的公网 “虚拟专用网络” IP 地址的 UDP 1194 端口转发到 0penVPN 服务器上的 UDP 1194 端口。如果你决定使用不同的 UDP 端口,请相应地调整端口号。
|
||||
|
||||
### 准备好,我们开始下一步
|
||||
|
||||
在本文中,你在服务器上安装并配置了一个操作系统,这已经成功了一半。在下一篇文章中,你将解决安装和配置 0penVPN 本身的问题。同时,请熟悉你的路由器并确保你可以从外部访问你的服务器。但是请务必在测试后关闭端口转发,直到你的 “虚拟专用网络” 服务启动并运行。
|
||||
|
||||
本文的部分内容改编自 D. Greg Scott 的博客,并经许可重新发布。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/8/openvpn-server-linux
|
||||
|
||||
作者:[D. Greg Scott][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[perfiffer](https://github.com/perfiffer)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/greg-scott
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_tea_laptop_computer_work_desk.png?itok=D5yMx_Dr (Person drinking a hot drink at the computer)
|
||||
[2]: https://openvpn.net/
|
||||
[3]: http://getfedora.org
|
||||
[4]: https://opensource.com/article/20/10/fedora-media-writer
|
||||
[5]: https://opensource.com/article/21/2/linux-installation
|
||||
[6]: https://www.redhat.com/sysadmin/secure-linux-network-firewall-cmd
|
||||
[7]: https://opensource.com/sites/default/files/uploads/reserved-ip.jpg (Router IP address settings)
|
||||
[8]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[9]: https://opensource.com/article/20/9/firewall
|
||||
[10]: https://www.dgregscott.com/how-to-build-a-vpn-in-four-easy-steps-without-spending-one-penny/
|
52
published/20210804 Move files in the Linux terminal.md
Normal file
52
published/20210804 Move files in the Linux terminal.md
Normal file
@ -0,0 +1,52 @@
|
||||
[#]: subject: (Move files in the Linux terminal)
|
||||
[#]: via: (https://opensource.com/article/21/8/move-files-linux)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (wxy)
|
||||
[#]: publisher: (wxy)
|
||||
[#]: url: (https://linux.cn/article-13677-1.html)
|
||||
|
||||
基础:在 Linux 终端中移动文件
|
||||
======
|
||||
|
||||
> 使用 mv 命令将一个文件从一个位置移动到另一个位置。
|
||||
|
||||
![](https://img.linux.net.cn/data/attachment/album/202108/13/112248lnal8a0qz50zqzld.jpg)
|
||||
|
||||
要在有图形界面的计算机上移动一个文件,你要打开该文件当前所在的文件夹,然后打开另一个窗口导航到你想把文件移到的文件夹。最后,你把文件从一个窗口拖到另一个窗口。
|
||||
|
||||
要在终端中移动文件,你可以使用 `mv` 命令将文件从一个位置移动到另一个位置。
|
||||
|
||||
```
|
||||
$ mv example.txt ~/Documents
|
||||
|
||||
$ ls ~/Documents
|
||||
example.txt
|
||||
```
|
||||
|
||||
在这个例子中,你已经把 `example.txt` 从当前文件夹移到了主目录下的 `Documents` 文件夹中。
|
||||
|
||||
只要你知道一个文件在 _哪里_,又想把它移到 _哪里_ 去,你就可以把文件从任何地方移动到任何地方,而不管你在哪里。与在一系列窗口中浏览你电脑上的所有文件夹以找到一个文件,然后打开一个新窗口到你想让该文件去的地方,再拖动该文件相比,这可以大大节省时间。
|
||||
|
||||
默认情况下,`mv` 命令完全按照它被告知的那样做:它将一个文件从一个位置移动到另一个位置。如果在目标位置已经存在一个同名的文件,它将被覆盖。为了防止文件在没有警告的情况下被覆盖,请使用 `--interactive`(或简写 `-i`)选项。
|
||||
|
||||
```
|
||||
$ mv -i example.txt ~/Documents
|
||||
mv: overwrite '/home/tux/Documents/example.txt'?
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/8/move-files-linux
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/ch01s05.svg_.png?itok=PgKQEDZ7 (Moving files)
|
@ -0,0 +1,174 @@
|
||||
[#]: subject: "Top 11 New Features in elementary OS 6 Linux Release"
|
||||
[#]: via: "https://news.itsfoss.com/elementary-os-6-features/"
|
||||
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "wxy"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-13678-1.html"
|
||||
|
||||
elementary OS 6 Linux 中的 11 个亮点
|
||||
======
|
||||
|
||||
> elementary OS 6 终于来了。让我们看一下这个主要版本中的重要亮点。
|
||||
|
||||
![](https://i2.wp.com/news.itsfoss.com/wp-content/uploads/2021/08/elementary-os-6-features.png?w=1200&ssl=1)
|
||||
|
||||
elementary OS 6 是其 5.x 系列经过几年更新后的一次重大升级。
|
||||
|
||||
虽然 5.x 系列也有许多功能更新和改进,但 [elementary OS 6][1] 的努力成果看起来令人兴奋。
|
||||
|
||||
在这里,让我们来看看 elementary OS 6 引入的所有新功能和变化。
|
||||
|
||||
### 1、暗黑风格及强调色
|
||||
|
||||
![][2]
|
||||
|
||||
[elementary OS][3] 暗黑风格的主题与现在主流的工作方式类似,是一种选择的偏好。你可以在安装 elementary OS 6 之后,在欢迎屏幕上选择它。
|
||||
|
||||
虽然增加暗黑模式听起来像是小事一桩,但他们似乎投入了大量的精力来提供一个整体一致的暗黑模式体验。
|
||||
|
||||
所有的第一方应用程序都无缝地支持暗黑风格和浅色主题。
|
||||
|
||||
elementary OS 还让应用开发者在 elementary OS 6 中遵照用户的偏好。因此,如果用户喜欢暗黑模式或浅色模式,应用程序就可以适应这种模式。
|
||||
|
||||
伴随着新的强调色的出现,还有一个自动的强调色偏好,可以从你当前的壁纸中挑选出强调的颜色。
|
||||
|
||||
### 2、改进的通知及重新设计的通知中心
|
||||
|
||||
通知现在支持图标徽章和行动按钮,这应该能提供更好的体验。
|
||||
|
||||
![][4]
|
||||
|
||||
这可以让你快速打开链接、标记一条消息已读,以及其他几种可能的操作。
|
||||
|
||||
紧急通知有了新的外观和独特的声音,以帮助你识别它们。
|
||||
|
||||
除了通知方面的改进,通知中心也进行了改造,使其看起来更好,并可以对多个通知进行清理。
|
||||
|
||||
### 3、在线账户
|
||||
|
||||
终于,在 elementary OS 6 中,你能够从系统设置中添加在线账户了。
|
||||
|
||||
一旦登录,你的数据将在支持的系统应用程序(如日历、任务)中同步。
|
||||
|
||||
它也会显示在系统托盘通知中。
|
||||
|
||||
### 4、第一方 Flatpak 应用及权限查看
|
||||
|
||||
为了提高整个平台的隐私和安全,elementary OS 6 采用了优先选择 Flatpak 的方式。
|
||||
|
||||
Elementary OS 现在有自己的应用中心 Flatpak 资源库。一些默认的应用程序以 Flatpak 包的形式出现,应用中心列出的所有应用程序也都有 Flatpak。
|
||||
|
||||
总的来说,这意味着更好的沙盒体验,你的所有应用程序将保持相互隔离,不会访问你的敏感数据。
|
||||
|
||||
![][5]
|
||||
|
||||
而且,最重要的是,elementary OS 6 增加了“门户”功能,应用程序会请求权限,以访问你的文件或启动另一个应用程序。
|
||||
|
||||
你还可以从系统设置中控制所有的权限。
|
||||
|
||||
### 5、多点触控手势
|
||||
|
||||
![][6]
|
||||
|
||||
对于笔记本电脑和触摸板用户来说,新的多点触控手势将变得非常方便。
|
||||
|
||||
从访问多任务视图到浏览工作区,你都可以用多点触摸手势来完成。
|
||||
|
||||
不仅仅局限于桌面上的某些功能,你还可以与通知互动、滑过应用程序,并可以通过新的多点触控手势获得全系统的顺滑体验。
|
||||
|
||||
你可以自定义手势或从系统设置下的手势部分了解更多信息。
|
||||
|
||||
### 6、屏幕盾牌
|
||||
|
||||
在 elementary OS 5 中,有些人注意到当你想运行一个耗时的任务或简单地观看视频时,会出现自动锁定屏幕的问题。
|
||||
|
||||
然而,这种情况在 elementary OS 6 中得到了改变,它不仅解决了这个问题,还以 “屏幕盾牌” 功能的形式带来了新的实现方式。
|
||||
|
||||
因此,在观看视频或执行耗时的任务时,你可以轻松地保持系统的清醒,而不会突然中断。
|
||||
|
||||
它利用了 GNOME 的守护程序设置,与第三方应用程序有更好的兼容性。
|
||||
|
||||
### 7、新的任务应用
|
||||
|
||||
![][7]
|
||||
|
||||
elementary OS 6 中添加了一个新的任务应用,在那里你可以管理任务、收到提醒,并在你的系统上组织任务,或与在线账户同步。
|
||||
|
||||
我可能还不会用它来取代 Planner,但它是一个很好的补充,因为它打造的很好。
|
||||
|
||||
### 8、固件更新应用程序
|
||||
|
||||
![][14]
|
||||
|
||||
你可以为支持的设备获得最新的固件更新,而无需摆弄任何其他设置。
|
||||
|
||||
只要从菜单中寻找“固件”应用程序就可以开始了。
|
||||
|
||||
### 9、更新的应用程序
|
||||
|
||||
一些应用程序已经被更新,同时引入了新的功能。
|
||||
|
||||
例如,Epiphany 浏览器被重新命名为 “Web”,现在有 Flatpak 包可用,以方便快速更新。
|
||||
|
||||
它还包括内置的跟踪保护和广告拦截。
|
||||
|
||||
其他一些值得注意的变化包括:
|
||||
|
||||
* 相机应用获得了一个新的用户界面,可以切换相机、镜像图像等等。
|
||||
* 应用中心现在不仅列出了 Flatpak 应用程序,而且还在应用程序完成安装后通知你,让你快速打开它。
|
||||
* 文件应用程序也得到了改进,其形式是一个新的侧边栏和列表视图。另外,现在需要双击才能打开一个文件,而单次点击可以在文件夹中导航。
|
||||
|
||||
其他应用程序如邮件、日历也得到了改进,以便更好地进行在线整合。
|
||||
|
||||
### 10、改进的桌面工作流程及屏幕截图工具
|
||||
|
||||
![][8]
|
||||
|
||||
多任务视图现在可以帮助你明确区分多个活动窗口。而热角视图可以让你将窗口移动到新的工作区,也可以将窗口最大化。
|
||||
|
||||
![][9]
|
||||
|
||||
屏幕截图工具可以在窗口中移动,而不仅仅是停留在窗口的中心。你还可以从预览中拖放图片,而不需要保存。
|
||||
|
||||
### 11、改进的安装程序
|
||||
|
||||
![][10]
|
||||
|
||||
你会注意到一些新的微妙的动画,而且还做了一些努力,以便在不重新调整窗口大小的情况下提供一个一致的安装程序布局。
|
||||
|
||||
这不是一次大修,但他们提到新的安装程序带有改进的磁盘检测和错误处理功能,这应该能使安装顺滑进行。
|
||||
|
||||
### 总结
|
||||
|
||||
[elementary OS 6][3] 是一个激动人心的版本,有多项改进。尽管外观和感觉并没有完全改变,但它已被全面精心雕琢。
|
||||
|
||||
我喜欢他们为提供一致和漂亮的用户体验所做的工作。另外,像全系统的 Flatpak 这样的变化应该使用户更容易和更安全。
|
||||
|
||||
你对这个版本有什么看法?你试过了吗?
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://news.itsfoss.com/elementary-os-6-features/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://news.itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://news.itsfoss.com/elementary-os-6-release/
|
||||
[2]: https://i1.wp.com/news.itsfoss.com/wp-content/uploads/2021/07/dark-style-elementary.jpg?w=1200&ssl=1
|
||||
[3]: https://elementary.io
|
||||
[4]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2021/06/notification-badge-elementary-os-6.png?w=724&ssl=1
|
||||
[5]: https://i2.wp.com/news.itsfoss.com/wp-content/uploads/2021/08/elementary-os-6-permissions.png?resize=1568%2C1158&ssl=1
|
||||
[6]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2021/08/multitouch-multitasking.png?resize=1568%2C883&ssl=1
|
||||
[7]: https://i0.wp.com/news.itsfoss.com/wp-content/uploads/2021/08/tasks.png?resize=1568%2C1188&ssl=1
|
||||
[8]: https://i1.wp.com/news.itsfoss.com/wp-content/uploads/2021/08/window-context-dark.png?w=808&ssl=1
|
||||
[9]: https://i2.wp.com/news.itsfoss.com/wp-content/uploads/2021/08/screenshot.png?w=660&ssl=1
|
||||
[10]: https://i2.wp.com/news.itsfoss.com/wp-content/uploads/2021/08/installer-progress.png?resize=1568%2C1140&ssl=1
|
||||
[14]: https://i1.wp.com/news.itsfoss.com/wp-content/uploads/2021/08/firmware.png?resize=1568%2C1158&ssl=1
|
@ -1,78 +0,0 @@
|
||||
[#]: subject: (GNOME Web Canary is Now Available to Test Bleeding Edge Features)
|
||||
[#]: via: (https://news.itsfoss.com/gnome-web-canary/)
|
||||
[#]: author: (Ankush Das https://news.itsfoss.com/author/ankush/)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
GNOME Web Canary is Now Available to Test Bleeding Edge Features
|
||||
======
|
||||
|
||||
Epiphany or [GNOME Web][1] is a minimal and yet capable browser for Linux distributions. You should find it as the default browser for elementary OS.
|
||||
|
||||
With GNOME 40, the Epiphany browser has had some [improvements and additions][2].
|
||||
|
||||
Behind the scenes, it regularly gets some exciting improvements and feature additions. And for that, you can opt for the Tech Preview version of GNOME Web tailored for early testers.
|
||||
|
||||
Now, a new Canary flavor has been introduced that you can use to test features that are not yet available even in the tech preview build.
|
||||
|
||||
### GNOME Web Canary Flavor
|
||||
|
||||
![][3]
|
||||
|
||||
GNOME Web’s “Canary” builds let you test features that are not even available in the latest [WebKitGTK][4] version.
|
||||
|
||||
Do note that the canary builds are supposed to be extremely unstable, even worse than the development builds available as a tech preview.
|
||||
|
||||
However, with the help of a Canary build, an end-user can test things way early in the process of development that can help find disastrous bugs.
|
||||
|
||||
Not just limited to end-user early testing, a canary build also makes things easier for a GNOME Web developer.
|
||||
|
||||
They no longer have to build WebKitGTK separately in order to implement and test a new feature.
|
||||
|
||||
Even though there was a Flatpak SDK available to ease the process for developers, it was still a time-consuming task.
|
||||
|
||||
Now, with that out of the way, the development pace can potentially improve as well.
|
||||
|
||||
### How to Get the Canary Build?
|
||||
|
||||
First, you need to add the WebKit SDK Flatpak remote using the commands below:
|
||||
|
||||
```
|
||||
flatpak --user remote-add --if-not-exists webkit https://software.igalia.com/flatpak-refs/webkit-sdk.flatpakrepo
|
||||
flatpak --user install https://nightly.gnome.org/repo/appstream/org.gnome.Epiphany.Canary.flatpakref
|
||||
```
|
||||
|
||||
Once done, you can install the Canary by using the [Flatpakref file][5] provided.
|
||||
|
||||
Testing a Canary build gives more users the ability to help GNOME Web developers in the process. So, it is definitely a much-needed addition to improve the development of the GNOME Web browser.
|
||||
|
||||
For more technical details, you might want to take a look at the [announcement post][6] by one of the developers.
|
||||
|
||||
#### Big Tech Websites Get Millions in Revenue, It's FOSS Got You!
|
||||
|
||||
If you like what we do here at It's FOSS, please consider making a donation to support our independent publication. Your support will help us keep publishing content focusing on desktop Linux and open source software.
|
||||
|
||||
I'm not interested
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://news.itsfoss.com/gnome-web-canary/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://news.itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://wiki.gnome.org/Apps/Web/
|
||||
[2]: https://news.itsfoss.com/gnome-web-new-tab/
|
||||
[3]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjY0MiIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
||||
[4]: https://webkitgtk.org
|
||||
[5]: https://nightly.gnome.org/repo/appstream/org.gnome.Epiphany.Canary.flatpakref
|
||||
[6]: https://base-art.net/Articles/introducing-the-gnome-web-canary-flavor/
|
@ -1,198 +0,0 @@
|
||||
[#]: subject: "Top 11 New Features in elementary OS 6 Linux Release"
|
||||
[#]: via: "https://news.itsfoss.com/elementary-os-6-features/"
|
||||
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Top 11 New Features in elementary OS 6 Linux Release
|
||||
======
|
||||
|
||||
elementary OS 6 is a major upgrade after a few good years of updates to the 5.x series.
|
||||
|
||||
While the 5.x series has had numerous feature updates and improvements, [elementary OS 6][1] looks to be an exciting endeavor.
|
||||
|
||||
Here, we shall take a look at all the new features and additions that have been introduced with elementary OS 6.
|
||||
|
||||
### 1\. Dark Style & Accent Color
|
||||
|
||||
![][2]
|
||||
|
||||
[elementary OS][3] approaches the dark style theme similar to how mainstream options work, as an opt-in preference. You get to choose it from the Welcome screen right after you install elementary OS 6.
|
||||
|
||||
While the addition of a dark mode may sound like something minor, they seem to have put a great deal of effort to provide a consistent dark mode experience overall.
|
||||
|
||||
All the first-party applications seamlessly support both the dark style and light theme.
|
||||
|
||||
elementary OS will also let the app developers respect the user’s preference in elementary OS 6. So, if the user prefers a dark mode or light mode, the app can adapt to that.
|
||||
|
||||
Along with new accent colors available, there is an automatic accent color preference that picks the color from your current wallpaper.
|
||||
|
||||
### 2\. Improved Notifications & Redesigned Notification Center
|
||||
|
||||
The notifications now support icon badges and action buttons, which should make up for a better experience.
|
||||
|
||||
![][4]
|
||||
|
||||
This could let you quickly open links, mark a message read, along with several other possibilities.
|
||||
|
||||
Urgent notifications have a new look and a unique sound to help you identify them.
|
||||
|
||||
In addition to the notification improvements, the notification center has also been revamped to look better and clean with multiple notifications.
|
||||
|
||||
### 3\. Online Accounts
|
||||
|
||||
Finally, with elementary OS 6, you will be able to add online accounts from the system settings.
|
||||
|
||||
Once signed in, your data will sync across the system apps wherever supported (like Calendar, Tasks).
|
||||
|
||||
It should also show up in the system tray notifications.
|
||||
|
||||
### 4\. First-Party Flatpak Apps & Permissions View
|
||||
|
||||
To improve privacy and security across the platform, elementary OS 6 chose the Flatpak-first approach.
|
||||
|
||||
elementary OS now has its own AppCenter Flatpak repository. Some of the default applications come baked in as Flatpak packages and all the applications listed in AppCenter are available as Flatpaks as well.
|
||||
|
||||
Overall, this means a better sandboxing experience where all of your applications will stay isolated from each other without accessing your sensitive data.
|
||||
|
||||
![][5]
|
||||
|
||||
And, to top it all off, elementary OS 6 adds “Portals” where the applications will request permission to access your files or launch another application.
|
||||
|
||||
You also get to control all the permissions from the System Settings.
|
||||
|
||||
### 5\. Multi-Touch Gestures
|
||||
|
||||
![][6]
|
||||
|
||||
For Laptop and touchpad users, the new multi-touch gestures are going to come in extremely handy.
|
||||
|
||||
From accessing the multitasking view to navigating through the workspaces, you can do it all using multi-touch gestures.
|
||||
|
||||
Not just limited to certain functions on the desktop, you can interact with notifications, swipe through applications, and can have a seamless system-wide experience with the new multi-touch gestures.
|
||||
|
||||
You can customize the gestures or learn more about it from the Gestures section under the System Settings.
|
||||
|
||||
### 6\. Screen Shield
|
||||
|
||||
With elementary OS 5, some noticed an issue with automatic screen locking when you want to run a time-consuming task or simply watch videos.
|
||||
|
||||
However, this changes with elementary OS 6, not only it solves the issue, it brings in a new implementation in the form of “**Screen Shield**” feature.
|
||||
|
||||
So, you can easily keep your system awake without sudden disruptions when watching a video or performing a time-consuming task.
|
||||
|
||||
It utilizes GNOME’s daemon settings to have better compatibility with third-party applications.
|
||||
|
||||
### 7\. New Tasks App
|
||||
|
||||
![][7]
|
||||
|
||||
A new tasks app has been added in elementary OS 6 where you can manage tasks, get reminded of them, and organize them on your system or synchronize it with an online account.
|
||||
|
||||
I may not replace it with Planner just yet, but it is a good addition to have baked in.
|
||||
|
||||
### 8\. Firmware Updates App
|
||||
|
||||
![][5]
|
||||
|
||||
You can get the latest firmware updates for supported devices without fiddling with any other settings.
|
||||
|
||||
Just look for the “Firmware” application from the menu to get started.
|
||||
|
||||
### 9\. App Updates
|
||||
|
||||
Several applications have been updated while introducing new capabilities.
|
||||
|
||||
For instance, Epiphany browser was renamed to “Web” and is now available as a Flatpak to facilitate quick updates.
|
||||
|
||||
It also includes tracking protection and ad blocking built-in.
|
||||
|
||||
Some other notable changes include:
|
||||
|
||||
* The camera app has recieved a new UI overhaul with the ability to switch cameras, mirroring of image, and more.
|
||||
* AppCenter not just lists Flatpak apps now but also notifies you when an application has completed installation to let you quickly open it.
|
||||
* Files app has also received improvements in the form a new sidebar and list view. Also, a double-click is now required to open a file and a single click can navigate through folders.
|
||||
|
||||
|
||||
|
||||
Other applications like Mail, Calendar have also received improvements for better online integrations.
|
||||
|
||||
### 10\. Improved Desktop Workflow & Screenshot Utility
|
||||
|
||||
![][8]
|
||||
|
||||
The multitasking view now helps you clearly distinguish among multiple active windows. And the hot corners view lets you move the window to a new workspace and maximize the window as well.
|
||||
|
||||
![][9]
|
||||
|
||||
The screenshot utility can be moved around in the window, not just stuck to the center of the window. You can also drag and drop the image from the preview without needing to save it.
|
||||
|
||||
### 11\. Improved Installer
|
||||
|
||||
![][10]
|
||||
|
||||
You will notice some new subtle animations, and some efforts have been made to provide a consistent layout of the installer without re-sizing the window.
|
||||
|
||||
![][11]
|
||||
|
||||
![][11]
|
||||
|
||||
![][12]
|
||||
|
||||
![][12]
|
||||
|
||||
![][12]
|
||||
|
||||
![][13]
|
||||
|
||||
![][13]
|
||||
|
||||
![][12]
|
||||
|
||||
![][12]
|
||||
|
||||
It isn’t a major overhaul, but they mention that the new installer comes with an improved disk detection and error handling, which should make the installation seamless.
|
||||
|
||||
### Wrapping Up
|
||||
|
||||
[elementary OS 6][3] is an exciting release with several improvements. Even though the look and feel is not entirely different, it has been polished across the board.
|
||||
|
||||
I like what they are doing to provide a consistent and beautiful user experience. Also, changes like system-wide Flatpak should make things easier and safer for users.
|
||||
|
||||
What do you think about this release? Have you tried it yet?
|
||||
|
||||
#### Big Tech Websites Get Millions in Revenue, It's FOSS Got You!
|
||||
|
||||
If you like what we do here at It's FOSS, please consider making a donation to support our independent publication. Your support will help us keep publishing content focusing on desktop Linux and open source software.
|
||||
|
||||
I'm not interested
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://news.itsfoss.com/elementary-os-6-features/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://news.itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://news.itsfoss.com/elementary-os-6-release/
|
||||
[2]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQzOSIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
||||
[3]: https://elementary.io
|
||||
[4]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjE4MCIgd2lkdGg9IjcyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
||||
[5]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjU3NyIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
||||
[6]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQ0MCIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
||||
[7]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjU5MSIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
||||
[8]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjgxNSIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
||||
[9]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjY5MiIgd2lkdGg9IjY2MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
||||
[10]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjU2NyIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
||||
[11]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjUzOSIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
||||
[12]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjUzNCIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
||||
[13]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQ5NyIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (chunibyo-wly)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
@ -1,108 +0,0 @@
|
||||
[#]: subject: (Tune your MySQL queries like a pro)
|
||||
[#]: via: (https://opensource.com/article/21/5/mysql-query-tuning)
|
||||
[#]: author: (Dave Stokes https://opensource.com/users/davidmstokes)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
Tune your MySQL queries like a pro
|
||||
======
|
||||
Optimizing your queries isn't a dark art; it's just simple engineering.
|
||||
![woman on laptop sitting at the window][1]
|
||||
|
||||
Many people consider tuning database queries to be some mysterious "dark art" out of a Harry Potter novel; with the wrong incantation, your data turns from a valuable resource into a pile of mush.
|
||||
|
||||
In reality, tuning queries for a relational database system is simple engineering and follows easy-to-understand rules or heuristics. The query optimizer translates the query you send to a [MySQL][2] instance, and then it determines the best way to get the requested data using those heuristics combined with what it knows about your data. Reread the last part of that: _"what it knows about your data_." The less the query optimizer has to guess about where your data is located, the better it can create a plan to deliver your data.
|
||||
|
||||
To give the optimizer better insight about the data, you can use indexes and histograms. Used properly, they can greatly increase the speed of a database query. If you follow the recipe, you will get something you will like. But if you add your own ingredients to that recipe, you may not get what you want.
|
||||
|
||||
### Cost-based optimizer
|
||||
|
||||
Most modern relational databases use a cost-based optimizer to determine how to retrieve your data out of the database. That cost is based on reducing very expensive disk reads as much as possible. The query optimizer code inside the database server keeps statistics on getting that data as it is encountered, and it builds a historical model of what it took to get the data.
|
||||
|
||||
But historical data can be out of date. It's like going to the store to buy your favorite snack and being shocked at a sudden price increase or that the store closed. Your server's optimization process may make a bad assumption based on old information, and that will produce a poor query plan.
|
||||
|
||||
A query's complexity can work against optimization. The optimizer wants to deliver the lowest-cost query of the available options. Joining five different tables means that there are five-factorial or 120 possible combinations about which to join to what. Heuristics are built into the code to try to shortcut evaluating all the possible options. MySQL wants to generate a new query plan every time it sees a query, while other databases such as Oracle can have a query plan locked down. This is why giving detailed information on your data to the optimizer is vital. For consistent performance, it really helps to have up-to-date information for the query optimizer to use when making query plans.
|
||||
|
||||
Also, rules are built into the optimizer with assumptions that probably do not match the reality of your data. The query optimizer will assume all the data in a column is evenly distributed among all the rows unless it has other information. And it will default to the smaller of two possible indexes if it sees no alternative. While the cost-based model for an optimizer can make a lot of good decisions, you can smack into cases where you will not get an optimal query plan.
|
||||
|
||||
### A query plan?
|
||||
|
||||
A query plan is what the optimizer will generate for the server to execute from the query. The way to see the query plan is to prepend the word `EXPLAIN` to your query. For example, the following query asks for the name of a city from the city table and the name of the corresponding country table, and the two tables are linked by the country's unique code. This case is interested only in the top five cities alphabetically from the United Kingdom:
|
||||
|
||||
|
||||
```
|
||||
SELECT city.name AS 'City',
|
||||
country.name AS 'Country'
|
||||
FROM city
|
||||
JOIN country ON (city.countrycode = country.code)
|
||||
WHERE country.code = 'GBR'
|
||||
LIMIT 5;
|
||||
```
|
||||
|
||||
Prepending `EXPLAIN` in front of this query will give the query plan generated by the optimizer. Skipping over all but the end of the output, it is easy to see the optimized query:
|
||||
|
||||
|
||||
```
|
||||
SELECT `world`.`city`.`Name` AS `City`,
|
||||
'United Kingdom' AS `Country`
|
||||
FROM `world`.`city`
|
||||
JOIN `world`.`country`
|
||||
WHERE (`world`.`city`.`CountryCode` = 'GBR')
|
||||
LIMIT 5;
|
||||
```
|
||||
|
||||
The big changes are that `country.name as 'Country'` was changed to `'United Kingdom' AS 'Country'` and the `WHERE` clause went from looking in the country table to the city table. The optimizer determined that these two changes will provide a faster result than the original query.
|
||||
|
||||
### Indexes
|
||||
|
||||
You will hear indexes and keys used interchangeably in the MySQL-verse. However, indexes are made up of keys, and keys are a way to identify a record, hopefully uniquely. If a column is designed as a key, the optimizer can search a list of those keys to find the desired record without having to read the entire table. Without an index, the server has to start at the first row of the first column and read through every row of data. If the column was created as a unique index, then the server can go to that one row of data and ignore the rest. The more unique the value of the index (also known as its cardinality), the better. Remember, we are looking for faster ways of getting to the data.
|
||||
|
||||
The MySQL default InnoDB storage engine wants your table to have a primary key and will store your data in a B+ tree by that key. A recently added MySQL feature is invisible columns—columns that do not return data unless the column is explicitly named in the query. For example, `SELECT * FROM foo;` doesn't provide any columns that are designated as hidden. This feature provides a way to add a primary key to older tables without recoding all the queries to include that new column.
|
||||
|
||||
To make this even more complicated, there are many types of indexes, such as functional, spatial, and composite. There are even cases where you can create an index that will provide all the requested information for a query so that there is no need to access the data table.
|
||||
|
||||
Describing the various indexes is beyond the scope of this article, so just think of an index as a shortcut to the record or records you desire. You can create an index on one or more columns or part of those columns. My physician's system can look up my records by the first three letters of my last name and birthdate. Using multiple columns requires using the most unique field first, then the second most unique, and so forth. An index on year-month-day works for year-month-day, year-month, and year searches, but it doesn't work for day, month-day, or year-day searches. It helps to design your indexes around how you want to use your data.
|
||||
|
||||
### Histograms
|
||||
|
||||
A histogram is a distribution of your data. If you were alphabetizing people by their last name, you could use a "logical bucket" for the folks with last names starting with the letters A to F, then another for G to J, and so forth. The optimizer assumes that the data is evenly distributed within the column, but this is rarely the case in practical use.
|
||||
|
||||
MySQL provides two types of histograms: equal height, where all the data is divided equally among the buckets, and singleton, where a single value is in a bucket. You can have up to 1,024 buckets. The amount of buckets to choose for your data column depends on many factors, including how many distinct values you have, how skewed your data is, and how high your accuracy really needs to be. After a certain amount of buckets, there are diminishing returns.
|
||||
|
||||
This command will create a histogram of 10 buckets on column c1 of table t:
|
||||
|
||||
|
||||
```
|
||||
`ANALYZE TABLE t UPDATE HISTOGRAM ON c1 WITH 10 BUCKETS;`
|
||||
```
|
||||
|
||||
Imagine you sell small, medium, and large socks, and each size has its own bin for storage. To find the size you need, you go to the bin for that size. MySQL has had histograms since MySQL 8.0 was released three years ago, yet they are not as well-known as indexes. Unlike indexes, there is no overhead for inserting, updating, or deleting a record. To update an index, an `ANALYZE TABLE` command must be updated. This is a good approach when the data does not churn very much and frequent changes to the data will reduce the efficiency.
|
||||
|
||||
### Indexes or histograms?
|
||||
|
||||
Use indexes for unique items where you need to access the data directly. There is overhead for updates, deletes, and inserts, but you get speedy access if your data is properly architected. Use histograms for data that does not get updated frequently, such as quarterly results for the last dozen years.
|
||||
|
||||
### Parting thoughts
|
||||
|
||||
This article grew out of a recent presentation at the [Open Source 101 conference][3]. And that presentation grew out of a workshop at a [PHP UK Conference][4]. Query tuning is a complex subject, and each time I present on indexes and histograms, I find ways to refine my presentation. But each presentation also shows that many folks in the software world are not well-versed on indexes and tend to use them incorrectly. Histograms have not been around long enough (I hope) to have been misused similarly.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/5/mysql-query-tuning
|
||||
|
||||
作者:[Dave Stokes][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/davidmstokes
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/lenovo-thinkpad-laptop-window-focus.png?itok=g0xPm2kD (young woman working on a laptop)
|
||||
[2]: https://www.mysql.com/
|
||||
[3]: https://opensource101.com/
|
||||
[4]: https://www.phpconference.co.uk/
|
@ -1,137 +0,0 @@
|
||||
[#]: subject: (Set up a VPN server on your Linux PC)
|
||||
[#]: via: (https://opensource.com/article/21/8/openvpn-server-linux)
|
||||
[#]: author: (D. Greg Scott https://opensource.com/users/greg-scott)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (perfiffer)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
Set up a VPN server on your Linux PC
|
||||
======
|
||||
The first step in building a VPN is setting up a VPN server.
|
||||
![Person drinking a hot drink at the computer][1]
|
||||
|
||||
Have you been connected to an untrusted network such as a hotel or café WiFi and need to securely browse the internet from your smartphone or laptop? By using a virtual private network (VPN), you can access that untrusted network anonymously and as safely as if you were on a private network.
|
||||
|
||||
VPN is an amazing tool for safeguarding private data. By using a VPN, you can connect to a private network on the internet while maintaining anonymity.
|
||||
|
||||
There are many VPN services available, and many people have found that the preferred option for securing private data when using untrusted networks is [OpenVPN][2].
|
||||
|
||||
OpenVPN creates an encrypted tunnel between two points, preventing a third party from accessing your network traffic data. By setting up your VPN server, you become your own VPN provider. Many popular VPN services use OpenVPN, so why tie your connection to a specific provider when you can have complete control yourself?
|
||||
|
||||
### Set up a Linux server
|
||||
|
||||
First, install a copy of Linux onto a spare PC. These examples use Fedora, but the steps are mostly the same no matter what Linux distribution you use.
|
||||
|
||||
Download a copy of the most recent Fedora ISO from the [Fedora project][3] website. Make a bootable USB drive, plug it into and boot your PC, and install the operating system. If you've never made a bootable USB drive, read about [Fedora Media Writer][4]. If you've never installed Linux, read about [installing Linux in three steps][5].
|
||||
|
||||
### Set up networking
|
||||
|
||||
After installing the Fedora operating system, log into the console or SSH session.
|
||||
|
||||
Apply the latest updates and reboot:
|
||||
|
||||
|
||||
```
|
||||
`$ sudo dnf update -y && reboot`
|
||||
```
|
||||
|
||||
Log in again and disable the firewall rules:
|
||||
|
||||
|
||||
```
|
||||
systemctl disable firewalld.service
|
||||
systemctl stop firewalld.service
|
||||
```
|
||||
|
||||
You may want to add appropriate firewall rules on this system for your internal network. If so, finish setting up and debugging OpenVPN with all firewall rules turned off, and then add your local firewall rules. For more information, read about [setting up firewalls on Linux][6].
|
||||
|
||||
### Set up IP addresses
|
||||
|
||||
You need a static IP address inside your local network. The commands below assume a Network Manager connection named `ens3` on a device named `ens3`. Your device and connection names might be different, so find them by opening an SSH session or the console and entering:
|
||||
|
||||
|
||||
```
|
||||
$ sudo nmcli connection show
|
||||
NAME UUID TYPE DEVICE
|
||||
ens3 39ad55bd-adde-384a-bb09-7f8e83380875 ethernet ens3
|
||||
```
|
||||
|
||||
You need to ensure that your remote people can find your VPN server. There are two ways to do this. You can set its IP address manually, or you can let your router do most of the work.
|
||||
|
||||
#### Configure an IP address manually
|
||||
|
||||
Set your static IP address, prefix, gateway, and DNS resolver with the following command but substituting your own IP addresses:
|
||||
|
||||
|
||||
```
|
||||
$ sudo nmcli connection modify ens3 ipv4.addresses 10.10.10.97/24
|
||||
$ sudo nmcli connection modify ens3 ipv4.gateway 10.10.10.1
|
||||
$ sudo nmcli connection modify ens3 ipv4.dns 10.10.10.10
|
||||
$ sudo nmcli connection modify ens3 ipv4.method manual
|
||||
$ sudo nmcli connection modify ens3 connection.autoconnect yes
|
||||
```
|
||||
|
||||
Set a hostname:
|
||||
|
||||
|
||||
```
|
||||
`$ sudo hostnamectl set-hostname OVPNserver2020`
|
||||
```
|
||||
|
||||
If you run a local DNS server, you will want to set up a DNS entry with the hostname pointing to the VPN server IP Address.
|
||||
|
||||
Reboot and make sure the system has the correct networking information.
|
||||
|
||||
#### Configure an IP address in your router
|
||||
|
||||
You probably have a router on your network. You may have purchased it, or you may have gotten one from your internet service provider (ISP). Either way, your router probably has a built-in DHCP server that assigns an IP address to each device on your network. Your new server counts as a device on your network, so you may have noticed an IP address is assigned to it automatically.
|
||||
|
||||
The potential problem here is that your router doesn't guarantee that any device will ever get the same IP address after reconnecting. It does _try_ to keep the IP addresses consistent, but they can change depending on how many devices are connected at the time.
|
||||
|
||||
However, almost all routers have an interface allowing you to intercede and reserve IP addresses for specific devices.
|
||||
|
||||
![Router IP address settings][7]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][8])
|
||||
|
||||
There isn't a universal interface for routers, so search the interface of the router you own for **DHCP** or **Static IP address** options. Assign your server its own reserved IP address so that its network location remains the same no matter what.
|
||||
|
||||
### Access your server
|
||||
|
||||
By default, your router probably has a firewall built into it. This is normally good because you don't want someone outside your network to be able to brute force their way into any of your computers. However, you must allow traffic destined for your VPN server through your firewall, or else your VPN will be unreachable and, therefore, no use to you.
|
||||
|
||||
You will need at least one public static IP Address from your internet service provider. Set up the public side of your router with its static IP Address, and then put your OpenVPN server on the private side, with its own private static IP Address inside your network. OpenVPN uses UDP port 1194 by default. Configure your router to [port-forward][9] traffic for your public VPN IP Address on UDP port 1194 to UDP port 1194 on your OpenVPN server. If you decide to use a different UDP port, adjust the port number accordingly.
|
||||
|
||||
### Get ready for the next step
|
||||
|
||||
In this article, you installed and configured an operating system on your server, which is approximately half the battle. In the next article, you'll tackle installing and configuring OpenVPN itself. In the meantime, get familiar with your router and make sure you can reach your server from the outside world. But be sure to close the port forwarding after testing until your VPN is up and running.
|
||||
|
||||
* * *
|
||||
|
||||
_Parts of this article were adapted from D. Greg Scott's [blog][10] and have been republished with permission._
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/8/openvpn-server-linux
|
||||
|
||||
作者:[D. Greg Scott][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/greg-scott
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_tea_laptop_computer_work_desk.png?itok=D5yMx_Dr (Person drinking a hot drink at the computer)
|
||||
[2]: https://openvpn.net/
|
||||
[3]: http://getfedora.org
|
||||
[4]: https://opensource.com/article/20/10/fedora-media-writer
|
||||
[5]: https://opensource.com/article/21/2/linux-installation
|
||||
[6]: https://www.redhat.com/sysadmin/secure-linux-network-firewall-cmd
|
||||
[7]: https://opensource.com/sites/default/files/uploads/reserved-ip.jpg (Router IP address settings)
|
||||
[8]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[9]: https://opensource.com/article/20/9/firewall
|
||||
[10]: https://www.dgregscott.com/how-to-build-a-vpn-in-four-easy-steps-without-spending-one-penny/
|
@ -0,0 +1,708 @@
|
||||
[#]: subject: "Code memory safety and efficiency by example"
|
||||
[#]: via: "https://opensource.com/article/21/8/memory-programming-c"
|
||||
[#]: author: "Marty Kalin https://opensource.com/users/mkalindepauledu"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Code memory safety and efficiency by example
|
||||
======
|
||||
Learn more about memory safety and efficiency
|
||||
![Code going into a computer.][1]
|
||||
|
||||
C is a high-level language with close-to-the-metal features that make it seem, at times, more like a portable assembly language than a sibling of Java or Python. Among these features is memory management, which covers an executing program's safe and efficient use of memory. This article goes into the details of memory safety and efficiency through code examples in C and a code segment from the assembly language that a modern C compiler generates.
|
||||
|
||||
Although the code examples are in C, the guidelines for safe and efficient memory management are the same for C++. The two languages differ in various details (e.g., C++ has object-oriented features and generics that C lacks), but these languages share the very same challenges with respect to memory management.
|
||||
|
||||
### Overview of memory for an executing program
|
||||
|
||||
For an executing program (aka _process_), memory is partitioned into three areas: The **stack**, the **heap**, and the **static area**. Here's an overview of each, with full code examples to follow.
|
||||
|
||||
As a backup for general-purpose CPU registers, the _stack_ provides scratchpad storage for the local variables within a code block, such as a function or a loop body. Arguments passed to a function count as local variables in this context. Consider a short example:
|
||||
|
||||
|
||||
```
|
||||
void some_func(int a, int b) {
|
||||
int n;
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Storage for the arguments passed in parameters **a** and **b** and the local variable **n** would come from the stack unless the compiler could find general-purpose registers instead. The compiler favors such registers for scratchpad because CPU access to these registers is fast (one clock tick). However, these registers are few (roughly sixteen) on the standard architectures for desktop, laptop, and handheld machines.
|
||||
|
||||
At the implementation level, which only an assembly-language programmer would see, the stack is organized as a LIFO (Last In, First Out) list with **push** (insert) and **pop** (remove) operations. The **top** pointer can act as a base address for offsets; in this way, stack locations other than **top** become accessible. For example, the expression **top+16** points to a location sixteen bytes above the stack's **top**, and the expression **top-16** points to sixteen bytes below the **top**. Accordingly, stack locations that implement scratchpad storage are accessible through the **top** pointer. On a standard ARM or Intel architecture, the stack grows from high to low memory addresses; hence, to decrement **top** is to grow the stack for a process.
|
||||
|
||||
To use the stack is to use memory effortlessly and efficiently. The compiler, rather than the programmer, writes the code that manages the stack by allocating and deallocating the required scratchpad storage; the programmer declares function arguments and local variables, leaving the implementation to the compiler. Moreover, the very same stack storage can be reused across consecutive function calls and code blocks such as loops. Well-designed modular code makes stack storage the first memory option for scratchpad, with an optimizing compiler using, whenever possible, general-purpose registers instead of the stack.
|
||||
|
||||
The **heap** provides storage allocated explicitly through programmer code, although the syntax for heap allocation differs across languages. In C, a successful call to the library function **malloc** (or variants such as **calloc**) allocates a specified number of bytes. (In languages such as C++ and Java, the **new** operator serves the same purpose.) Programming languages differ dramatically on how heap-allocated storage is deallocated:
|
||||
|
||||
* In languages such as Java, Go, Lisp, and Python, the programmer does not explicitly deallocate dynamically allocated heap storage.
|
||||
|
||||
|
||||
|
||||
For example, this Java statement allocates heap storage for a string and stores the address of this heap storage in the variable **greeting**:
|
||||
|
||||
|
||||
```
|
||||
`String greeting = new String("Hello, world!");`
|
||||
```
|
||||
|
||||
Java has a garbage collector, a runtime utility that automatically deallocates heap storage that is no longer accessible to the process that allocated the storage. Java heap deallocation is thus automatic through a garbage collector. In the example above, the garbage collector would deallocate the heap storage for the string after the variable **greeting** went out of scope.
|
||||
|
||||
* The Rust compiler writes the heap-deallocation code. This is Rust's pioneering effort to automate heap-deallocation without relying on a garbage collector, which entails runtime complexity and overhead. Hats off to the Rust effort!
|
||||
* In C (and C++), heap deallocation is a programmer task. The programmer who allocates heap storage through a call to **malloc** is then responsible for deallocating this same storage with a matching call to the library function **free**. (In C++, the **new** operator allocates heap storage, whereas the **delete** and **delete[]** operators free such storage.) Here's a C example:
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
char* greeting = malloc(14); /* 14 heap bytes */
|
||||
strcpy(greeting, "Hello, world!"); /* copy greeting into bytes */
|
||||
puts(greeting); /* print greeting */
|
||||
free(greeting); /* free malloced bytes */
|
||||
```
|
||||
|
||||
C avoids the cost and complexity of a garbage collector, but only by burdening the programmer with the task of heap deallocation.
|
||||
|
||||
The **static area** of memory provides storage for executable code such as C functions, string literals such as "Hello, world!", and global variables:
|
||||
|
||||
|
||||
```
|
||||
int n; /* global variable */
|
||||
int main() { /* function */
|
||||
char* msg = "No comment"; /* string literal */
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
This area is static in that its size remains fixed from the start until the end of process execution. Because the static area amounts to a fixed-sized memory footprint for a process, the rule of thumb is to keep this area as small as possible by avoiding, for example, global arrays.
|
||||
|
||||
Code examples in the following sections flesh out this overview.
|
||||
|
||||
### Stack storage
|
||||
|
||||
Imagine a program that has various tasks to perform consecutively, including processing numeric data downloaded every few minutes over a network and stored in a local file. The **stack** program below simplifies the processing (odd integer values are made even) to keep the focus on the benefits of stack storage.
|
||||
|
||||
|
||||
```
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define Infile "incoming.dat"
|
||||
#define Outfile "outgoing.dat"
|
||||
#define IntCount 128000 /* 128,000 */
|
||||
|
||||
void other_task1() { /*...*/ }
|
||||
void other_task2() { /*...*/ }
|
||||
|
||||
void process_data(const char* infile,
|
||||
const char* outfile,
|
||||
const unsigned n) {
|
||||
int nums[n];
|
||||
FILE* input = [fopen][2](infile, "r");
|
||||
if (NULL == infile) return;
|
||||
FILE* output = [fopen][2](outfile, "w");
|
||||
if (NULL == output) {
|
||||
[fclose][3](input);
|
||||
return;
|
||||
}
|
||||
|
||||
[fread][4](nums, n, sizeof(int), input); /* read input data */
|
||||
unsigned i;
|
||||
for (i = 0; i < n; i++) {
|
||||
if (1 == (nums[i] & 0x1)) /* odd parity? */
|
||||
nums[i]--; /* make even */
|
||||
}
|
||||
[fclose][3](input); /* close input file */
|
||||
|
||||
[fwrite][5](nums, n, sizeof(int), output);
|
||||
[fclose][3](output);
|
||||
}
|
||||
|
||||
int main() {
|
||||
process_data(Infile, Outfile, IntCount);
|
||||
|
||||
/** now perform other tasks **/
|
||||
other_task1(); /* automatically released stack storage available */
|
||||
other_task2(); /* ditto */
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
The **main** function at the bottom first calls the **process_data** function, which creates a stack-based array of a size given by argument **n** (128,000 in the current example). Accordingly, the array holds 128,000 x **sizeof(int)** bytes, which comes to 512,000 bytes on standard devices because an **int** is four bytes on these devices. Data then are read into the array (using library function **fread**), processed in a loop, and saved to the local file **outgoing.dat** (using library function **fwrite**).
|
||||
|
||||
When the **process_data** function returns to its caller **main**, the roughly 500MB of stack scratchpad for the **process_data** function become available for other functions in the **stack** program to use as scratchpad. In this example, **main** next calls the stub functions **other_task1** and **other_task2**. The three functions are called consecutively from **main**, which means that all three can use the same stack storage for scratchpad. Because the compiler rather than the programmer writes the stack-management code, this approach is both efficient and easy on the programmer.
|
||||
|
||||
In C, any variable defined inside a block (e.g., a function's or a loop's body) has an **auto** storage class by default, which means that the variable is stack-based. The storage class **register** is now outdated because C compilers are aggressive, on their own, in trying to use CPU registers whenever possible. Only a variable defined inside a block may be **register**, which the compiler changes to **auto** if no CPU register is available.Stack-based programming may be the preferred way to go, but this style does have its challenges. The **badStack** program below illustrates.
|
||||
|
||||
|
||||
```
|
||||
#include <stdio.h>
|
||||
|
||||
const int* get_array(const unsigned n) {
|
||||
int arr[n]; /* stack-based array */
|
||||
unsigned i;
|
||||
for (i = 0; i < n; i++) arr[i] = 1 + 1;
|
||||
|
||||
return arr; /** ERROR **/
|
||||
}
|
||||
|
||||
int main() {
|
||||
const unsigned n = 16;
|
||||
const int* ptr = get_array(n);
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < n; i++) [printf][6]("%i ", ptr[i]);
|
||||
[puts][7]("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
The flow of control in the **badStack** program is straightforward. Function **main** calls function **get_array** with an argument of 128, which the called function then uses to create a local array of this size. The **get_array** function initializes the array and returns to **main** the array's identifier **arr**, which is a pointer constant that holds the address of the array's first **int** element.
|
||||
|
||||
The local array **arr** is accessible within the **get_array** function, of course, but this array cannot be legitimately accessed once **get_array** returns. Nonetheless, function **main** tries to print the stack-based array by using the stack address **arr**, which function **get_array** returns. Modern compilers warn about the mistake. For example, here's the warning from the GNU compiler:
|
||||
|
||||
|
||||
```
|
||||
badStack.c: In function 'get_array':
|
||||
badStack.c:9:10: warning: function returns address of local variable [-Wreturn-local-addr]
|
||||
8 | return arr; /** ERROR **/
|
||||
```
|
||||
|
||||
The general rule is that stack-based storage should be accessed only within the code block that contains the local variables implemented with stack storage (in this case, the array pointer **arr** and the loop counter **i**). Accordingly, a function should never return a pointer to stack-based storage.
|
||||
|
||||
### Heap storage
|
||||
|
||||
Several code examples highlight the fine points of using heap storage in C. In the first example, heap storage is allocated, used, and then freed in line with best practice. The second example nests heap storage inside other heap storage, which complicates the deallocation operation.
|
||||
|
||||
|
||||
```
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int* get_heap_array(unsigned n) {
|
||||
int* heap_nums = [malloc][8](sizeof(int) * n);
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < n; i++)
|
||||
heap_nums[i] = i + 1; /* initialize the array */
|
||||
|
||||
/* stack storage for variables heap_nums and i released
|
||||
automatically when get_num_array returns */
|
||||
return heap_nums; /* return (copy of) the pointer */
|
||||
}
|
||||
|
||||
int main() {
|
||||
unsigned n = 100, i;
|
||||
int* heap_nums = get_heap_array(n); /* save returned address */
|
||||
|
||||
if (NULL == heap_nums) /* malloc failed */
|
||||
[fprintf][9](stderr, "%s\n", "malloc(...) failed...");
|
||||
else {
|
||||
for (i = 0; i < n; i++) [printf][6]("%i\n", heap_nums[i]);
|
||||
[free][10](heap_nums); /* free the heap storage */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
The **heap** program above has two functions: **main** calls **get_heap_array** with an argument (currently 100) that specifies how many **int** elements the array should have. Because the heap allocation could fail, **main** checks whether **get_heap_array** has returned **NULL**, which signals failure. If the allocation succeeds, **main** prints the **int** values in the array—and immediately thereafter deallocates, with a call to library function **free**, the heap-allocated storage. This is best practice.
|
||||
|
||||
The **get_heap_array** function opens with this statement, which merits a closer look:
|
||||
|
||||
|
||||
```
|
||||
`int* heap_nums = malloc(sizeof(int) * n); /* heap allocation */`
|
||||
```
|
||||
|
||||
The **malloc** library function and its variants deal with bytes; hence, the argument to **malloc** is the number of bytes required for **n** elements of type **int**. (The **sizeof(int)** is four bytes on a standard modern device.) The **malloc** function returns either the address of the first among the allocated bytes or, in case of failure, **NULL**.
|
||||
|
||||
In a successful call to **malloc**, the returned address is 64-bits in size on a modern desktop machine. On handhelds and earlier desktop machines, the address might be 32-bits in size or, depending on age, even smaller. The elements in the heap-allocated array are of type **int**, a four-byte signed integer. The address of these heap-allocated **int**s is stored in the local variable **heap_nums**, which is stack-based. Here's a depiction:
|
||||
|
||||
|
||||
```
|
||||
heap-based
|
||||
stack-based /
|
||||
\ +----+----+ +----+
|
||||
heap-nums--->|int1|int2|...|intN|
|
||||
+----+----+ +----+
|
||||
```
|
||||
|
||||
Once the **get_heap_array** function returns, stack storage for pointer variable **heap_nums** is reclaimed automatically—but the heap storage for the dynamic **int** array persists, which is why the **get_heap_array** function returns (a copy of) this address to **main**, which now is responsible, after printing the array's integers, for explicitly deallocating the heap storage with a call to the library function **free**:
|
||||
|
||||
|
||||
```
|
||||
`free(heap_nums); /* free the heap storage */`
|
||||
```
|
||||
|
||||
The **malloc** function does not initialize heap-allocated storage, which therefore contains random values. By contrast, the **calloc **variant initializes the allocated storage to zeros. Both functions return **NULL** to signal failure.
|
||||
|
||||
In the **heap** example, **main** returns immediately after calling **free**, and the executing program terminates, which allows the system to reclaim any allocated heap storage. Nonetheless, the programmer should develop the habit of explicitly freeing heap storage as soon as it is no longer needed.
|
||||
|
||||
### Nested heap allocation
|
||||
|
||||
The next code example is trickier. C has various library functions that return a pointer to heap storage. Here's a familiar scenario:
|
||||
|
||||
1\. The C program invokes a library function that returns a pointer to heap-based storage, typically an aggregate such as an array or a structure:
|
||||
|
||||
|
||||
```
|
||||
`SomeStructure* ptr = lib_function(); /* returns pointer to heap storage */`
|
||||
```
|
||||
|
||||
2\. The program then uses the allocated storage.
|
||||
|
||||
3\. For cleanup, the issue is whether a simple call to **free** will clean up all of the heap-allocated storage that the library function allocates. For example, the **SomeStructure** instance may have fields that, in turn, point to heap-allocated storage. A particularly troublesome case would be a dynamically allocated array of structures, each of which has a field pointing to more dynamically allocated storage.The following code example illustrates the problem and focuses on designing a library that safely provides heap-allocated storage to clients.
|
||||
|
||||
|
||||
```
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct {
|
||||
unsigned id;
|
||||
unsigned len;
|
||||
float* heap_nums;
|
||||
} HeapStruct;
|
||||
unsigned structId = 1;
|
||||
|
||||
HeapStruct* get_heap_struct(unsigned n) {
|
||||
/* Try to allocate a HeapStruct. */
|
||||
HeapStruct* heap_struct = [malloc][8](sizeof(HeapStruct));
|
||||
if (NULL == heap_struct) /* failure? */
|
||||
return NULL; /* if so, return NULL */
|
||||
|
||||
/* Try to allocate floating-point aggregate within HeapStruct. */
|
||||
heap_struct->heap_nums = [malloc][8](sizeof(float) * n);
|
||||
if (NULL == heap_struct->heap_nums) { /* failure? */
|
||||
[free][10](heap_struct); /* if so, first free the HeapStruct */
|
||||
return NULL; /* then return NULL */
|
||||
}
|
||||
|
||||
/* Success: set fields */
|
||||
heap_struct->id = structId++;
|
||||
heap_struct->len = n;
|
||||
|
||||
return heap_struct; /* return pointer to allocated HeapStruct */
|
||||
}
|
||||
|
||||
void free_all(HeapStruct* heap_struct) {
|
||||
if (NULL == heap_struct) /* NULL pointer? */
|
||||
return; /* if so, do nothing */
|
||||
|
||||
[free][10](heap_struct->heap_nums); /* first free encapsulated aggregate */
|
||||
[free][10](heap_struct); /* then free containing structure */
|
||||
}
|
||||
|
||||
int main() {
|
||||
const unsigned n = 100;
|
||||
HeapStruct* hs = get_heap_struct(n); /* get structure with N floats */
|
||||
|
||||
/* Do some (meaningless) work for demo. */
|
||||
unsigned i;
|
||||
for (i = 0; i < n; i++) hs->heap_nums[i] = 3.14 + (float) i;
|
||||
for (i = 0; i < n; i += 10) [printf][6]("%12f\n", hs->heap_nums[i]);
|
||||
|
||||
free_all(hs); /* free dynamically allocated storage */
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
The **nestedHeap** example above centers on a structure **HeapStruct** with a pointer field named **heap_nums**:
|
||||
|
||||
|
||||
```
|
||||
typedef struct {
|
||||
unsigned id;
|
||||
unsigned len;
|
||||
float* heap_nums; /** pointer **/
|
||||
} HeapStruct;
|
||||
```
|
||||
|
||||
The function **get_heap_struct** tries to allocate heap storage for a **HeapStruct** instance, which entails allocating heap storage for a specified number of **float** variables to which the field **heap_nums** points. The result of a successful call to **get_heap_struct** can be depicted as follows, with **hs** as the pointer to the heap-allocated structure:
|
||||
|
||||
|
||||
```
|
||||
hs-->HeapStruct instance
|
||||
id
|
||||
len
|
||||
heap_nums-->N contiguous float elements
|
||||
```
|
||||
|
||||
In the **get_heap_struct** function, the first heap allocation is straightforward:
|
||||
|
||||
|
||||
```
|
||||
HeapStruct* heap_struct = [malloc][8](sizeof(HeapStruct));
|
||||
if (NULL == heap_struct) /* failure? */
|
||||
return NULL; /* if so, return NULL */
|
||||
```
|
||||
|
||||
The **sizeof(HeapStruct)** includes the bytes (four on a 32-bit machine, eight on a 64-bit machine) for the **heap_nums** field, which is a pointer to the **float** elements in a dynamically allocated array. At issue, then, is whether the **malloc** delivers the bytes for this structure or **NULL** to signal failure; if **NULL**, the **get_heap_struct** function returns **NULL** to notify the caller that the heap allocation failed.
|
||||
|
||||
The second attempted heap allocation is more complicated because, at this step, heap storage for the **HeapStruct** has been allocated:
|
||||
|
||||
|
||||
```
|
||||
heap_struct->heap_nums = [malloc][8](sizeof(float) * n);
|
||||
if (NULL == heap_struct->heap_nums) { /* failure? */
|
||||
[free][10](heap_struct); /* if so, first free the HeapStruct */
|
||||
return NULL; /* and then return NULL */
|
||||
}
|
||||
```
|
||||
|
||||
The argument **n** sent to the **get_heap_struct** function indicates how many **float** elements should be in the dynamically allocated **heap_nums** array. If the required **float** elements can be allocated, then the function sets the structure's **id** and **len** fields before returning the heap address of the **HeapStruct**. If the attempted allocation fails, however, two steps are necessary to meet best practice:
|
||||
|
||||
1\. The storage for the **HeapStruct** must be freed to avoid memory leakage. Without the dynamic **heap_nums** array, the **HeapStruct** is presumably of no use to the client function that calls **get_heap_struct**; hence, the bytes for the **HeapStruct** instance should be explicitly deallocated so that the system can reclaim these bytes for future heap allocations.
|
||||
|
||||
2\. **NULL** is returned to signal failure.
|
||||
|
||||
If the call to the **get_heap_struct** function succeeds, then freeing the heap storage is also tricky because it involves two **free** operations in the proper order. Accordingly, the program includes a **free_all** function instead of requiring the programmer to figure out the appropriate two-step deallocation. For review, here's the **free_all** function:
|
||||
|
||||
|
||||
```
|
||||
void free_all(HeapStruct* heap_struct) {
|
||||
if (NULL == heap_struct) /* NULL pointer? */
|
||||
return; /* if so, do nothing */
|
||||
|
||||
[free][10](heap_struct->heap_nums); /* first free encapsulated aggregate */
|
||||
[free][10](heap_struct); /* then free containing structure */
|
||||
}
|
||||
```
|
||||
|
||||
After checking that the argument **heap_struct** is not **NULL**, the function first frees the **heap_nums** array, which requires that the **heap_struct** pointer is still valid. It would be an error to release the **heap_struct** first. Once the **heap_nums** have been deallocated, the **heap_struct** can be freed as well. If **heap_struct** were freed, but **heap_nums** were not, then the **float** elements in the array would be leakage: still allocated bytes but with no possibility of access—hence, of deallocation. The leakage would persist until the **nestedHeap** program exited and the system reclaimed the leaked bytes.
|
||||
|
||||
A few cautionary notes on the **free** library function are in order. Recall the sample calls above:
|
||||
|
||||
|
||||
```
|
||||
[free][10](heap_struct->heap_nums); /* first free encapsulated aggregate */
|
||||
[free][10](heap_struct); /* then free containing structure */
|
||||
```
|
||||
|
||||
These calls free the allocated storage—but they do _not_ set their arguments to **NULL**. (The **free** function gets a copy of an address as an argument; hence, changing the copy to **NULL** would leave the original unchanged.) For example, after a successful call to **free**, the pointer **heap_struct** still holds a heap address of some heap-allocated bytes, but using this address now would be an error because the call to **free** gives the system the right to reclaim and then reuse the allocated bytes.
|
||||
|
||||
Calling **free** with a **NULL** argument is pointless but harmless. Calling **free** repeatedly on a non-**NULL** address is an error with indeterminate results:
|
||||
|
||||
|
||||
```
|
||||
[free][10](heap_struct); /* 1st call: ok */
|
||||
[free][10](heap_struct); /* 2nd call: ERROR */
|
||||
```
|
||||
|
||||
### Memory leakage and heap fragmentation
|
||||
|
||||
The phrase "memory leakage" refers to dynamically allocated heap storage that is no longer accessible. Here's a code segment for review:
|
||||
|
||||
|
||||
```
|
||||
float* nums = [malloc][8](sizeof(float) * 10); /* 10 floats */
|
||||
nums[0] = 3.14f; /* and so on */
|
||||
nums = [malloc][8](sizeof(float) * 25); /* 25 new floats */
|
||||
```
|
||||
|
||||
Assume that the first **malloc** succeeds. The second **malloc** resets the **nums** pointer, either to **NULL** (allocation failure) or to the address of the first **float** among newly allocated twenty-five. Heap storage for the initial ten **float** elements remains allocated but is now inaccessible because the **nums** pointer either points elsewhere or is **NULL**. The result is forty bytes (**sizeof(float) * 10**) of leakage.
|
||||
|
||||
Before the second call to **malloc**, the initially allocated storage should be freed:
|
||||
|
||||
|
||||
```
|
||||
float* nums = [malloc][8](sizeof(float) * 10); /* 10 floats */
|
||||
nums[0] = 3.14f; /* and so on */
|
||||
[free][10](nums); /** good **/
|
||||
nums = [malloc][8](sizeof(float) * 25); /* no leakage */
|
||||
```
|
||||
|
||||
Even without leakage, the heap can fragment over time, which then requires system defragmentation. For example, suppose that the two biggest heap chunks are currently of sizes 200MB and 100MB. However, the two chunks are not contiguous, and process **P** needs to allocate 250MB of contiguous heap storage. Before the allocation can be made, the system must _defragment_ the heap to provide 250MB contiguous bytes for **P**. Defragmentation is complicated and, therefore, time-consuming.
|
||||
|
||||
Memory leakage promotes fragmentation by creating allocated but inaccessible heap chunks. Freeing no-longer-needed heap storage is, therefore, one way that a programmer can help to reduce the need for defragmentation.
|
||||
|
||||
### Tools to diagnose memory leakage
|
||||
|
||||
Various tools are available for profiling memory efficiency and safety. My favorite is [valgrind][11]. To illustrate how the tool works for memory leaks, here's the **leaky** program:
|
||||
|
||||
|
||||
```
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int* get_ints(unsigned n) {
|
||||
int* ptr = [malloc][8](n * sizeof(int));
|
||||
if (ptr != NULL) {
|
||||
unsigned i;
|
||||
for (i = 0; i < n; i++) ptr[i] = i + 1;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void print_ints(int* ptr, unsigned n) {
|
||||
unsigned i;
|
||||
for (i = 0; i < n; i++) [printf][6]("%3i\n", ptr[i]);
|
||||
}
|
||||
|
||||
int main() {
|
||||
const unsigned n = 32;
|
||||
int* arr = get_ints(n);
|
||||
if (arr != NULL) print_ints(arr, n);
|
||||
|
||||
/** heap storage not yet freed... **/
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
The function **main** calls **get_ints**, which tries to **malloc** thirty-two 4-byte **int**s from the heap and then initializes the dynamic array if the **malloc** succeeds. On success, the **main** function then calls **print_ints**. There is no call to **free** to match the call to **malloc**; hence, memory leaks.
|
||||
|
||||
With the **valgrind** toolbox installed, the command below checks the **leaky** program for memory leaks (**%** is the command-line prompt):
|
||||
|
||||
|
||||
```
|
||||
`% valgrind --leak-check=full ./leaky`
|
||||
```
|
||||
|
||||
Below is most of the output. The number on the left, 207683, is the process identifier of the executing **leaky** program. The report provides details of where the leak occurs, in this case, from the call to **malloc** within the **get_ints** function that **main** calls.
|
||||
|
||||
|
||||
```
|
||||
==207683== HEAP SUMMARY:
|
||||
==207683== in use at exit: 128 bytes in 1 blocks
|
||||
==207683== total heap usage: 2 allocs, 1 frees, 1,152 bytes allocated
|
||||
==207683==
|
||||
==207683== 128 bytes in 1 blocks are definitely lost in loss record 1 of 1
|
||||
==207683== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
|
||||
==207683== by 0x109186: get_ints (in /home/marty/gc/leaky)
|
||||
==207683== by 0x109236: main (in /home/marty/gc/leaky)
|
||||
==207683==
|
||||
==207683== LEAK SUMMARY:
|
||||
==207683== definitely lost: 128 bytes in 1 blocks
|
||||
==207683== indirectly lost: 0 bytes in 0 blocks
|
||||
==207683== possibly lost: 0 bytes in 0 blocks
|
||||
==207683== still reachable: 0 bytes in 0 blocks
|
||||
==207683== suppressed: 0 bytes in 0 blocks
|
||||
```
|
||||
|
||||
If function **main** is revised to include a call to **free** right after the one to **print_ints**, then **valgrind** gives the **leaky** program a clean bill of health:
|
||||
|
||||
|
||||
```
|
||||
`==218462== All heap blocks were freed -- no leaks are possible`
|
||||
```
|
||||
|
||||
### Static area storage
|
||||
|
||||
In orthodox C, a function must be defined outside all blocks. This rules out having one function defined inside the body of another, a feature that some C compilers support. My examples stick with functions defined outside all blocks. Such a function is either **static** or **extern**, with **extern** as the default.
|
||||
|
||||
C functions and variables with either **static** or **extern** as their storage class reside in what I've been calling the **static area** of memory because this area has a fixed size during program execution. The syntax for these two storage classes is complicated enough to merit a review. After the review, a full code example brings the syntactic details back to life. Functions or variables defined outside all blocks default to **extern**; hence, the storage class **static** must be explicit for both functions and variables:
|
||||
|
||||
|
||||
```
|
||||
/** file1.c: outside all blocks, five definitions **/
|
||||
int foo(int n) { return n * 2; } /* extern by default */
|
||||
static int bar(int n) { return n; } /* static */
|
||||
extern int baz(int n) { return -n; } /* explicitly extern */
|
||||
|
||||
int num1; /* extern */
|
||||
static int num2; /* static */
|
||||
```
|
||||
|
||||
The difference between **extern** and **static** comes down to scope: an **extern** function or variable may be visible across files. By contrast, a **static** function is visible only in the file that contains the function's _definition_, and a **static** variable is visible only in the file (or a block therein) that has the variable's _definition_:
|
||||
|
||||
|
||||
```
|
||||
static int n1; /* scope is the file */
|
||||
void func() {
|
||||
static int n2; /* scope is func's body */
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
If a **static** variable such as **n1** above is defined outside all blocks, the variable's scope is the file in which the variable is defined. Wherever a **static** variable may be defined, storage for the variable is in the static area of memory.
|
||||
|
||||
An **extern** function or variable is defined outside all blocks in a given file, but the function or variable so defined then may be declared in some other file. The typical practice is to _declare_ such a function or variable in a header file, which is included wherever needed. Some short examples clarify these tricky points.
|
||||
|
||||
Suppose that the **extern** function **foo** is _defined_ in **file1.c**, with or without the keyword **extern**:
|
||||
|
||||
|
||||
```
|
||||
/** file1.c **/
|
||||
int foo(int n) { return n * 2; } /* definition has a body {...} */
|
||||
```
|
||||
|
||||
This function must be _declared_ with an explicit **extern** in any other file (or block therein) for the function to be visible. Here's the declaration that makes the **extern** function **foo** visible in file **file2.c**:
|
||||
|
||||
|
||||
```
|
||||
/** file2.c: make function foo visible here **/
|
||||
extern int foo(int); /* declaration (no body) */
|
||||
```
|
||||
|
||||
Recall that a function declaration does not have a body enclosed in curly braces, whereas a function definition does have such a body.
|
||||
|
||||
For review, header files typically contain function and variable declarations. Source-code files that require the declarations then **#include** the relevant header file(s). The **staticProg** program in the next section illustrates this approach.
|
||||
|
||||
The rules get trickier (sorry!) with **extern** variables. Any **extern** object—function or variable—must be _defined_ outside all blocks. Also, a variable defined outside all blocks defaults to **extern**:
|
||||
|
||||
|
||||
```
|
||||
/** outside all blocks **/
|
||||
int n; /* defaults to extern */
|
||||
```
|
||||
|
||||
However, the **extern** can be explicit in the variable's _definition_ only if the variable is initialized explicitly there:
|
||||
|
||||
|
||||
```
|
||||
/** file1.c: outside all blocks **/
|
||||
int n1; /* defaults to extern, initialized by compiler to zero */
|
||||
extern int n2 = -1; /* ok, initialized explicitly */
|
||||
int n3 = 9876; /* ok, extern by default and initialized explicitly */
|
||||
```
|
||||
|
||||
For a variable defined as **extern** in **file1.c** to be visible in another file such as **file2.c**, the variable must be _declared_ as explicitly **extern** in **file2.c** and not initialized, which would turn the declaration into a definition:
|
||||
|
||||
|
||||
```
|
||||
/** file2.c **/
|
||||
extern int n1; /* declaration of n1 defined in file1.c */
|
||||
```
|
||||
|
||||
To avoid confusion with **extern** variables, the rule of thumb is to use **extern** explicitly in a _declaration_ (required) but not in a _definition_ (optional and tricky). For functions, the **extern** is optional in a definition but needed for a declaration. The **staticProg** example in the next section brings these points together in a full program.
|
||||
|
||||
### The staticProg example
|
||||
|
||||
The **staticProg** program consists of three files: two C source files (**static1.c** and **static2.c**) together with a header file (**static.h**) that contains two declarations:
|
||||
|
||||
|
||||
```
|
||||
/** header file static.h **/
|
||||
#define NumCount 100 /* macro */
|
||||
extern int global_nums[NumCount]; /* array declaration */
|
||||
extern void fill_array(); /* function declaration */
|
||||
```
|
||||
|
||||
The **extern** in the two declarations, one for an array and the other for a function, underscores that the objects are _defined_ elsewhere ("externally"): the array **global_nums** is defined in file **static1.c** (without an explicit **extern**) and the function **fill_array** is defined in file **static2.c** (also without an explicit **extern**). Each source file includes the header file **static.h**.The **static1.c** file defines the two arrays that reside in the static area of memory, **global_nums** and **more_nums**. The second array has a **static** storage class, which restricts its scope to the file (**static1.c**) in which the array is defined. As noted, **global_nums** as **extern** can be made visible in multiple files.
|
||||
|
||||
|
||||
```
|
||||
/** static1.c **/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "static.h" /* declarations */
|
||||
|
||||
int global_nums[NumCount]; /* definition: extern (global) aggregate */
|
||||
static int more_nums[NumCount]; /* definition: scope limited to this file */
|
||||
|
||||
int main() {
|
||||
fill_array(); /** defined in file static2.c **/
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < NumCount; i++)
|
||||
more_nums[i] = i * -1;
|
||||
|
||||
/* confirm initialization worked */
|
||||
for (i = 0; i < NumCount; i += 10)
|
||||
[printf][6]("%4i\t%4i\n", global_nums[i], more_nums[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
The **static2.c** file below defines the **fill_array** function, which **main** (in the **static1.c** file) invokes; the **fill_array** function populates the **extern** array named **global_nums**, which is defined in file **static1.c**. The sole point of having two files is to underscore that an **extern** variable or function can be visible across files.
|
||||
|
||||
|
||||
```
|
||||
/** static2.c **/
|
||||
#include "static.h" /** declarations **/
|
||||
|
||||
void fill_array() { /** definition **/
|
||||
unsigned i;
|
||||
for (i = 0; i < NumCount; i++) global_nums[i] = i + 2;
|
||||
}
|
||||
```
|
||||
|
||||
The **staticProg** program can be compiled as follows:
|
||||
|
||||
|
||||
```
|
||||
`% gcc -o staticProg static1.c static2.c`
|
||||
```
|
||||
|
||||
### More details from assembly language
|
||||
|
||||
A modern C compiler can handle any mix of C and assembly language. When compiling a C source file, the compiler first translates the C code into assembly language. Here's the command to save the assembly language generated from the **static1.c** file above:
|
||||
|
||||
|
||||
```
|
||||
`% gcc -S static1.c`
|
||||
```
|
||||
|
||||
The resulting file is **static1.s**. Here's a segment from the top, with added line numbers for readability:
|
||||
|
||||
|
||||
```
|
||||
.file "static1.c" ## line 1
|
||||
.text ## line 2
|
||||
.comm global_nums,400,32 ## line 3
|
||||
.local more_nums ## line 4
|
||||
.comm more_nums,400,32 ## line 5
|
||||
.section .rodata ## line 6
|
||||
.LC0: ## line 7
|
||||
.string "%4i\t%4i\n" ## line 8
|
||||
.text ## line 9
|
||||
.globl main ## line 10
|
||||
.type main, @function ## line 11
|
||||
main: ## line 12
|
||||
...
|
||||
```
|
||||
|
||||
The assembly-language directives such as **.file** (line 1) begin with a period. As the name suggests, a directive guides the assembler as it translates assembly language into machine code. The **.rodata** directive (line 6) indicates that read-only objects follow, including the string constant **"%4i\t%4i\n"** (line 8), which function **main** (line 12) uses to format output. The function **main** (line 12), introduced as a label (the colon at the end makes it so), is likewise read-only.
|
||||
|
||||
In assembly language, labels are addresses. The label **main:** (line 12) marks the address at which the code for the **main** function begins, and the label **.LC0**: (line 7) marks the address at which the format string begins.
|
||||
|
||||
The definitions of the **global_nums** (line 3) and **more_nums** (line 4) arrays include two numbers: 400 is the total number of bytes in each array, and 32 is the number of bits in each of the 100 **int** elements per array. (The **.comm** directive in line 5 stands for **common name**, which can be ignored.)
|
||||
|
||||
The array definitions differ in that **more_nums** is marked as **.local** (line 4), which means that its scope is restricted to the containing file **static1.s**. By contrast, the **global_nums** array can be made visible across multiple files, including the translations of the **static1.c** and **static2.c** files.
|
||||
|
||||
Finally, the **.text** directive occurs twice (lines 2 and 9) in the assembly code segment. The term "text" suggests "read-only" but also covers read/write variables such as the elements in the two arrays. Although the assembly language shown is for an Intel architecture, Arm6 assembly would be quite similar. For both architectures, variables in the **.text** area (in this case, elements in the two arrays) are initialized automatically to zeros.
|
||||
|
||||
### Wrapping up
|
||||
|
||||
For memory-efficient and memory-safe programming in C, the guidelines are easy to state but may be hard to follow, especially when calls to poorly designed libraries are in play. The guidelines are:
|
||||
|
||||
* Use stack storage whenever possible, thereby encouraging the compiler to optimize with general-purpose registers for scratchpad. Stack storage represents efficient memory use and promotes clean, modular code. Never return a pointer to stack-based storage.
|
||||
* Use heap storage carefully. The challenge in C (and C++) is to ensure that dynamically allocated storage is deallocated ASAP. Good programming habits and tools (such as **valgrind**) help to meet the challenge. Favor libraries that provide their own deallocation function(s), such as the **free_all** function in the **nestedHeap** code example.
|
||||
* Use static storage judiciously, as this storage impacts the memory footprint of a process from start to finish. In particular, try to avoid **extern** and **static** arrays.
|
||||
|
||||
|
||||
|
||||
The C code examples are available at my website (<https://condor.depaul.edu/mkalin>).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/8/memory-programming-c
|
||||
|
||||
作者:[Marty Kalin][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/mkalindepauledu
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/code_computer_development_programming.png?itok=4OM29-82 (Code going into a computer.)
|
||||
[2]: http://www.opengroup.org/onlinepubs/009695399/functions/fopen.html
|
||||
[3]: http://www.opengroup.org/onlinepubs/009695399/functions/fclose.html
|
||||
[4]: http://www.opengroup.org/onlinepubs/009695399/functions/fread.html
|
||||
[5]: http://www.opengroup.org/onlinepubs/009695399/functions/fwrite.html
|
||||
[6]: http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
|
||||
[7]: http://www.opengroup.org/onlinepubs/009695399/functions/puts.html
|
||||
[8]: http://www.opengroup.org/onlinepubs/009695399/functions/malloc.html
|
||||
[9]: http://www.opengroup.org/onlinepubs/009695399/functions/fprintf.html
|
||||
[10]: http://www.opengroup.org/onlinepubs/009695399/functions/free.html
|
||||
[11]: https://www.valgrind.org/
|
126
sources/tech/20210813 Install Linux with LVM.md
Normal file
126
sources/tech/20210813 Install Linux with LVM.md
Normal file
@ -0,0 +1,126 @@
|
||||
[#]: subject: "Install Linux with LVM"
|
||||
[#]: via: "https://opensource.com/article/21/8/install-linux-mint-lvm"
|
||||
[#]: author: "Kenneth Aaron https://opensource.com/users/flyingrhino"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Install Linux with LVM
|
||||
======
|
||||
A tutorial on getting Linux Mint 20.2 working with logical volume
|
||||
manager (LVM).
|
||||
![Linux keys on the keyboard for a desktop computer][1]
|
||||
|
||||
A couple of weeks ago, the good folks at [Linux Mint][2] released version 20.2 of their open source operating system. The installer built into the live ISO is excellent and only requires a few clicks to install the OS. You even have a built-in partitioner if you want to customize your partitions.
|
||||
|
||||
The installer is mainly focused on a simple install—define your partitions and install into them. For those wanting a more flexible setup—[logical volume manager][3] (LVM) is the way to go—you benefit from setting up volume groups and define your logical volumes within them.
|
||||
|
||||
LVM is a hard drive management system that allows you to create storage space across multiple physical drives. In other words, you could "tether" a few small drives together so your OS treats them as if they were one drive. Beyond that, it has the advantages of live resizing, file system snapshots, and much more. This article isn't a tutorial on LVM (the web is full of [good information on that already][4].) Instead, I aim to keep this page on topic and focus solely on getting Linux Mint 20.2 working with LVM.
|
||||
|
||||
As a desktop OS, the installer is kept simple, and installing LM 20.2 on LVM is slightly more involved but not too complicated. If you select LVM in the installer, you get a setup that's been defined by the Linux Mint devs, and you have no control over the individual volumes at the time of install.
|
||||
|
||||
However, there's a solution—right there in the live ISO—and that solution only requires a few commands in the terminal to set up the LVM, after which you resume the regular installer to complete the job.
|
||||
|
||||
I'm using Linux Mint 20.2 with the [XFCE desktop][5] for my install, but the procedure is similar for the other LM desktops.
|
||||
|
||||
### Partitioning the drive
|
||||
|
||||
In the Linux Mint live ISO, you have access to Linux command-line tools through the terminal and GUI tools. If you need to do any partition work, you can use the command-line `fdisk` or `parted` commands, or the GUI application `gparted`. I want to keep these instructions simple enough for anyone to follow, so I'll use GUI tools where possible and command-line tools where necessary.
|
||||
|
||||
Start by creating a couple of partitions for the install.
|
||||
|
||||
Using `gparted` (launched from the menu), complete the following:
|
||||
|
||||
First, create a partition of 512 MB of type **FAT32** (this is used to ensure the system is bootable.) 512 MB is overkill for most, and you can get away with 256 MB or even less, but with today's big disks, allocating even 512 MB is not a significant concern.
|
||||
|
||||
![Creating a boot partition][6]
|
||||
|
||||
CC BY-SA Seth Kenlon
|
||||
|
||||
Next, create a partition of the rest of the disk of type `lvm2 pv` (this is where your LVM will be.)
|
||||
|
||||
![Partition layout][7]
|
||||
|
||||
CC BY-SA Seth Kenlon
|
||||
|
||||
Now open a terminal window, and escalate your privileges to root:
|
||||
|
||||
|
||||
```
|
||||
$ sudo -s
|
||||
# whoami
|
||||
root
|
||||
```
|
||||
|
||||
Next, you must locate the LVM member (the big partition) you created earlier. Use one of the following commands: `lsblk -f` or `pvs` or `pvscan`.
|
||||
|
||||
|
||||
```
|
||||
# pvs
|
||||
PV VG Fmt [...]
|
||||
/dev/sda2 lvm2 [...]
|
||||
```
|
||||
|
||||
In my case, the partition is located at `/dev/sda2`, but you should replace this with whatever you get in your output.
|
||||
|
||||
Now that you know what device designation your partition has, you can create an LVM volume group there:
|
||||
|
||||
|
||||
```
|
||||
`# vgcreate vg /dev/sda2`
|
||||
```
|
||||
|
||||
You can see the details of the volume group you created using `vgs `or `vgscan`.
|
||||
|
||||
Create the logical volumes you want to use during install. I'm keeping it simple by creating one for the root partition (`/`) and one for `swap`, but you can create more as needed (for example, a separate partition for `/home`.)
|
||||
|
||||
|
||||
```
|
||||
# lvcreate -L 80G -n root vg
|
||||
# lvcreate -L 16G -n swap vg
|
||||
```
|
||||
|
||||
The partition sizes in my examples are arbitrary and based on what I have available. Use partition sizes that make sense for your drive.
|
||||
|
||||
You can view the logical volumes with `lvs` or `lvdisplay`.
|
||||
|
||||
That's it for the terminal.
|
||||
|
||||
### Installing Linux
|
||||
|
||||
Now start the installer program from the desktop icon:
|
||||
|
||||
* Once you get to the **Installation type**, select **Something else**.
|
||||
* Edit the 512 Mb partition and change it to `EFI`.
|
||||
* Edit the root LV and change it to `ext4` (or a file system of your choice). Select to mount it as root and select to format it.
|
||||
* Edit the swap partition and set it as `swap`.
|
||||
* Continue the install process normally—Linux Mint installer puts the files in the correct places and creates the mount points for you.
|
||||
|
||||
|
||||
|
||||
That's it—enjoy the power of LVM in your Linux Mint install.
|
||||
|
||||
If ever you need to resize partitions or do any advanced work on the system—you'll be thankful for choosing LVM.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/8/install-linux-mint-lvm
|
||||
|
||||
作者:[Kenneth Aaron][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/flyingrhino
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/linux_keyboard_desktop.png?itok=I2nGw78_ (Linux keys on the keyboard for a desktop computer)
|
||||
[2]: https://linuxmint.com/
|
||||
[3]: https://en.wikipedia.org/wiki/Logical_Volume_Manager_(Linux)
|
||||
[4]: https://opensource.com/business/16/9/linux-users-guide-lvm
|
||||
[5]: https://opensource.com/article/19/12/xfce-linux-desktop
|
||||
[6]: https://opensource.com/sites/default/files/boot-part.png (Creating a boot partition)
|
||||
[7]: https://opensource.com/sites/default/files/part-layout.png (Partition layout)
|
@ -0,0 +1,231 @@
|
||||
[#]: subject: "Parse command options in Java with commons-cli"
|
||||
[#]: via: "https://opensource.com/article/21/8/java-commons-cli"
|
||||
[#]: author: "Seth Kenlon https://opensource.com/users/seth"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Parse command options in Java with commons-cli
|
||||
======
|
||||
Let your users modify how your Java application runs with command-line
|
||||
options.
|
||||
![Learning and studying technology is the key to success][1]
|
||||
|
||||
When you enter a command into your terminal, whether it's to launch a GUI app or just a terminal app, there are often [options][2] (sometimes called _switches_ or _flags_) you can use to modify how the application runs. This is a standard set by the [POSIX specification][3], so it's useful for a Java programmer to know how to detect and parse options.
|
||||
|
||||
There are several ways to parse options in Java. My favorite is the [Apache Commons CLI][4] library, called **commons-cli** for short.
|
||||
|
||||
### Installing commons-cli
|
||||
|
||||
If you're using a project management system like [Maven][5] and an IDE, you can install the Apache Commons CLI library in your project properties (such as `pom.xml` or a configuration screen in Eclipse or NetBeans).
|
||||
|
||||
If you're managing libraries manually, you can download [the latest release][6] from the Apache website. Several JAR files come bundled together. The only required JAR is the `commons-cli-X.Y.jar` (where X and Y are the latest version numbers.) Add that JAR to your project, either manually or in your IDE, and then you can use it in your code.
|
||||
|
||||
### Importing a library into your Java code
|
||||
|
||||
To use the **commons-cli** library in your code, you must import it. For this simple option parsing example, you can populate a file called `Main.java` with the standard minimal code:
|
||||
|
||||
|
||||
```
|
||||
package com.opensource.myoptparser;
|
||||
|
||||
import org.apache.commons.cli.*;
|
||||
|
||||
public class Main {
|
||||
public static void main([String][7][] args) {
|
||||
// code
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now you're set to parse options in Java.
|
||||
|
||||
### Defining Boolean options in Java
|
||||
|
||||
The first thing you must do to parse options is to define the valid options your application can accept. Use the `Option` (singular) class to create option objects and the `Options` (plural) class to help keep track of all the options you've created in your project.
|
||||
|
||||
First, create a group for your options, and call it `options` according to convention:
|
||||
|
||||
|
||||
```
|
||||
//code
|
||||
Options options = new Options();
|
||||
```
|
||||
|
||||
Next, define your individual options by listing a short option, a long option, a default Boolean value, and a help message. You then set whether the option is required or not, and finally add the option to the `options` object, which contains all of your options. In this example, I create just one option, arbitrarily called `alpha`:
|
||||
|
||||
|
||||
```
|
||||
//define options
|
||||
[Option][8] alpha = new [Option][8]("a", "alpha", false, "Activate feature alpha");
|
||||
options.addOption(alpha);
|
||||
```
|
||||
|
||||
### Defining options with arguments in Java
|
||||
|
||||
Sometimes you want users to provide information other than just **true** or **false** along with an option. You might want to let a user refer to a configuration file, an input file, or any setting like a date or a color. For this, you use the `builder` method, creating attributes for an option based on its short version (for example, `-c` is a short option, `--config` is a long option). Once it's defined, you add the new option to your `options` group:
|
||||
|
||||
|
||||
```
|
||||
[Option][8] config = [Option][8].builder("c").longOpt("config")
|
||||
.argName("config")
|
||||
.hasArg()
|
||||
.required(true)
|
||||
.desc("set config file").build();
|
||||
options.addOption(config);
|
||||
```
|
||||
|
||||
With the `builder` function, you can set the short version, long version, whether it's required (I set this to **true** in this code, so my application can't run unless this option is provided by the user at launch time), the help message, and so on.
|
||||
|
||||
### Parsing options with Java
|
||||
|
||||
With all possible options defined, you can now iterate over arguments provided by the user, checking to see whether any argument matches your approved list of valid short options. To do this, you create an instance of the **CommandLine** itself, which contains all arguments provided by the user (valid options and otherwise.) You also create a **CommandLineParser** object, which I call `parser` in my code, to facilitate interaction over those arguments. Finally, you can create a **HelpFormatter** object (which I call `helper`) to automatically provide helpful messages to the user when either a required option is missing, or the `--help` or `-h` option is used.
|
||||
|
||||
|
||||
```
|
||||
// define parser
|
||||
CommandLine cmd;
|
||||
CommandLineParser parser = new BasicParser();
|
||||
HelpFormatter helper = new HelpFormatter();
|
||||
```
|
||||
|
||||
Finally, add some conditionals to analyze the options provided by the user as command-line input (discovered and stored in the `cmd` variable). This sample application has two different types of options, but in both cases, you can check whether the option exists with the `.hasOption` method plus the short option name. When an option is detected, you can do whatever needs to be done with the data.
|
||||
|
||||
|
||||
```
|
||||
try {
|
||||
cmd = parser.parse(options, args);
|
||||
if(cmd.hasOption("a")) {
|
||||
[System][9].out.println("Alpha activated");
|
||||
}
|
||||
|
||||
if (cmd.hasOption("c")) {
|
||||
[String][7] opt_config = cmd.getOptionValue("config");
|
||||
[System][9].out.println("Config set to " + opt_config);
|
||||
}
|
||||
} catch ([ParseException][10] e) {
|
||||
[System][9].out.println(e.getMessage());
|
||||
helper.printHelp("Usage:", options);
|
||||
[System][9].exit(0);
|
||||
}
|
||||
```
|
||||
|
||||
The act of parsing potentially generates an error because sometimes the required `-c` or `--config` option could be missing. In that event, a help message is printed, and the application is immediately ended. Because of this error (an _exception_ in Java terminology), you must amend the start of the main method to declare a possible exception:
|
||||
|
||||
|
||||
```
|
||||
`public static void main(String[] args) throws ParseException {`
|
||||
```
|
||||
|
||||
The sample application is now complete.
|
||||
|
||||
### Test your code
|
||||
|
||||
You can test the application in your IDE by adjusting the default parameters passed to your code or just build a JAR file and run it from your terminal. The process for this differs depending on your IDE. Refer to your IDE documentation, read my article on how to LINK-TO-ARTICLE[build a JAR], or see Daniel Oh's article on how to do the same with [Maven][11].
|
||||
|
||||
First, confirm the parser exception by omitting the required `-c` or `--config` option:
|
||||
|
||||
|
||||
```
|
||||
$ java -jar dist/myapp.jar
|
||||
Missing required option: c
|
||||
usage: Usage:
|
||||
-a,--alpha Activate feature alpha
|
||||
-c,--config <config> Set config file
|
||||
```
|
||||
|
||||
Try it again with the options provided:
|
||||
|
||||
|
||||
```
|
||||
java -jar dist/myantapp.jar --config foo -a
|
||||
Alpha activated
|
||||
Config set to foo
|
||||
```
|
||||
|
||||
### Option parsing
|
||||
|
||||
Including options for your users is an important feature for any application. Java and the Apache commons make it easy to do.
|
||||
|
||||
Here's the full demonstration code for your reference:
|
||||
|
||||
|
||||
```
|
||||
package com.opensource.myapp;
|
||||
|
||||
import org.apache.commons.cli.*;
|
||||
|
||||
public class Main {
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
* @throws org.apache.commons.cli.ParseException
|
||||
*/
|
||||
public static void main([String][7][] args) throws [ParseException][10] {
|
||||
// define options
|
||||
Options options = new Options();
|
||||
|
||||
[Option][8] alpha = new [Option][8]("a", "alpha", false, "Activate feature alpha");
|
||||
options.addOption(alpha);
|
||||
|
||||
[Option][8] config = [Option][8].builder("c").longOpt("config")
|
||||
.argName("config")
|
||||
.hasArg()
|
||||
.required(true)
|
||||
.desc("Set config file").build();
|
||||
options.addOption(config);
|
||||
|
||||
// define parser
|
||||
CommandLine cmd;
|
||||
CommandLineParser parser = new BasicParser();
|
||||
HelpFormatter helper = new HelpFormatter();
|
||||
|
||||
try {
|
||||
cmd = parser.parse(options, args);
|
||||
if(cmd.hasOption("a")) {
|
||||
[System][9].out.println("Alpha activated");
|
||||
}
|
||||
|
||||
if (cmd.hasOption("c")) {
|
||||
[String][7] opt_config = cmd.getOptionValue("config");
|
||||
[System][9].out.println("Config set to " + opt_config);
|
||||
}
|
||||
} catch ([ParseException][10] e) {
|
||||
[System][9].out.println(e.getMessage());
|
||||
helper.printHelp("Usage:", options);
|
||||
[System][9].exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Using Java and options
|
||||
|
||||
Options allow users to modify how commands work. There are many ways to parse options when using Java, and the `commons-cli` is a robust and flexible open source solution. Give it a try in your next Java project.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/8/java-commons-cli
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/studying-books-java-couch-education.png?itok=C9gasCXr (Learning and studying technology is the key to success)
|
||||
[2]: https://opensource.com/article/21/8/linux-terminal#options
|
||||
[3]: https://opensource.com/article/19/7/what-posix-richard-stallman-explains
|
||||
[4]: https://commons.apache.org/proper/commons-cli/usage.html
|
||||
[5]: https://maven.apache.org/
|
||||
[6]: https://commons.apache.org/proper/commons-cli/download_cli.cgi
|
||||
[7]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
|
||||
[8]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+option
|
||||
[9]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
|
||||
[10]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+parseexception
|
||||
[11]: https://developers.redhat.com/blog/2021/04/08/build-even-faster-quarkus-applications-with-fast-jar
|
@ -0,0 +1,304 @@
|
||||
[#]: subject: "Use dnf updateinfo to read update changelogs"
|
||||
[#]: via: "https://fedoramagazine.org/use-dnf-updateinfo-to-read-update-changelogs/"
|
||||
[#]: author: "Mateus Rodrigues Costa https://fedoramagazine.org/author/mateusrodcosta/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Use dnf updateinfo to read update changelogs
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
Cover image background excerpted from photo by [Fotis Fotopoulos][2] on [Unsplash][3]
|
||||
|
||||
This article will explore how to check the changelogs for the Fedora Linux operating system using the command line and _dnf updateinfo_. Instead of showing the commands running on a real Fedora Linux install, this article will demo running the dnf commands in [toolbox][4].
|
||||
|
||||
### Introduction
|
||||
|
||||
If you have used any type of computer recently (be it a desktop, laptop or even a smartphone), you most likely have had to deal with software updates. You might have an opinion about them. They might be a “necessary evil”, something that always breaks your setup and makes you waste hours fixing the new problems that appeared, or you might even like them.
|
||||
|
||||
No matter your opinion, there are reasons to update your software: mainly bug fixes, especially security-related bug fixes. After all, you most likely don’t want someone getting your private data by exploiting a bug that happens because of a interaction between the code of your web browser and the code that renders text on your screen.
|
||||
|
||||
If you manage your software updates in a manual or semi-manual fashion (in comparison to letting the operating system auto-update your software), one feature you should be aware of is “changelogs”.
|
||||
|
||||
A changelog is, as the name hints, a big list of changes between two releases of the same software. The changelog content can vary a lot. It may depend on the team, the type of software, its importance, and the number of changes. It can range from a very simple “several small bugs were fixed in this release”-type message, to a list of links to the bugs fixed on a issue tracker with a small description, to a big and detailed list of changes or elaborate blog posts.
|
||||
|
||||
Now, how do you check the changelogs for the updates?
|
||||
|
||||
If you use Fedora Workstation the easy way to see the changelog with a GUI is with Gnome Software. Select the name of the package or name of the software on the updates page and the changelog is displayed. You could also try your favorite GUI package manager, which will most likely show it to you as well. But how does one do the same thing via CLI?
|
||||
|
||||
### How to use dnf updateinfo
|
||||
|
||||
Start by creating a Fedora 34 toolbox called _updateinfo-demo_:
|
||||
|
||||
```
|
||||
toolbox create --distro fedora --release f34 updateinfo-demo
|
||||
```
|
||||
|
||||
Now, enter the toolbox:
|
||||
|
||||
```
|
||||
toolbox enter updateinfo-demo
|
||||
```
|
||||
|
||||
The commands from here on can also be used on a normal Fedora install.
|
||||
|
||||
First, check the updates available:
|
||||
|
||||
```
|
||||
$ dnf check-update
|
||||
audit-libs.x86_64 3.0.3-1.fc34 updates
|
||||
ca-certificates.noarch 2021.2.50-1.0.fc34 updates
|
||||
coreutils.x86_64 8.32-30.fc34 updates
|
||||
coreutils-common.x86_64 8.32-30.fc34 updates
|
||||
curl.x86_64 7.76.1-7.fc34 updates
|
||||
dnf.noarch 4.8.0-1.fc34 updates
|
||||
dnf-data.noarch 4.8.0-1.fc34 updates
|
||||
expat.x86_64 2.4.1-1.fc34 updates
|
||||
file-libs.x86_64 5.39-6.fc34 updates
|
||||
glibc.x86_64 2.33-20.fc34 updates
|
||||
glibc-common.x86_64 2.33-20.fc34 updates
|
||||
glibc-minimal-langpack.x86_64 2.33-20.fc34 updates
|
||||
krb5-libs.x86_64 1.19.1-14.fc34 updates
|
||||
libcomps.x86_64 0.1.17-1.fc34 updates
|
||||
libcurl.x86_64 7.76.1-7.fc34 updates
|
||||
libdnf.x86_64 0.63.1-1.fc34 updates
|
||||
libeconf.x86_64 0.4.0-1.fc34 updates
|
||||
libedit.x86_64 3.1-38.20210714cvs.fc34 updates
|
||||
libgcrypt.x86_64 1.9.3-3.fc34 updates
|
||||
libidn2.x86_64 2.3.2-1.fc34 updates
|
||||
libmodulemd.x86_64 2.13.0-1.fc34 updates
|
||||
librepo.x86_64 1.14.1-1.fc34 updates
|
||||
libsss_idmap.x86_64 2.5.2-1.fc34 updates
|
||||
libsss_nss_idmap.x86_64 2.5.2-1.fc34 updates
|
||||
libuser.x86_64 0.63-4.fc34 updates
|
||||
libxcrypt.x86_64 4.4.23-1.fc34 updates
|
||||
nano.x86_64 5.8-3.fc34 updates
|
||||
nano-default-editor.noarch 5.8-3.fc34 updates
|
||||
nettle.x86_64 3.7.3-1.fc34 updates
|
||||
openldap.x86_64 2.4.57-5.fc34 updates
|
||||
pam.x86_64 1.5.1-6.fc34 updates
|
||||
python-setuptools-wheel.noarch 53.0.0-2.fc34 updates
|
||||
python-unversioned-command.noarch 3.9.6-2.fc34 updates
|
||||
python3.x86_64 3.9.6-2.fc34 updates
|
||||
python3-dnf.noarch 4.8.0-1.fc34 updates
|
||||
python3-hawkey.x86_64 0.63.1-1.fc34 updates
|
||||
python3-libcomps.x86_64 0.1.17-1.fc34 updates
|
||||
python3-libdnf.x86_64 0.63.1-1.fc34 updates
|
||||
python3-libs.x86_64 3.9.6-2.fc34 updates
|
||||
python3-setuptools.noarch 53.0.0-2.fc34 updates
|
||||
sssd-client.x86_64 2.5.2-1.fc34 updates
|
||||
systemd.x86_64 248.6-1.fc34 updates
|
||||
systemd-libs.x86_64 248.6-1.fc34 updates
|
||||
systemd-networkd.x86_64 248.6-1.fc34 updates
|
||||
systemd-pam.x86_64 248.6-1.fc34 updates
|
||||
systemd-rpm-macros.noarch 248.6-1.fc34 updates
|
||||
vim-minimal.x86_64 2:8.2.3182-1.fc34 updates
|
||||
xkeyboard-config.noarch 2.33-1.fc34 updates
|
||||
yum.noarch 4.8.0-1.fc34 updates
|
||||
```
|
||||
|
||||
OK, so run your first _dnf updateinfo_ command:
|
||||
|
||||
```
|
||||
$ dnf updateinfo
|
||||
Updates Information Summary: available
|
||||
5 Security notice(s)
|
||||
4 Moderate Security notice(s)
|
||||
1 Low Security notice(s)
|
||||
11 Bugfix notice(s)
|
||||
8 Enhancement notice(s)
|
||||
3 other notice(s)
|
||||
```
|
||||
|
||||
This is the summary of updates. As you can see there are security updates, bugfix updates, enhancement updates and some which are not specified.
|
||||
|
||||
Look at the list of updates and which types they belong to:
|
||||
|
||||
```
|
||||
$ dnf updateinfo list
|
||||
FEDORA-2021-e4866762d8 enhancement audit-libs-3.0.3-1.fc34.x86_64
|
||||
FEDORA-2021-1f32e18471 bugfix ca-certificates-2021.2.50-1.0.fc34.noarch
|
||||
FEDORA-2021-b09e010a46 bugfix coreutils-8.32-30.fc34.x86_64
|
||||
FEDORA-2021-b09e010a46 bugfix coreutils-common-8.32-30.fc34.x86_64
|
||||
FEDORA-2021-83fdddca0f Moderate/Sec. curl-7.76.1-7.fc34.x86_64
|
||||
FEDORA-2021-3b74285c43 bugfix dnf-4.8.0-1.fc34.noarch
|
||||
FEDORA-2021-3b74285c43 bugfix dnf-data-4.8.0-1.fc34.noarch
|
||||
FEDORA-2021-523ee0a81e enhancement expat-2.4.1-1.fc34.x86_64
|
||||
FEDORA-2021-07625b9c81 unknown file-libs-5.39-6.fc34.x86_64
|
||||
FEDORA-2021-e14e86e40e Moderate/Sec. glibc-2.33-20.fc34.x86_64
|
||||
FEDORA-2021-e14e86e40e Moderate/Sec. glibc-common-2.33-20.fc34.x86_64
|
||||
FEDORA-2021-e14e86e40e Moderate/Sec. glibc-minimal-langpack-2.33-20.fc34.x86_64
|
||||
FEDORA-2021-8b25e4642f Low/Sec. krb5-libs-1.19.1-14.fc34.x86_64
|
||||
FEDORA-2021-3b74285c43 bugfix libcomps-0.1.17-1.fc34.x86_64
|
||||
FEDORA-2021-83fdddca0f Moderate/Sec. libcurl-7.76.1-7.fc34.x86_64
|
||||
FEDORA-2021-3b74285c43 bugfix libdnf-0.63.1-1.fc34.x86_64
|
||||
FEDORA-2021-ca22b882a5 enhancement libeconf-0.4.0-1.fc34.x86_64
|
||||
FEDORA-2021-f9c139edd8 bugfix libedit-3.1-38.20210714cvs.fc34.x86_64
|
||||
FEDORA-2021-31fdc84207 Moderate/Sec. libgcrypt-1.9.3-3.fc34.x86_64
|
||||
FEDORA-2021-bc56cf7c1f enhancement libidn2-2.3.2-1.fc34.x86_64
|
||||
FEDORA-2021-da2ec14d7f bugfix libmodulemd-2.13.0-1.fc34.x86_64
|
||||
FEDORA-2021-3b74285c43 bugfix librepo-1.14.1-1.fc34.x86_64
|
||||
FEDORA-2021-1db6330a22 unknown libsss_idmap-2.5.2-1.fc34.x86_64
|
||||
FEDORA-2021-1db6330a22 unknown libsss_nss_idmap-2.5.2-1.fc34.x86_64
|
||||
FEDORA-2021-8226c82fe9 bugfix libuser-0.63-4.fc34.x86_64
|
||||
FEDORA-2021-e6916d6758 bugfix libxcrypt-4.4.22-2.fc34.x86_64
|
||||
FEDORA-2021-fed4036fd9 bugfix libxcrypt-4.4.23-1.fc34.x86_64
|
||||
FEDORA-2021-3122d2b8d2 unknown nano-5.8-3.fc34.x86_64
|
||||
FEDORA-2021-3122d2b8d2 unknown nano-default-editor-5.8-3.fc34.noarch
|
||||
FEDORA-2021-d1fc0b9d32 Moderate/Sec. nettle-3.7.3-1.fc34.x86_64
|
||||
FEDORA-2021-97949d7a4e bugfix openldap-2.4.57-5.fc34.x86_64
|
||||
FEDORA-2021-e6916d6758 bugfix pam-1.5.1-6.fc34.x86_64
|
||||
FEDORA-2021-07931f7f08 bugfix python-setuptools-wheel-53.0.0-2.fc34.noarch
|
||||
FEDORA-2021-2056ce89d9 enhancement python-unversioned-command-3.9.6-1.fc34.noarch
|
||||
FEDORA-2021-d613e00b72 enhancement python-unversioned-command-3.9.6-2.fc34.noarch
|
||||
FEDORA-2021-2056ce89d9 enhancement python3-3.9.6-1.fc34.x86_64
|
||||
FEDORA-2021-d613e00b72 enhancement python3-3.9.6-2.fc34.x86_64
|
||||
FEDORA-2021-3b74285c43 bugfix python3-dnf-4.8.0-1.fc34.noarch
|
||||
FEDORA-2021-3b74285c43 bugfix python3-hawkey-0.63.1-1.fc34.x86_64
|
||||
FEDORA-2021-3b74285c43 bugfix python3-libcomps-0.1.17-1.fc34.x86_64
|
||||
FEDORA-2021-3b74285c43 bugfix python3-libdnf-0.63.1-1.fc34.x86_64
|
||||
FEDORA-2021-2056ce89d9 enhancement python3-libs-3.9.6-1.fc34.x86_64
|
||||
FEDORA-2021-d613e00b72 enhancement python3-libs-3.9.6-2.fc34.x86_64
|
||||
FEDORA-2021-07931f7f08 bugfix python3-setuptools-53.0.0-2.fc34.noarch
|
||||
FEDORA-2021-1db6330a22 unknown sssd-client-2.5.2-1.fc34.x86_64
|
||||
FEDORA-2021-3141f0eff1 bugfix systemd-248.6-1.fc34.x86_64
|
||||
FEDORA-2021-3141f0eff1 bugfix systemd-libs-248.6-1.fc34.x86_64
|
||||
FEDORA-2021-3141f0eff1 bugfix systemd-networkd-248.6-1.fc34.x86_64
|
||||
FEDORA-2021-3141f0eff1 bugfix systemd-pam-248.6-1.fc34.x86_64
|
||||
FEDORA-2021-3141f0eff1 bugfix systemd-rpm-macros-248.6-1.fc34.noarch
|
||||
FEDORA-2021-b8b1f6e54f enhancement vim-minimal-2:8.2.3182-1.fc34.x86_64
|
||||
FEDORA-2021-67645ae09f enhancement xkeyboard-config-2.33-1.fc34.noarch
|
||||
FEDORA-2021-3b74285c43 bugfix yum-4.8.0-1.fc34.noarch
|
||||
```
|
||||
|
||||
The output is in three columns. These show the ID for an update, the type of the update, and the package to which it refers.
|
||||
|
||||
If you want to see the Bodhi page for a specific update, just add the id to the end of this URL:
|
||||
<https://bodhi.fedoraproject.org/updates/>.
|
||||
|
||||
For example, <https://bodhi.fedoraproject.org/updates/FEDORA-2021-3141f0eff1> for _systemd-248.6-1.fc34.x86_64_ or <https://bodhi.fedoraproject.org/updates/FEDORA-2021-b09e010a46> for _coreutils-8.32-30.fc34.x86_64_.
|
||||
|
||||
The next command will list the actual changelog.
|
||||
|
||||
```
|
||||
dnf updateinfo info
|
||||
```
|
||||
|
||||
The output from this command is quite long. So only a few interesting excerpts are provided below.
|
||||
|
||||
Start with a small one:
|
||||
|
||||
```
|
||||
===============================================================================
|
||||
ca-certificates-2021.2.50-1.0.fc34
|
||||
===============================================================================
|
||||
Update ID: FEDORA-2021-1f32e18471
|
||||
Type: bugfix
|
||||
Updated: 2021-06-18 22:08:02
|
||||
Description: Update the ca-certificates list to the lastest upstream list.
|
||||
Severity: Low
|
||||
```
|
||||
|
||||
Notice how this info has the update ID, type, updated time, description and severity. Very simple and easy to understand.
|
||||
|
||||
Now look at the _systemd_ update which, in addition to the previous items, has some bugs associated with it in Red Hat Bugzilla, a more elaborate description, and a different severity.
|
||||
|
||||
```
|
||||
===============================================================================
|
||||
systemd-248.6-1.fc34
|
||||
===============================================================================
|
||||
Update ID: FEDORA-2021-3141f0eff1
|
||||
Type: bugfix
|
||||
Updated: 2021-07-24 22:00:30
|
||||
Bugs: 1963428 - if keyfile >= 1024*4096-1 service "systemd-cryptsetup@<partition name>" can't start
|
||||
: 1965815 - 50-udev-default.rules references group "sgx" which does not exist
|
||||
: 1975564 - systemd-cryptenroll SIGABRT when adding recovery key - buffer overflow
|
||||
: 1984651 - systemd[1]: Assertion 'a <= b' failed at src/libsystemd/sd-event/sd-event.c:2903, function sleep_between(). Aborting.
|
||||
Description: - Create 'sgx' group (and also use soft-static uids for input and render, see https://pagure.io/setup/c/df3194a7295c2ca3cfa923981b046f4bd2754825 and https://pagure.io/packaging-committee/issue/1078 (#1965815)
|
||||
: - Various bugfixes (#1963428, #1975564)
|
||||
: - Fix for a regression introduced in the previous release with sd-event abort (#1984651)
|
||||
:
|
||||
: No need to log out or reboot.
|
||||
Severity: Moderate
|
||||
```
|
||||
|
||||
Next look at a _curl_ update. This has a security update with several [CVE][5]s associated with it. Each CVE has its respective Red Hat Bugzilla bug.
|
||||
|
||||
```
|
||||
===============================================================================
|
||||
curl-7.76.1-7.fc34
|
||||
===============================================================================
|
||||
Update ID: FEDORA-2021-83fdddca0f
|
||||
Type: security
|
||||
Updated: 2021-07-22 22:03:07
|
||||
Bugs: 1984325 - CVE-2021-22922 curl: wrong content via metalink is not being discarded [fedora-all]
|
||||
: 1984326 - CVE-2021-22923 curl: Metalink download sends credentials [fedora-all]
|
||||
: 1984327 - CVE-2021-22924 curl: bad connection reuse due to flawed path name checks [fedora-all]
|
||||
: 1984328 - CVE-2021-22925 curl: Incorrect fix for CVE-2021-22898 TELNET stack contents disclosure [fedora-all]
|
||||
Description: - fix TELNET stack contents disclosure again (CVE-2021-22925)
|
||||
: - fix bad connection reuse due to flawed path name checks (CVE-2021-22924)
|
||||
: - disable metalink support to fix the following vulnerabilities
|
||||
: CVE-2021-22923 - metalink download sends credentials
|
||||
: CVE-2021-22922 - wrong content via metalink not discarded
|
||||
Severity: Moderate
|
||||
```
|
||||
|
||||
This item shows a simple enhancement update.
|
||||
|
||||
```
|
||||
===============================================================================
|
||||
python3-docs-3.9.6-1.fc34 python3.9-3.9.6-1.fc34
|
||||
===============================================================================
|
||||
Update ID: FEDORA-2021-2056ce89d9
|
||||
Type: enhancement
|
||||
Updated: 2021-07-08 22:00:53
|
||||
Description: Update of Python 3.9 and python3-docs to latest release 3.9.6
|
||||
Severity: None
|
||||
```
|
||||
|
||||
Finally an “unknown” type update.
|
||||
|
||||
```
|
||||
===============================================================================
|
||||
file-5.39-6.fc34
|
||||
===============================================================================
|
||||
Update ID: FEDORA-2021-07625b9c81
|
||||
Type: unknown
|
||||
Updated: 2021-06-11 22:16:57
|
||||
Bugs: 1963895 - Wrong detection of python bytecode mimetypes
|
||||
Description: do not classify python bytecode files as text (#1963895)
|
||||
Severity: None
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
|
||||
So, in what situation does dnf updateinfo become handy?
|
||||
|
||||
Well, you could use it if you prefer managing updates fully via the CLI, or if you are unable to successfully use the GUI tools at a specific moment.
|
||||
|
||||
In which case is checking the changelog useful?
|
||||
|
||||
Say you manage the updates yourself, sometimes you might not consider it ideal to stop what you are doing to update your system. Instead of simply installing the updates, you check the changelogs. This allows you to figure out whether you should prioritize your updates (maybe there’s a important security fix?) or whether to postpone a bit longer (no important fix, “I will do it later when I’m not doing anything important”).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://fedoramagazine.org/use-dnf-updateinfo-to-read-update-changelogs/
|
||||
|
||||
作者:[Mateus Rodrigues Costa][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://fedoramagazine.org/author/mateusrodcosta/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://fedoramagazine.org/wp-content/uploads/2021/08/dnf-updateinfo-816x345.jpg
|
||||
[2]: https://unsplash.com/@ffstop?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
|
||||
[3]: https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
|
||||
[4]: https://fedoramagazine.org/a-quick-introduction-to-toolbox-on-fedora/
|
||||
[5]: https://en.wikipedia.org/wiki/Common_Vulnerabilities_and_Exposures
|
@ -0,0 +1,138 @@
|
||||
[#]: subject: "What is SteamOS? Everything Important You Need to Know About This “Gaming Distribution”"
|
||||
[#]: via: "https://itsfoss.com/steamos/"
|
||||
[#]: author: "Ankush Das https://itsfoss.com/author/ankush/"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
What is SteamOS? Everything Important You Need to Know About This “Gaming Distribution”
|
||||
======
|
||||
|
||||
SteamOS is a Linux-based operating system that aims to provide a seamless gaming experience from Steam’s own game store.
|
||||
|
||||
While it has been in existence for about a decade now, there are a few things that you should know about it.
|
||||
|
||||
In this article, we try to address most of the common questions regarding SteamOS.
|
||||
|
||||
### What is SteamOS?
|
||||
|
||||
SteamOS is a Linux distribution from the game distribution platform Steam. It is not a generic desktop operating system like Debian, Linux Mint or Ubuntu though you could use the desktop features. By default, SteamOS gives you a console like interface because SteamOS is intended to be the operating system on Steam devices like Steam Machine (discontinued) and Steam Deck.
|
||||
|
||||
![SteamOS interface][1]
|
||||
|
||||
While you can install the Steam game client on any Linux distribution and other platforms, SteamOS was developed to provide a console-like experience to play games from the Steam store.
|
||||
|
||||
### Which Linux distribution SteamOS is based on?
|
||||
|
||||
SteamOS is a Linux-based operating system originally based on Debian 8. With Valve’s new [Steam Deck][2] handheld gaming device, SteamOS’s latest version (SteamOS 3.0) uses Arch Linux as its base because of its rolling-release update schedule.
|
||||
|
||||
The developers believe that Arch Linux as a base for SteamOS is useful to push quick updates and optimize SteamOS for Steam Deck.
|
||||
|
||||
![][3]
|
||||
|
||||
### System requirements for SteamOS
|
||||
|
||||
Ideally, any machine with the following minimum requirements should work:
|
||||
|
||||
* Intel or AMD 64-bit capable processor
|
||||
* 4GB or more memory
|
||||
* 250GB or larger disk
|
||||
* NVIDIA, Intel, or AMD graphics card
|
||||
* USB port or DVD drive for installation
|
||||
|
||||
|
||||
|
||||
### Will SteamOS Work on your PC?
|
||||
|
||||
SteamOS (version 2.0) comes with drivers and chipsets that support a specific set of hardware.
|
||||
|
||||
It should theoretically work on every PC, but there’s no official support for the latest and greatest hardware.
|
||||
|
||||
### Is SteamOS just another Linux distribution?
|
||||
|
||||
SteamOS is technically one of the [gaming Linux distributions][4] available. But, unlike some others, it is not meant for a full-fledged desktop experience. While you have the ability to install Linux applications, it supports a limited number of packages.
|
||||
|
||||
In short, it is not suitable to replace a desktop Linux OS.
|
||||
|
||||
### Is Steam OS Actively Maintained?
|
||||
|
||||
**Yes** and **No.**
|
||||
|
||||
SteamOS is based on Debian 8 for a long time now with no updates whatsoever.
|
||||
|
||||
So, if you are looking to install it on your personal machine, the version available to the public (SteamOS 2.0) is not actively maintained.
|
||||
|
||||
However, Valve is actively working on SteamOS 3.0 for its Steam Deck hardware. Hence, there is a possibility that you should find it available soon enough for your desktop.
|
||||
|
||||
### Should You Prefer SteamOS for PC Gaming?
|
||||
|
||||
**No.** SteamOS is not a proper replacement for Windows or other Linux distributions.
|
||||
|
||||
While it was primarily tailored to play games, there are many caveats to know before you proceed.
|
||||
|
||||
### Do all games work on SteamOS?
|
||||
|
||||
**No.** SteamOS relies on the Proton compatibility layer to make most of the Windows-exclusive games work.
|
||||
|
||||
Of course, [Gaming on Linux][5] has been made possible with the same underlying tech, but at the time of writing this, you cannot make all the games available in Steam work with it.
|
||||
|
||||
Even though many games should work on it, that does not guarantee that all games you have in your library will work as expected.
|
||||
|
||||
If you are looking to play supported games and Linux-only games, you can consider trying it.
|
||||
|
||||
### Is SteamOS open source?
|
||||
|
||||
**Yes** (SteamOS 2.0).
|
||||
|
||||
The operating system is open-source, and you can find the source code in its [official repo][6].
|
||||
|
||||
But, the Steam client that you will be using on it is proprietary.
|
||||
|
||||
It is worth noting that SteamOS 3.0 is still a work in progress. So, you cannot find the source code or any progress of it available to the public.
|
||||
|
||||
### Is SteamOS free to use?
|
||||
|
||||
You won’t find the new SteamOS version available to the public yet, but it is essentially free to use. The older version based on Debian is available to download from the [official site][7].
|
||||
|
||||
### Can I find a gaming system with SteamOS built in?
|
||||
|
||||
![Steam Machine console has been doscontinued][8]
|
||||
|
||||
SteamOS was originally created to be the operating system on Steam’s very own PlayStation/Xbox styled console called Steam Machine. Released around 2015, Steam Machine did not see much success and was eventually discontinued.
|
||||
|
||||
Now the only device to feature SteamOS is the much-anticipated Steam Deck.
|
||||
|
||||
If SteamOS is available to download for other hardware, you may see commercial choices to have SteamOS pre-installed with a gaming machine.
|
||||
|
||||
But, for now, you should not believe any claims by unknown manufacturers to offer SteamOS out of the box.
|
||||
|
||||
### Will Next-gen SteamOS Make Linux a Viable Choice for Gaming?
|
||||
|
||||
Absolutely. Yes.
|
||||
|
||||
Linux may not be the recommended choice for gamers out there. You can explore if [we recommend Linux for gaming][9]. Still, if SteamOS evolves to support every game for its Steam Deck hardware, desktop Linux users can finally experience all unsupported Steam games.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/steamos/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/08/steamos.jpg?resize=800%2C450&ssl=1
|
||||
[2]: https://www.steamdeck.com/en/
|
||||
[3]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2021/08/steam-deck.jpg?resize=800%2C479&ssl=1
|
||||
[4]: https://itsfoss.com/linux-gaming-distributions/
|
||||
[5]: https://itsfoss.com/linux-gaming-guide/
|
||||
[6]: https://repo.steampowered.com/steamos/
|
||||
[7]: https://store.steampowered.com/steamos/
|
||||
[8]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2021/08/valves-steam-machine.jpg?resize=800%2C441&ssl=1
|
||||
[9]: https://news.itsfoss.com/linux-for-gaming-opinion/
|
@ -0,0 +1,74 @@
|
||||
[#]: subject: (GNOME Web Canary is Now Available to Test Bleeding Edge Features)
|
||||
[#]: via: (https://news.itsfoss.com/gnome-web-canary/)
|
||||
[#]: author: (Ankush Das https://news.itsfoss.com/author/ankush/)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (zd200572)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
GNOME Web Canary现在可用于测试前沿功能
|
||||
======
|
||||
|
||||
Epiphany或[GNOME Web][1]是一个Linux发行版上最小但功能强大的浏览器,你会发现它是elementary OS的默认浏览器。
|
||||
|
||||
使用GNOME40,Epiphany浏览器有一些[改进和新增功能][2]。
|
||||
|
||||
在幕后,经常有许多令人兴奋的提升和新增特性。因此,你可以选择为早期测试人员量身定制的GNOME Web技术预览版。
|
||||
|
||||
现在,一个新的Canary版本发布了,你可以使用它来测试甚至在技术预览版中都没有的特性。
|
||||
|
||||
### GNOME Web Canary版本
|
||||
|
||||
![][3]
|
||||
|
||||
GNOME Web的“Canary”版本允许你测试甚至没有出现在最新[WebKitGTK][4]版本中的特性。
|
||||
|
||||
注意Canary版本应该是极其不稳定的,甚至稳定性比开发者技术预览版更差。
|
||||
|
||||
可是,使用Canary版本, 一个终端用户可以在开发过程中的早期进行测试,帮助开发者发现灾难性bugs。
|
||||
|
||||
不只是终端用户的早期测试,Canary版本还让GNOME Web开发者的工作更轻松。
|
||||
|
||||
他们不再需要为了实现和测试一个新特性,来单独构建WebKitGTK。
|
||||
|
||||
尽管开发者有一个Flatpak SDK可以简化开发人员的流程,但是这仍然是一项耗时的任务。
|
||||
|
||||
现在,没有了这个阻碍,开发速度也有可能提升。
|
||||
|
||||
### 怎样获得Canary版本?
|
||||
|
||||
首先,你需要使用以下命令添加WebKit SDK Flatpak remote:
|
||||
|
||||
```
|
||||
flatpak --user remote-add --if-not-exists webkit https://software.igalia.com/flatpak-refs/webkit-sdk.flatpakrepo
|
||||
flatpak --user install https://nightly.gnome.org/repo/appstream/org.gnome.Epiphany.Canary.flatpakref
|
||||
```
|
||||
|
||||
一旦完成,你就可以使用提供的[Flatpakref文件][5]安装啦!
|
||||
|
||||
测试一个Canary版本让更多的用户能够在此过程中帮助GNOME Web开发者的开发人员。所以,这绝对是改进GNOME Web浏览器开发的急需补充。
|
||||
|
||||
更多技术细节,你可能需要看一位开发者中发布的[公告][6]。
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://news.itsfoss.com/gnome-web-canary/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[zd200572](https://github.com/zd200572)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://news.itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://wiki.gnome.org/Apps/Web/
|
||||
[2]: https://news.itsfoss.com/gnome-web-new-tab/
|
||||
[3]: data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjY0MiIgd2lkdGg9Ijc4MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=
|
||||
[4]: https://webkitgtk.org
|
||||
[5]: https://nightly.gnome.org/repo/appstream/org.gnome.Epiphany.Canary.flatpakref
|
||||
[6]: https://base-art.net/Articles/introducing-the-gnome-web-canary-flavor/
|
105
translated/tech/20210608 Tune your MySQL queries like a pro.md
Normal file
105
translated/tech/20210608 Tune your MySQL queries like a pro.md
Normal file
@ -0,0 +1,105 @@
|
||||
[#]: subject: (Tune your MySQL queries like a pro)
|
||||
[#]: via: (https://opensource.com/article/21/5/mysql-query-tuning)
|
||||
[#]: author: (Dave Stokes https://opensource.com/users/davidmstokes)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (unigeorge)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
如老手一般玩转 MySQL 查询
|
||||
======
|
||||
优化查询语句不过是一项简单的工程,而非什么高深的黑魔法。
|
||||
![woman on laptop sitting at the window][1]
|
||||
|
||||
许多人将数据库查询语句的调优视作哈利波特小说中某种神秘的“黑魔法”;使用错误的咒语,数据就会从宝贵的资源变成一堆糊状物。
|
||||
|
||||
实际上,对关系数据库系统的查询调优是一项简单的工程,其遵循的规则或启发式方法很容易理解。查询优化器会将你发送的查询指令转换为 [MySQL][2] 实例,然后将这些启发式方法和优化器已知的数据信息结合使用,确定获取所请求数据的最佳方式。再读一下最后一部分:_“优化器已知的数据信息_。”查询优化器需要对数据所在位置的猜测越少(即已知信息越多),它就可以越好地制定交付数据的计划。
|
||||
|
||||
为了让优化器更好地了解数据,你可以考虑使用索引和直方图。正确使用索引和直方图可以大大提高数据库查询的速度。这就像如果你按照食谱做菜,就可以得到你喜欢吃的东西;但是假如你随意在该食谱中添加材料,最终得到的东西可能就不那么尽如人意了。
|
||||
|
||||
### 基于成本的优化器
|
||||
|
||||
大多数现代关系型数据库使用基于成本的优化器(cost-based optimizer)来确定如何从数据库中检索数据。该成本方案是基于尽可能减少非常耗费资源的磁盘读取过程。数据库服务器上的查询优化器代码会在遇到数据时保留有关获取该数据的统计信息,并构建获取数据所需时间的历史模型。
|
||||
|
||||
但历史数据是可能会过时的。这就好像你去商店买你最喜欢的零食,然后突然发现零食涨价或者商店关门了。服务器的优化进程可能会根据旧信息做出错误的假设,进而制定出低效的查询计划。
|
||||
|
||||
查询的复杂性可能会影响优化。优化器希望提供可用的最低成本查询方式。连接五个不同的表就意味着有 5 的阶乘即 120 种可能的连接顺序组合。代码中内置了启发式方法,以尝试对所有可能的选项进行快捷评估。 MySQL 每次看到查询时都希望生成一个新的查询计划,而其他数据库(例如 Oracle)则可以锁定查询计划。这就是向优化器提供有关数据的详细信息至关重要的原因。要想获得稳定的性能,在制定查询计划时为查询优化器提供最新信息确实很有效。
|
||||
|
||||
此外,优化器中内置的规则可能与数据的实际情况并不相符。没有更多有效信息的情况下,查询优化器会假设列中的所有数据均匀分布在所有行中。没有其他选择依据时,它会默认选择两个可能索引中较小的一个。虽然基于成本的优化器模型可以制定出很多好的决策,但最终查询计划并不是最佳方案的情况也是有可能的。
|
||||
|
||||
### 查询计划是神马?
|
||||
|
||||
查询计划(query plan)是指优化器基于查询语句产生的,提供给服务器执行的计划内容。查看查询计划的方法是在查询语句前加上 `EXPLAIN` 关键字。例如,以下查询要从城市表(city)和相应的国家表(country)中获得城市名称(和所属国家名称),城市表和国家表通过国家唯一代码连接。本例中仅查询了英国的字母顺序前五名的城市:
|
||||
|
||||
```
|
||||
SELECT city.name AS 'City',
|
||||
country.name AS 'Country'
|
||||
FROM city
|
||||
JOIN country ON (city.countrycode = country.code)
|
||||
WHERE country.code = 'GBR'
|
||||
LIMIT 5;
|
||||
```
|
||||
|
||||
在查询语句前加上 `EXPLAIN` 可以看到优化器生成的查询计划。跳过除输出末尾之外的所有内容,可以看到优化后的查询:
|
||||
|
||||
```
|
||||
SELECT `world`.`city`.`Name` AS `City`,
|
||||
'United Kingdom' AS `Country`
|
||||
FROM `world`.`city`
|
||||
JOIN `world`.`country`
|
||||
WHERE (`world`.`city`.`CountryCode` = 'GBR')
|
||||
LIMIT 5;
|
||||
```
|
||||
|
||||
看下比较大的几个变化, `country.name as 'Country'` 改成了 `'United Kingdom' AS 'Country'`,`WHERE` 子句从在国家表中查找变成了在城市表中查找。优化器认为这两个改动会提供比原始查询更快的结果。
|
||||
|
||||
### 索引
|
||||
|
||||
在MySQL世界中,你会听到索引或键的概念。不过,索引是由键组成的,键是一种识别记录的方式,并且大概率是唯一的。如果将列设计为键,优化器可以搜索这些键的列表以找到所需的记录,而无需读取整个表。如果没有索引,服务器必须从第一列的第一行开始读取每一行数据。如果该列是作为唯一索引创建的,则服务器可以直接读取该行数据并忽略其余数据。索引的值(也称为基数)唯一性越强越好。请记住,我们在寻找更快获取数据的方法。
|
||||
|
||||
MySQL 默认的 InnoDB 存储引擎希望你的表有一个主键,并将通过该键将你的数据存储在 B+ 树中。不可见列是 MySQL 最近添加的功能——除非在查询中明确指明该不可见列,否则不会返回该列数据。例如,`SELECT * FROM foo;` 就不会返回任何不可见列。这个功能提供了一种向旧表添加主键的方法,且无需为了包含该新列而重写所有查询语句。
|
||||
|
||||
更复杂的是,有多种类型的索引,例如函数索引、空间索引和复合索引。甚至在某些情况下,你还可以创建这样一个索引:该索引可以为查询提供所有请求的信息,从而无需再去访问数据表。
|
||||
|
||||
本文不会详细讲解各种索引类型,你只需将索引看作指向要查询的数据记录的快捷方式。你可以在一个或多个列或这些列的一部分上创建索引。我的医师系统就可以通过我姓氏的前三个字母和出生日期来查找我的记录。使用多列时要注意首选唯一性最强的字段,然后是第二强的字段,依此类推。年-月-日的索引可用于年-月-日、年-月和年搜索,但不适用于日、月-日或年-日搜索。考虑这些因素有助于你围绕如何使用数据这一出发点来设计索引。
|
||||
|
||||
### 直方图
|
||||
|
||||
直方图就是数据的分布式。如果你将人名按其姓氏的字母顺序排序,就可以对姓氏以字母 A 到 F 开头的人放到一个“逻辑桶”中,然后将 G 到 J 开头的放到另一个中,依此类推。优化器会假定数据在列内均匀分布,但实际使用时多数情况并不是均匀的。
|
||||
|
||||
MySQL 提供两种类型的直方图:所有数据在桶中平均分配的等高型,以及单个值在单个桶中的等宽型。最多可以设置 1,024 个存储桶。 数据存储桶数量的选择取决于许多因素,包括去重后的数值量、数据倾斜度以及需要的结果准确度。如果桶的数量超过某个阈值,桶机制带来的收益就会开始递减。
|
||||
|
||||
以下命令将在表 t 的列 c1 上创建 10 个桶的直方图:
|
||||
|
||||
```
|
||||
ANALYZE TABLE t UPDATE HISTOGRAM ON c1 WITH 10 BUCKETS;
|
||||
```
|
||||
|
||||
想象一下你在售卖小号、中号和大号袜子,每种尺寸的袜子都放在单独的储物箱中。如果你想找某个尺寸的袜子,就可以直接去对应尺寸的箱子里找。MySQL 自从三年前发布 MySQL 8.0 以来就有了直方图功能,但该功能却并没有像索引那样广为人知。与索引不同,使用直方图插入、更新或删除记录都不会产生额外开销。而如果更新索引,就必须更新 `ANALYZE TABLE` 命令。 当数据变动不大并且频繁更改数据会降低效率时,直方图是一种很好的方法。
|
||||
|
||||
### 选择索引还是直方图?
|
||||
|
||||
对需要直接访问的且具备唯一性的数据项目使用索引。虽然修改、删除和插入操作会产生额外开销,但如果数据架构正确,索引就可以方便你快速访问。对不经常更新的数据则建议使用直方图,例如过去十几年的季度结果。
|
||||
|
||||
### 结语
|
||||
|
||||
本文源于最近在 [Open Source 101 会议][3] 上的一次报告。报告的演示文稿源自 [PHP UK Conferenc][4] 的研讨会。查询调优是一个复杂的话题,每次我就索引和直方图作报告时,我都会找到新的可改进点。但是每次报告反馈也表明很多软件界中的人并不精通索引,并且时常使用错误。我想直方图大概由于出现时间较短,还没有出现像索引这种使用错误的情况。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/5/mysql-query-tuning
|
||||
|
||||
作者:[Dave Stokes][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[unigeorge](https://github.com/unigeorge)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/davidmstokes
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/lenovo-thinkpad-laptop-window-focus.png?itok=g0xPm2kD (young woman working on a laptop)
|
||||
[2]: https://www.mysql.com/
|
||||
[3]: https://opensource101.com/
|
||||
[4]: https://www.phpconference.co.uk/
|
@ -1,95 +0,0 @@
|
||||
[#]: subject: (5 useful ways to manage Kubernetes with kubectl)
|
||||
[#]: via: (https://opensource.com/article/21/7/kubectl)
|
||||
[#]: author: (Alan Smithee https://opensource.com/users/alansmithee)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: (turbokernel)
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
用 kubectl 管理 Kubernetes 的 5 种有用方法
|
||||
======
|
||||
学习kubectl,提升你与 Kubernetes 的互动方式。
|
||||
![Ship captain sailing the Kubernetes seas][1]
|
||||
|
||||
Kubernetes 可以帮你编排运行大量容器的软件。Kubernetes 不仅提供工具来管理(或[编排][2])运行的容器,还帮助这些容器根据需要进行扩展。有了 Kubernetes 作为你的中央控制平台(或称 _control plane_),你需要一种方式来管理 Kubernetes,而这项工作的工具就是 kubectl。`kubectl` 命令让你控制、维护、分析和排查 Kubernetes 集群的故障。与许多使用 `ctl`(“控制”的缩写)后缀的工具一样,如 systemctl 和 sysctl,kubectl 拥有大量的功能和任务权限,所以如果你正在运行 Kubernetes,你最终会经常使用它。它是一个拥有众多选项的命令,所以下面是 kubectl 中简单易用的五个常见任务。
|
||||
|
||||
### 1\. 列出并描述资源
|
||||
|
||||
按照设计,容器往往会成倍增加。在某些条件下,它们可以快速增加。如果你只能通过 `podman ps`或 `docker ps` 来查看正在运行的容器,这可能会让你不知所措。通过 `kubectl get` 和 `kubectl describe`,你可以列出正在运行的 pod 以及它们正在处理的容器信息。更重要的是,你可以通过使用 `--namespace` 或 `name` 或 `--selector`等选项,只列出所需信息。
|
||||
|
||||
`get` 子命令不仅仅对 pod 和容器有用。它有关于节点、命名空间、发布、服务和副本的信息。
|
||||
|
||||
### 2\. 创建资源
|
||||
|
||||
如果你只通过类似 OpenShift、OKD 或 Kubernetes 提供的 Web 用户界面(UI)创建过发布,但你想从 Linux 终端控制你的集群,那么可以使用 `kubectl create`。`kubectl create` 命令并不只是实例化一个新的应用发布。Kubernetes 中还有很多其他组件可以创建,比如服务、配额和 [计划任务][3]。
|
||||
|
||||
Kubernetes 中的计划任务可以创建一个临时的 pod,用来在你选择的时间表上执行一些任务。它们并不难设置。下面是一个计划任务,让一个 BusyBox 镜像每分钟打印 “hello world”。
|
||||
|
||||
|
||||
```
|
||||
$ kubectl create cronjob \
|
||||
hello-world \
|
||||
\--image=busybox \
|
||||
\--schedule="*/1 * * * *" -- echo "hello world"
|
||||
```
|
||||
|
||||
### 3\. 编辑文件
|
||||
|
||||
Kubernetes 中的对象都有相应的配置文件,但在文件系统中查找相应的文件较为麻烦。有了 `kubectl edit`,你可以把注意力放在对象上,而不是定义文件上。你可以通过 `kubectl` 找到并打开文件(关联 `KUBE_EDITOR` 环境变量,你可以设置成你喜欢的编辑器)。
|
||||
|
||||
|
||||
```
|
||||
$ KUBE_EDITOR=emacs \
|
||||
kubectl edit cronjob/hello-world
|
||||
```
|
||||
|
||||
### 4\. 容器之间的传输文件
|
||||
|
||||
初次接触容器的人往往对无法直接访问的共享系统的概念感到困惑。他们可能会在容器引擎或 kubectl 中了解到 `exec` 选项,但当他们不能从容器中提取文件或将文件放入容器中时,容器仍然会显得不透明。使用 `kubectl cp` 命令,你可以把容器当做远程服务器,使主机和容器之间文件传输如 SSH 命令一样简单:
|
||||
|
||||
|
||||
```
|
||||
`$ kubectl cp foo my-pod:/tmp`
|
||||
```
|
||||
|
||||
### 5\. 应用变更
|
||||
|
||||
对 Kubernetes 对象进行修改,可以通过 `kubectl apply` 命令完成。你所要做的就是将该命令指向一个配置文件:
|
||||
|
||||
|
||||
```
|
||||
`$ kubectl apply -f ./mypod.json`
|
||||
```
|
||||
|
||||
类似于运行 Ansible playbook 或 Bash 脚本,`apply` 使得快速“导入”设置到运行中的 Kubernetes 实例很容易。例如,GitOps 工具 [ArgoCD][4] 由于 `apply` 子命令,安装起来出奇地简单:
|
||||
|
||||
|
||||
```
|
||||
$ kubectl create namespace argocd
|
||||
$ kubectl apply -n argocd \
|
||||
-f <https://raw.githubusercontent.com/argoproj/argo-cd/vx.y.z/manifests/install.yaml>
|
||||
```
|
||||
|
||||
### 使用 kubectl
|
||||
|
||||
Kubectl 是一个强大的工具,由于它是一个终端命令,它可以写成脚本,并能实现用众多 Web UI 无法实现的功能。学习 kubectl 是进一步了解 Kubernetes、容器、pod 以及围绕这些重要的云计算创新技术的一个好方法。[下载我们的 kubectl 速查表][5],以获得快速参考,其中包括命令示例,以帮助你学习,并在为你提供注意细节。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/7/kubectl
|
||||
|
||||
作者:[Alan Smithee][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[turbokernel](https://github.com/turbokernel)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/alansmithee
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/ship_captain_devops_kubernetes_steer.png?itok=LAHfIpek (Ship captain sailing the Kubernetes seas)
|
||||
[2]: https://opensource.com/article/20/11/orchestration-vs-automation
|
||||
[3]: https://opensource.com/article/20/11/kubernetes-jobs-cronjobs
|
||||
[4]: https://argoproj.github.io/argo-cd/
|
||||
[5]: https://opensource.com/downloads/kubectl-cheat-sheet
|
@ -1,52 +0,0 @@
|
||||
[#]: subject: (Move files in the Linux terminal)
|
||||
[#]: via: (https://opensource.com/article/21/8/move-files-linux)
|
||||
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
||||
在 Linux 终端中移动文件
|
||||
======
|
||||
使用 mv 命令将一个文件从一个位置移动到另一个位置。
|
||||
![Moving files][1]
|
||||
|
||||
要在有图形界面的计算机上移动一个文件,你要打开该文件当前所在的文件夹,然后打开另一个窗口到你想把文件移到的文件夹。最后,你把文件从一个窗口拖到另一个窗口。
|
||||
|
||||
要在终端中移动文件,你可以使用 **mv** 命令将文件从一个位置移动到另一个位置。
|
||||
|
||||
|
||||
```
|
||||
$ mv example.txt ~/Documents
|
||||
|
||||
$ ls ~/Documents
|
||||
example.txt
|
||||
```
|
||||
|
||||
在这个例子中,你已经把 **example.txt** 从当前文件夹移到了 **Documents** 文件夹中。
|
||||
|
||||
只要你知道一个文件在__哪里__,又想把它移到_哪里_去,你就可以把文件从任何地方移动到任何地方,而不管你在哪里。与在一系列窗口中浏览你电脑上的所有文件夹以找到一个文件,然后打开一个新窗口到你想让该文件去的地方,再拖动该文件相比,这可以大大节省时间。
|
||||
|
||||
默认情况下,**mv** 命令完全按照它被告知的那样做:它将一个文件从一个位置移动到另一个位置。如果在目标位置已经存在一个同名的文件,它将被覆盖。为了防止文件在没有警告的情况下被覆盖,请使用 **\--interactive**(或简写 **-i**)选项。
|
||||
|
||||
|
||||
```
|
||||
$ mv -i example.txt ~/Documents
|
||||
mv: overwrite '/home/tux/Documents/example.txt'?
|
||||
```
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/8/move-files-linux
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/ch01s05.svg_.png?itok=PgKQEDZ7 (Moving files)
|
Loading…
Reference in New Issue
Block a user