分类 技术 下的文章

你可以在 VirtualBox 中的虚拟机上使用立付 Linux USB。这样可以省去重新启动主机的麻烦。

你有一个 立付 Live Linux USB 吗?在当前系统上测试它的常用方法是重新启动,并在系统重新启动时选择从立付 USB 启动。

但这很烦人,因为你需要停止计算机上的工作并重新启动它。

一种干扰较小的方法是使用虚拟机。

是的,你可以使用 VirtualBox 从虚拟机中的 USB 启动。这样,你不必为了尝试而在 VM 中安装发行版,而是改用立付会话。

在本教程中,我将展示在 Linux 系统使用 VirtualBox 从 USB 驱动器启动的步骤。这需要花费一些时间和精力,但可以让你免于重启系统。

在 Linux 的 VirtualBox 中从 USB 驱动器启动

由于这是针对高级用户的教程,因此我省略了你事先需要的几个步骤:

本指南分为三个部分:

  • 创建虚拟机磁盘文件
  • 在 VM 中使用 USB 启动
  • 删除虚拟机磁盘(可选)

那么让我们从第一个开始。

步骤 1:创建虚拟机磁盘文件(VMDK)

首先,你需要识别 USB 驱动器的磁盘名称,为此,你需要 列出系统的驱动器

为此,我将使用 lsblk 命令:

lsblk

? 确保使用不带任何数字的磁盘名称。就我而言,Ventoy 以 sdb1 命名,但我仍然只能使用 sdb。

从上图中,你可以看到,Ventoy 列出了 sdb11,但你必须使用不带任何数字的名称。这意味着我必须只使用 sdb,否则,它会抛出错误。

找到驱动器名称后,使用以下命令中的 VBoxManage 命令来创建:

sudo VBoxManage createmedium disk --filename=/path/to/rawdisk.vmdk --variant=RawDisk --format=VMDK --property RawDrive=/dev/sda

在上面的命令中,将 /path/to/rawdisk.vmdk 替换为要保存文件的路径 ,将 /dev/sda 替换为目标驱动器。

就我而言,我想在我的主目录中创建一个名为 IF.vmdk 的文件,并且我的目标驱动器是 /dev/sdb,然后,我将使用以下命令:

? 你需要提供绝对路径来创建 vmdk 文件!
sudo VBoxManage createmedium disk --filename=/home/sagar/IF.vmdk --variant=RawDisk --format=VMDK --property RawDrive=/dev/sdb

最后,使用 chmod 命令更改权限:

sudo chmod 777 Filename.vmdk

步骤 2:在 Linux 的 VirtualBox 中从 USB 启动

首先,从系统菜单中打开 VirtualBox,然后单击 “ 新建 New ” 按钮。

在那里,为你的虚拟机命名并选择操作系统类型及其版本:

现在,单击 “ 下一步 Next ” 按钮,它会要求你为虚拟机分配硬件资源:

完成硬件资源分配后,单击“下一步”按钮。

在这里,你将找到创建或添加虚拟磁盘的选项。现在,请执行 3 个简单步骤:

  • 选择第二个选项 “ 使用现有虚拟硬盘文件 Use an Existing Virtual Hard Disk File ”。
  • 点击“文件”图标。
  • 点击“ 添加 Add ”按钮并选择你最近创建的以 .vmdk 结尾的文件。

选择文件后,它将显示文件的名称,选择它并点击 “ 选择 Choose ” 选项:

它将向你显示已选择从中启动的文件。单击下一步,它将显示你所做的选择的摘要。

点击 “ 完成 Finish ” 按钮:

就是这样! 虚拟机已创建。

要启动虚拟机,首先选择虚拟机并单击启动按钮:

由于我的 USB 有 Ventoy,你可以看到,此处列出了多个发行版:

很酷。是么?

步骤 3:使用删除虚拟机及 vmdk 文件(可选)

当我在删除虚拟机后尝试删除 vmdk 文件时,当然,它被删除了,但每当我尝试创建具有相同名称的新文件时,它都会给我一个错误,说该文件已经存在!

因此,在这里,我将引导你了解如何删除虚拟机及 vmdk 文件。

首先,关闭虚拟机并将其删除。

现在,如果你尝试 使用 rm 命令 并提升权限删除 vmdk 文件,你可以删除它(但这就是幻觉的开始)。

例如,在这里,我删除了 IF.vmdk 文件:

sudo rm IF.vmdk

现在,如果我尝试创建一个具有相同名称的新 vmdk 文件,则会出现错误,指出该文件已存在:

要删除 vmdk 文件,首先,你必须使用以下命令取消注册该文件:

sudo VBoxManage closemedium disk /path/to/MyDrive.vmdk

完成后,你可以使用 rm 命令删除该文件,它将轻松删除:

sudo rm Filename.vmdk

然后,如果你尝试创建具有相同文件名的 vmdk 文件,你可以这样做:

这就行了!

更多虚拟机技巧

如果你正在寻找最快的 VM,可以使用 Qemu + KVM 的组合。我知道这听起来很复杂。

但为了更简单一些,我们制作了一份关于如何在 Ubuntu 上安装和使用 Qemu 的专门指南,包括启用共享文件夹、剪贴板和自动调整大小:

如何在 Ubuntu 上安装和使用 Qemu

我希望本指南对你有所帮助。

(题图:MJ/f74a3b33-2bcf-445b-8868-1dfc420f5b9d)


via: https://itsfoss.com/virtualbox-boot-from-usb/

作者:Sagar Sharma 选题:lujun9972 译者:geekpi 校对:wxy

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

Fedora 39 即将热门登场!在你进行安装前,先在这里了解一下新的功能。

Fedora 38 的升级引人瞩目,带来了全新的定制版,同时可以无限制地访问 Flathub。

如今,我们再次迎来升级,也就是 Fedora 39

如果一切按计划进行,Fedora 39 将在 2023 年 10 月 17 日 正式发布。然而,这次有何新奇特性呢?

一起来探索一下!

Fedora 39:重要亮点

在 Fedora 39 中,你能期待一些值得关注的更新和变化,以及其他一些内容。

其主要改进包括:

  • GNOME 45
  • Fedora Onyx 定制版
  • 彩色 Bash 提示符
  • 应用程序更新
  • 性能优化

彩色 Bash 提示符

Bash 提示符有了微小修改,改变了默认配色。

过往的单色默认配色与长命令的输出在视觉上容易混淆,现在,这种区分就容易多了。

当然,你也可以根据个人喜好,随意更改提示符的颜色。

GNOME 45

GNOME 45 是本次升级的一大亮点。

Ubuntu 23.10 一样,Fedora 39 也将是首批搭载 GNOME 45 的发行版之一。

GNOME 45 带来了大量实用的改动,以及一些微妙的视觉整改。

一些关键亮点包括:

  • 新增的核心应用
  • 系统设置新增的“ 关于 About ”面板
  • 系统设置中的隐私中心
  • 对 Nautilus 文件管理器的改善

对文件管理器的性能优化应会带来显著提升。

重新设计的简洁的侧边栏使得文件与文件夹区域的区分比以往更为明显。

左侧(GNOME 44),右侧(GNOME 45)

引入的核心应用,如 “ 放大镜图像查看器 Loupe Image Viewer ” 和 “ 快照 Snapshot ”,应当大有用处。这是一个简单且极简的图片查看器,以及一款网络摄像头应用。然而,Fedora 39 仍坚持使用较为经典的 “ 茄子 Cheese ” 网络摄像头应用。

不仅新增了应用,已有的核心应用也进行了很多优化,例如“ 日历 Calendar ”应用有了新的应用图标,“ 控制台 Console ”应用和“ 天气 Weather ”应用的用户体验也得到了提升。

设置 Settings ”菜单在呈现信息方式上也进行了升级,目的在于更好地为最终用户呈现信息。

在 “ 关于 About ” 面板,新增了一个 “ 系统详情 System Details ”,在此你可以获取到你正在运行的系统详细信息以及其硬件规格。

尽管在 Fedora 等 Linux 发行版中,隐私保护已经非常可靠,但 GNOME 45 给我们带来了更深一步的改进。

这些选项既便于快速访问,对于初次接触 Linux 的用户来说,也易于理解。

当然,GNOME 45 还有更多的亮点,你可以在我们的 GNOME 45 特性 专题文章中详细略览:

GNOME 45 带来令人兴奋的升级: 新功能介绍

Fedora Onyx

Fedora 提供的 Silverblue 变体,被公认为 最优秀的不可变发行版 之一,其桌面环境采用的是 GNOME。

为了拓宽其产品线,Joshua Strobl 提出新增一款采用 Budgie 桌面环境的不可变版本,以此补充 Budgie 定制版,即 Fedora Onyx

在 Fedora 39 的新版本发布时,你应可以找到这个全新的版本。

11 个面向未来、不可改变的 Linux 发行版

默认废弃 fedora-repos-modular

Fedora 带有几个已预先启用的存储库,让你可以顺畅地安装软件包。

然而,根据开发者的观察,现在大多数用户并不使用模块化的存储库。因此,移除这些存储库将有助于提升 DNF 的性能。

? DNF 是 Fedora 的 软件包管理器

因此,预计在默认不再包含 fedora-repos-modular 存储库的情况下,DNF 特别是在网络环境较差的情况下,其性能会得到一些改善。

应用和软件包更新

以下是最主要的应用程序更新:

  • LibreOffice 7.6
  • Python 3.12
  • RPM 4.19
  • Vagrant 2.3
  • Perl 5.38
  • LLVM 17
  • Golang 1.21
  • FontAwesome6

其它改进

虽然安装程序基本无变化(Anaconda Web UI 的 目标 是 Fedora 40),但是新的“ 欢迎屏 Welcome Screen ”在帮助你开始使用时会提供些许便利。

为了提供更好的用户体验,Fedora 39 加入了多项改进。

其中包括:

  • Fedora Workstation 不再对 Qt 进行定制主题设计:Qt 应用将遵循 Qt 上游的默认主题设置。
  • Fedora Kinoite 变体启用自动更新
  • 改变 Fedora 中的 Flatpak 构建方式(不用模块)

更多细节改进,你可以在其 官方变更集维基 上查看。

? 你对 Fedora 39 有怎样的期待?这是否对你将是一个重要的升级,或者只是类似常规新版本发布?


via: https://news.itsfoss.com/fedora-39-features/

作者:Ankush Das 选题:lujun9972 译者:ChatGPT 校对:wxy

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

扩展 VxFX 文件系统是 Linux/Unix 管理员的一项日常任务,可以通过以下文章中描述的几个步骤在线完成此任务:

在此,磁盘组没有足够的可用空间,因此我们将在现有磁盘组(DG)中添加新磁盘,然后调整其大小。

相关文章:

步骤 1:识别文件系统

使用 df 命令 检查要增加/扩展的文件系统,并记下以下输出中的磁盘组(DG)和卷名称,稍后在运行 vxdgvxresize 命令时将使用这些名称。

# df -hP /data

Filesystem                  Size  Used Avail Use% Mounted on
/dev/vx/dsk/testdg/testvol  9.0G  8.4G 0.6G  95%  /data

根据上面的输出,VxFS 文件系统大小为 9.0 GB,我们希望额外扩展 5 GB 并发布此活动,VxFS 大小将为 14 GB。

在本例中,DG 名称为 testdg,卷名称为 testvol

步骤 2:获取新磁盘/LUN

新磁盘必须由存储团队映射到主机,这可能需要 CR 批准,因此提出 CR 并向相关团队添加必要的任务,并且还包括此活动的回滚计划。

步骤 3:扫描磁盘/LUN

存储团队将新 LUN 映射到主机后,获取 LUN id 并将其保存。

使用以下命令扫描 LUN 以在操作系统级别发现它们。

for disk_scan in `ls /sys/class/scsi_host`; do 
    echo "Scanning $disk_scan…Completed"
    echo "- - -" > /sys/class/scsi_host/$disk_scan/scan
done
Scanning host0...Completed
Scanning host1...Completed
.
.
Scanning host[N]...Completed

扫描完成后,使用以下命令查看是否在操作系统级别找到给定的 LUN。

lsscsi --scsi | grep -i [Last_Five_Digit_of_LUN]

步骤 4:在 VxVM 中查找磁盘

默认情况下,所有可用磁盘对 Veritas 卷管理器(VxVM)都是可见的,可以使用 vxdisk 命令列出这些磁盘,如下所示。

# vxdisk -e list

DEVICE       TYPE           DISK        GROUP        STATUS               OS_NATIVE_NAME   ATTR
emc_01       auto:cdsdisk   disk1       testdg       online               sdd              -
emc_02       auto:cdsdisk   disk2       testdg       online               sde              -
emc_03       auto:none      -           -            online invalid       sdf              -
sda          auto:LVM       -           -            LVM                  sda              -
sdb          auto:LVM       -           -            LVM                  sdb              -

磁盘 sdf 的状态显示为 Online invalid 表示该磁盘不受 VxVM 控制。但是,请使用 smartctl 命令仔细检查 LUN id,以确保你选择了正确的磁盘。

smartctl -a /dev/sd[x]|grep -i unit

如果磁盘未填充到 VxVM,请执行以下命令扫描操作系统设备树中的磁盘设备。

vxdisk scandisks

步骤 5:在 VxVM 中初始化磁盘

当磁盘在步骤 4 中对 VxVM 可见,那么使用 vxdisksetup 命令初始化磁盘,如下所示:

vxdisksetup -i sdf

上面的命令将磁盘 sdf 带到 Veritas 卷管理器(VxVM),并且磁盘状态现在更改为 online

步骤 6:将磁盘添加到 VxVM 中的磁盘组(DG)

vxdg 命令对磁盘组执行各种管理操作。在此示例中,我们将使用它向现有磁盘组(DG)添加新磁盘。

vxdg -g [DG_Name] adddisk [Any_Name_to_Disk_as_per_Your_Wish=Device_Name]
vxdg -g testdg adddisk disk3=emc_03

运行上述命令后,磁盘名称为 disk3 且磁盘组名称为 testdg 已针对 emc_03 设备进行更新 如下所示:

# vxdisk -e list

DEVICE       TYPE           DISK        GROUP        STATUS               OS_NATIVE_NAME   ATTR
emc_01       auto:cdsdisk   disk1       testdg       online               sdd              -
emc_02       auto:cdsdisk   disk2       testdg       online               sde              -
emc_03       auto:none      disk3       testdg       online               sdf              -
sda          auto:LVM       -           -            LVM                  sda              -
sdb          auto:LVM       -           -            LVM                  sdb              -

步骤 7:检查磁盘组(DG)中的可用空间

要确定连接卷有多少可用空间,请运行:

vxassist -g testdg maxsize

步骤 8:扩展 VxVM 卷和 VxFS 文件系统

我们为此活动添加了 5GB LUN,因此额外扩展了 VxVM 卷和 VxFS 文件系统 5GB,如下所示:

vxresize -b -g [DG_Name] [Volume_Name] +[Size_to_be_Increased]
vxresize -b -g testdg testvol +5g

这里:

  • vxresize:命令
  • -b:在后台执行调整大小操作(可选)。
  • -g:将命令的操作限制为给定磁盘组,由磁盘组 ID 或磁盘组名称指定。
  • testdg:我们的磁盘组(DG)名称
  • testvol`:我们的卷名称
  • +5g:此卷将额外增加 5GB。

步骤 9:检查扩展 VxFS 文件系统

最后,使用 df 命令检查 /data 的扩展 VxFS:

# df -hP /data

Filesystem                  Size  Used Avail Use% Mounted on
/dev/vx/dsk/testdg/testvol  14G   8.4G 5.6G  68%  /data

总结

在本教程中,我们向你展示了如何向现有磁盘组(DG)添加新磁盘,以及如何通过几个简单步骤在 Linux 中扩展 VxVM 卷和 VxFS 文件系统。

如果你有任何问题或反馈,请随时在下面发表评论。

(题图:MJ/3fe4fdb7-99da-4b8f-a818-0ae232e6fbcc)


via: https://www.2daygeek.com/extend-increase-vxvm-volume-vxfs-filesystem-linux/

作者:Jayabal Thiyagarajan 选题:lujun9972 译者:geekpi 校对:wxy

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

大家好!今天我和一个朋友讨论 Git 的工作原理,我们感到奇怪,Git 是如何存储你的文件的?我们知道它存储在 .git 目录中,但具体到 .git 中的哪个位置,各个版本的历史文件又被存储在哪里呢?

以这个博客为例,其文件存储在一个 Git 仓库中,其中有一个文件名为 content/post/2019-06-28-brag-doc.markdown。这个文件在我的 .git 文件夹中具体的位置在哪里?过去的文件版本又被存储在哪里?那么,就让我们通过编写一些简短的 Python 代码来探寻答案吧。

Git 把文件存储在 .git/objects 之中

你的仓库中,每一个文件的历史版本都被储存在 .git/objects 中。比如,对于这个博客,.git/objects 包含了 2700 多个文件。

$ find .git/objects/ -type f | wc -l
2761
注意:.git/objects 包含的信息,不仅仅是 “仓库中每一个文件的所有先前版本”,但我们暂不详细讨论这一内容。

这里是一个简短的 Python 程序(find-git-object.py),它可以帮助我们定位在 .git/objects 中的特定文件的具体位置。

import hashlib
import sys

def object_path(content):
    header = f"blob {len(content)}\0"
    data = header.encode() + content
    sha1 = hashlib.sha1()
    sha1.update(data)
    digest = sha1.hexdigest()
    return f".git/objects/{digest[:2]}/{digest[2:]}"

with open(sys.argv[1], "rb") as f:
    print(object_path(f.read()))

此程序的主要操作如下:

  • 读取文件内容
  • 计算一个头部(blob 16673\0),并将其与文件内容合并
  • 计算出文件的 sha1 校验和(此处为 e33121a9af82dd99d6d706d037204251d41d54
  • 将这个 sha1 校验和转换为路径(如 .git/objects/e3/3121a9af82dd99d6d706d037204251d41d54

运行的方法如下:

$ python3 find-git-object.py content/post/2019-06-28-brag-doc.markdown
.git/objects/8a/e33121a9af82dd99d6d706d037204251d41d54

术语解释:“内容寻址存储”

这种存储策略的术语为“ 内容寻址存储 content addressed storage ”,它指的是对象在数据库中的文件名与文件内容的哈希值相同。

内容寻址存储的有趣之处就是,假设我有两份或许多份内容完全相同的文件,在 Git 的数据库中,并不会因此占用额外空间。如果内容的哈希值是 aabbbbbbbbbbbbbbbbbbbbbbbbb,它们都会被存储在 .git/objects/aa/bbbbbbbbbbbbbbbbbbbbb 中。

这些对象是如何进行编码的?

如果我尝试在 .git/objects 目录下查看这个文件,显示的内容似乎有一些奇怪:

$ cat .git/objects/8a/e33121a9af82dd99d6d706d037204251d41d54
x^A<8D><9B>}s<E3>Ƒ<C6><EF>o|<8A>^Q<9D><EC>ju<92><E8><DD><9C><9C>*<89>j<FD>^...

这是怎么回事呢?让我们来运行 file 命令检查一下:

$ file .git/objects/8a/e33121a9af82dd99d6d706d037204251d41d54
.git/objects/8a/e33121a9af82dd99d6d706d037204251d41d54: zlib compressed data

原来,它是压缩的!我们可以编写一个小巧的 Python 程序—— decompress.py,然后用 zlib 模块去解压这些数据:

import zlib
import sys

with open(sys.argv[1], "rb") as f:
    content = f.read()
    print(zlib.decompress(content).decode())

让我们来解压一下看看结果:

$ python3 decompress.py .git/objects/8a/e33121a9af82dd99d6d706d037204251d41d54
blob 16673---
title: "Get your work recognized: write a brag document"
date: 2019-06-28T18:46:02Z
url: /blog/brag-documents/
categories: []
---
... the entire blog post ...

结果显示,这些数据的编码方式非常简单:首先有 blob 16673\0 标识,其后就是文件的全部内容。

这里并没有差异性数据(diff)

这里有一件我第一次知道时让我感到惊讶的事:这里并没有任何差异性数据!那个文件是该篇博客文章的第 9 个版本,但 Git 在 .git/objects 目录中存储的版本是完整文件内容,而并非与前一版本的差异。

尽管 Git 实际上有时候会以差异性数据存储文件(例如,当你运行 git gc 时,为了提升效率,它可能会将多个不同的文件封装成 “打包文件”),但在我个人经验中,我从未需要关注这个细节,所以我们不在此深入讨论。然而,关于这种格式如何工作,Aditya Mukerjee 有篇优秀的文章 《拆解 Git 的打包文件》。

博客文章的旧版本在哪?

你可能会好奇:如果在我修复了一些错别字之前,这篇博文已经存在了 8 个版本,那它们在 .git/objects 目录中的位置是哪里?我们如何找到它们呢?

首先,我们来使用 git log 命令来查找改动过这个文件的每一个提交:

$ git log --oneline  content/post/2019-06-28-brag-doc.markdown
c6d4db2d
423cd76a
7e91d7d0
f105905a
b6d23643
998a46dd
67a26b04
d9999f17
026c0f52
72442b67

然后,我们选择一个之前的提交,比如 026c0f52。提交也被存储在 .git/objects 中,我们可以尝试在那里找到它。但是失败了!因为 ls .git/objects/02/6c* 没有显示任何内容!如果有人告诉你,“我们知道有时 Git 会打包对象来节省空间,我们并不需过多关心它”,但现在,我们需要去面对这个问题了。

那就让我们去解决它吧。

让我们开始解包一些对象

现在我们需要从打包文件中解包出一些对象。我在 Stack Overflow 上查找了一下,看起来我们可以这样进行操作:

$ mv .git/objects/pack/pack-adeb3c14576443e593a3161e7e1b202faba73f54.pack .
$ git unpack-objects < pack-adeb3c14576443e593a3161e7e1b202faba73f54.pack

这种直接对库进行手术式的做法让人有些紧张,但如果我误操作了,我还可以从 Github 上重新克隆这个库,所以我并不太担心。

解包所有的对象文件后,我们得到了更多的对象:大约有 20000 个,而不是原来的大约 2700 个。看起来很酷。

find .git/objects/ -type f | wc -l
20138

我们回头再看看提交

现在我们可以继续看看我们的提交 026c0f52。我们之前说过 .git/objects 中并不都是文件,其中一部分是提交!为了弄清楚我们的旧文章 content/post/2019-06-28-brag-doc.markdown 是在哪里被保存的,我们需要深入查看这个提交。

首先,我们需要在 .git/objects 中查看这个提交。

查看提交的第一步:找到提交

经过解包后,我们现在可以在 .git/objects/02/6c0f5208c5ea10608afc9252c4a56c1ac1d7e4 中找到提交 026c0f52,我们可以用下面的方法去查看它:

$ python3 decompress.py .git/objects/02/6c0f5208c5ea10608afc9252c4a56c1ac1d7e4
commit 211tree 01832a9109ab738dac78ee4e95024c74b9b71c27
parent 72442b67590ae1fcbfe05883a351d822454e3826
author Julia Evans <[email protected]> 1561998673 -0400
committer Julia Evans <[email protected]> 1561998673 -0400

brag doc

我们也可以用 git cat-file -p 026c0f52 命令来获取相同的信息,这个命令能起到相同的作用,但是它在格式化数据时做得更好一些。(-p 选项意味着它能够以更友好的方式进行格式化)

查看提交的第二步:找到树

这个提交包含一个。树是什么呢?让我们看一下。树的 ID 是 01832a9109ab738dac78ee4e95024c74b9b71c27,我们可以使用先前的 decompress.py 脚本查看这个 Git 对象,尽管我不得不移除 .decode() 才能避免脚本崩溃。

$ python3 decompress.py .git/objects/01/832a9109ab738dac78ee4e95024c74b9b71c27

这个输出的格式有些难以阅读。主要的问题在于,该提交的哈希(\xc3\xf7$8\x9b\x8dO\x19/\x18\xb7}|\xc7\xce\x8e…)是原始字节,而没有进行十六进制的编码,因此我们看到 \xc3\xf7$8\x9b\x8d 而非 c3f76024389b8d。我打算切换至 git cat-file -p 命令,它能以更友好的方式显示数据,我不想自己编写一个解析器。

$ git cat-file -p 01832a9109ab738dac78ee4e95024c74b9b71c27
100644 blob c3f76024389b8d4f192f18b77d7cc7ce8e3a68ad    .gitignore
100644 blob 7ebaecb311a05e1ca9a43f1eb90f1c6647960bc1    README.md
100644 blob 0f21dc9bf1a73afc89634bac586271384e24b2c9    Rakefile
100644 blob 00b9d54abd71119737d33ee5d29d81ebdcea5a37    config.yaml
040000 tree 61ad34108a327a163cdd66fa1a86342dcef4518e    content <-- 这是我们接下来的目标
040000 tree 6d8543e9eeba67748ded7b5f88b781016200db6f    layouts
100644 blob 22a321a88157293c81e4ddcfef4844c6c698c26f    mystery.rb
040000 tree 8157dc84a37fca4cb13e1257f37a7dd35cfe391e    scripts
040000 tree 84fe9c4cb9cef83e78e90a7fbf33a9a799d7be60    static
040000 tree 34fd3aa2625ba784bced4a95db6154806ae1d9ee    themes

这是我在这次提交时库的根目录中所有的文件。看起来我曾经不小心提交了一个名为 mystery.rb 的文件,后来我删除了它。

我们的文件在 content 目录中,接下来让我们看看那个树:61ad34108a327a163cdd66fa1a86342dcef4518e

查看提交的第三步:又一棵树

$ git cat-file -p 61ad34108a327a163cdd66fa1a86342dcef4518e
040000 tree 1168078878f9d500ea4e7462a9cd29cbdf4f9a56    about
100644 blob e06d03f28d58982a5b8282a61c4d3cd5ca793005    newsletter.markdown
040000 tree 1f94b8103ca9b6714614614ed79254feb1d9676c    post <-- 我们接下来的目标!
100644 blob 2d7d22581e64ef9077455d834d18c209a8f05302    profiler-project.markdown
040000 tree 06bd3cee1ed46cf403d9d5a201232af5697527bb    projects
040000 tree 65e9357973f0cc60bedaa511489a9c2eeab73c29    talks
040000 tree 8a9d561d536b955209def58f5255fc7fe9523efd    zines

还未结束……

查看提交的第四步:更多的树……

我们要寻找的文件位于 post/ 目录,因此我们需要进一步探索:

$ git cat-file -p 1f94b8103ca9b6714614614ed79254feb1d9676c
.... 省略了大量行 ...
100644 blob 170da7b0e607c4fd6fb4e921d76307397ab89c1e    2019-02-17-organizing-this-blog-into-categories.markdown
100644 blob 7d4f27e9804e3dc80ab3a3912b4f1c890c4d2432    2019-03-15-new-zine--bite-size-networking-.markdown
100644 blob 0d1b9fbc7896e47da6166e9386347f9ff58856aa    2019-03-26-what-are-monoidal-categories.markdown
100644 blob d6949755c3dadbc6fcbdd20cc0d919809d754e56    2019-06-23-a-few-debugging-resources.markdown
100644 blob 3105bdd067f7db16436d2ea85463755c8a772046    2019-06-28-brag-doc.markdown <-- 我们找到了!!!

在此,2019-06-28-brag-doc.markdown 之所以位于列表最后,是因为在发布时它是最新的博文。

查看提交的第五步:我们终于找到它!

经过努力,我们找到了博文历史版本所在的对象文件!太棒了!它的哈希值是 3105bdd067f7db16436d2ea85463755c8a772046,因此它位于 git/objects/31/05bdd067f7db16436d2ea85463755c8a772046

我们可以使用 decompress.py 来查看它:

$ python3 decompress.py .git/objects/31/05bdd067f7db16436d2ea85463755c8a772046 | head
blob 15924---
title: "Get your work recognized: write a brag document"
date: 2019-06-28T18:46:02Z
url: /blog/brag-documents/
categories: []
---
... 文件的剩余部分在此 ...

这就是博文的旧版本!如果我执行命令 git checkout 026c0f52 content/post/2019-06-28-brag-doc.markdown 或者 git restore --source 026c0f52 content/post/2019-06-28-brag-doc.markdown,我就会获取到这个版本。

这样遍历树就是 git log 的运行机制

我们刚刚经历的整个过程(找到提交、逐层遍历目录树、搜索所需文件名)看似繁琐,但实际上当我们执行 git log content/post/2019-06-28-brag-doc.markdown 时,背后就是这样在运行。它需要逐个检查你历史记录中的每一个提交,在每个提交中核查 content/post/2019-06-28-brag-doc.markdown 的版本(例如在这个案例中为 3105bdd067f7db16436d2ea85463755c8a772046),并查看它是否自上一提交以来有所改变。

这就是为什么有时 git log FILENAME 会执行的有些缓慢 —— 我的这个仓库中有 3000 个提交,它需要对每个提交做大量的工作,来判断该文件是否在该提交中发生过变化。

我有多少个历史版本的文件?

目前,我在我的博客仓库中跟踪了 1530 个文件:

$ git ls-files | wc -l
1530

但历史文件有多少呢?我们可以列出 .git/objects 中所有的内容,看看有多少对象文件:

$ find .git/objects/ -type f | grep -v pack | awk -F/ '{print $3 $4}' | wc -l
20135

但并不是所有这些都代表过去版本的文件 —— 正如我们之前所见,许多都是提交和目录树。不过,我们可以编写一个小小的 Python 脚本 find-blobs.py,遍历所有对象并检查是否以 blob 开头:

import zlib
import sys

for line in sys.stdin:
    line = line.strip()
    filename = f".git/objects/{line[0:2]}/{line[2:]}"
    with open(filename, "rb") as f:
        contents = zlib.decompress(f.read())
        if contents.startswith(b"blob"):
            print(line)
$ find .git/objects/ -type f | grep -v pack | awk -F/ '{print $3 $4}' | python3 find-blobs.py | wc -l
6713

于是,看起来在我的 Git 仓库中存放的旧文件版本有 6713 - 1530 = 5183 个,Git 会为我保存这些文件,以备我想着要恢复它们时使用。太好了!

就这些啦!

这个 gist 中附上了全部的此篇文章所用代码,其实没多少。

我以为我已经对 Git 的工作方式了如指掌,但我以前从未真正涉及过打包文件,所以这次探索很有趣。我也很少思考当我让 git log 跟踪一个文件的历史时,它实际上有多大的工作量,因此也很开心能深入研究这个。

作为一个有趣的后续:我提交这篇博文后,Git 就警告我仓库中的对象太多(我猜 20,000 太多了!),并运行 git gc 将它们全部压缩成打包文件。所以现在我的 .git/objects 目录已经被压缩得十分小了:

$ find .git/objects/ -type f | wc -l
14

(题图:MJ/319a396c-6f3f-4891-b051-261312c8ea9a)


via: https://jvns.ca/blog/2023/09/14/in-a-git-repository--where-do-your-files-live-/

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

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

提升 DevOps 文档成熟度的过程与达到 DevOps 或 DevSecOps 成熟化的历程是类似的。

为了能在软件迭代交付周期内按时交付优质的文档,DevOps 和 DevSecOps 的文档实践也需要是敏捷的。这与实现 DevOps 类似,只是更偏向自动化和敏捷的内容处理方法。如果文档现在才进入你的机构的 DevOps 讨论,那么是时候让文档实践追上 DevOps 的步伐了。

下面是 DevOps 文档成熟度的四个层次:

第一层:临时且孤立

在最低一级成熟度(最不成熟),文档编制工作没有和 DevOps 开发对齐。开发团队和文档团队按照各自的路线开展工作,常常导致文档落后于开发。在竞争激烈的“云”世界里,因为文档问题而推迟产品发布是不可接受的。

人员

这个阶段的文档编制人员还没有摆脱传统的工作方式。 技术写作 technical writer 人员隶属于一个中心化的单独团队,与开发团队是脱节的。技术写作组和开发团队之间的鸿可能是由多方面原因造成的:

  • 造成团队分裂和孤立的公司政治
  • 团队只是将技术文档视为项目验收清单上的检查项,而不是推动项目成功的资产
  • 事后才雇佣技术写作人员
  • 技术写作的优先级与开发团队的实际情况不匹配

这个阶段,另一个在人员配置上的挑战是如何“界定工作完成”。刚接触敏捷实践的技术写作可能难以适应 CI/CD 工具链和流程。

文档工具和流程

这个阶段的技术写作仍习惯于使用传统的办公工具,比如办公套件和布局程序。这些工具不够敏捷,没有版本控制和内容管理的要求。它们无法与 DevOps 工具链高效集成,不能支撑快速开发。在这个成熟度,技术写作仍然参照遗留的模板和流程。

成果

这个级别交付的文档可能是过时的,甚至缺乏技术准确性的。如果开发团队以 DevOps 的速度推进工作,而技术文档编制却遵循传统的非敏捷流程(使用专有的工具和交付格式),这就很难让文档迭代速度并跟上应用程序的变化。

第二层:实验和试点

DevOps 文档成熟度的第二层是实验/试验阶段。这个阶段是 DevOps 团队主管和技术写作采取行动打造更敏捷的文档实践和工具的第一步。

理想的情况下,这些实验是 相关方 stakeholder 支持的试点项目的一部分。他们能够从文档交付流程的改善以及其与 DevOps 实践的集成中获益。

人员

本阶段的人员可能来自以下三种形式:

  1. 有远见的技术写作为了更好地完成工作,用自己的时间来实验更敏捷的工具。并且向领导层提出更敏捷的文档编制过程的想法。
  2. DevOps 负责人或工程师试用 Hugo 和 Jekyll 等工具,并将这些工具集成到 CI/CD 流水线中。然后 DevOps 小组教授技术写作如何使用它们。
  3. 团队引入了第三方承包商或顾问,他们在 DevOps 文档工具方面具有专业知识,并且了解文档工具适合嵌入到 CI/CD 工具链和 DevOps 生命周期的位置。

文档工具和实践

HugoJekyll 是本阶段开始出现的工具。在这个阶段也出现新的内容策略和技术写作方法。

成果

实验试点阶段理想的成果应该能够“ 落地并推广 land and expand ”。也就是说其它项目组也可以将其付诸实践。

这个阶段的实验也包括内容策略和发布流程上的根本性变化。其它非试点项目组的技术写作可以学习和使用它们。

试点带来的另一个可能的产出是 技术写作招聘流程 的变化。你需要针对 DevOps 和你新引入的文档工具对内部编写人员进行培训。

新的文档工具和流程是此阶段的关键成果,你需要通过演示、状态报告和内部案例研究等方式,将这一成果推给领导层、相关方和其它团队。

第三层:部分自动化和扩展

DevOps 文档成熟度的第三层(部分自动化和扩展)就是“落地并推广”的进一步行动。在这个阶段,其它 DevOps 团队借用试点项目中产生的 DevOps 文档工具和流程,吸取其中的经验教训。

人员

在这个成熟度,技术写作和 DevOps 团队开始更紧密的协作。招聘新的技术写作主要关注具有 DevOps 环境经验的人选。

工具和文档实践

技术写作开始从抛弃传统的工具和流程,转到更敏捷的文档工具上,比如:

在这个成熟度,技术写作也负责调整遗留的文档实践。

成果

DevOps 文档工具和实践超越试点项目,成为标准实践。在这个成熟度,随着新团队使用新的文档工具和流程,持续学习是必不可少的。

第四层:完全采用

在最高一级的 DevOps 文档成熟度(完全采用且自动化)所有工具、实践和流程已经到位,以支持将文档为项目中的高优先级事项。要达到这一成熟度,需要不断实验、迭代和团队协作。

人员

完全自动化使 DevOps 团队与技术写作之间的协作更紧密。这一阶段的标志是,技术写作牢牢地融入到项目团队的工作流程中。文档工具的维护工作由一些大型企业负责,它们拥有专职维护 DevOps 工具链的工程师。

文档工具和实践

在这个成熟度,技术写作统一采用 Markdown 语言和自动化工具。

成果

本阶段的成果是一套完整的工具和实践,它们支持自动化在线文档发布。技术写作者可以按需发布和重新发布文档,以支持迭代开发流程。

持续学习是这个阶段的另一项成果。技术写作和工具链维护者寻找改进自动化和流程的方法,以帮助文档实践。

总结

提升 DevOps 文档成熟度的过程跟达到 DevOps 或 DevSecOps 成熟化的历程是类似的。我希望行业能够将更灵活的文档实践和工具作为公司推进 DevOps 进程中的一个部分。提高 DevOps 文档成熟度应该作整体 DevOps 成熟化甚至 DevOps 到 DevSecOps 转型的一部分。

(题图:MJ/154429b7-bdfc-4b34-9a81-55d9fe33ab07)


via: https://opensource.com/article/22/2/devops-documentation-maturity

作者:Will Kelly 选题:lujun9972 译者:toknow-gh 校对:wxy

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

数据分析已成为企业的当务之急,并且对具有用户友好界面的数据驱动应用程序有巨大的需求。本文介绍如何使用 R 语言中的 Shiny 包开发交互式 Web 应用程序,R 语言是一种流行的数据科学编程语言。

如今,世界各地几乎所有企业都以某种形式依赖于数据。数据科学通过使用数据驱动的应用程序帮助许多企业实现转型,无论是在金融、银行、零售、物流、电子商务、运输、航空还是任何其他领域。

高性能计算机和低成本存储使我们现在能够在几分钟内预测结果,而不是像以前一样以前需要花费很多时间。数据科学家着眼于未来,正在开发具有高性能和多维可视化的便捷应用。这一切都始于大数据,它由三个组成部分组成:数量、多样性和速度。算法和模型都是根据这些数据提供的。机器学习和人工智能领域最前沿的数据科学家正在创建能够自我改进、检测错误并从中学习的模型。

在数据科学领域,统计和计算用于将数据转化为有用的信息,通常称为数据驱动科学。数据科学是来自各个领域的方法的综合,用于收集、分析和解释数据,以形成新的见解并做出选择。构成数据科学的技术学科包括统计学、概率、数学、机器学习、商业智能和一些编程。

数据科学可以应用于各个领域(图 1)。对大型、复杂数据集的分析是数据科学的重点。它帮助我们创建了一个以全新方式看待数据的新宇宙。亚马逊、谷歌和 Facebook 等科技巨头利用数据科学原理进行商业智能和商业决策。

Figure 1 Key applications-and use cases of data science

R 语言:为数据科学量身打造的语言

由于海量的可用信息,我们迫切需要数据分析以得到新的见解,在多种技术的帮助下,原始数据转化为成品数据产品。在数据研究、处理、转换和可视化方面,没有比 R 语言更好的工具了。

R 语言用于数据科学的主要功能包括:

  • 数据预处理
  • 社交媒体数据获取和分析
  • 对数据结构的各种操作
  • 提取、转换、加载(ETL)
  • 连接到各种数据库,包括 SQL 和电子表格
  • 与 NoSQL 数据库交互
  • 使用模型进行训练和预测
  • 机器学习模型
  • 聚类
  • 傅里叶变换
  • 网页抓取

R 语言是一种强大的编程语言,常用于统计计算和数据分析。有关优化 R 语言用户界面的努力由来已久。从简单的文本编辑器到更现代的交互式 R Studio 和 Jupyter Notebooks,世界各地的多个数据科学小组都在关注 R 语言的发展。

只有全世界 R 用户的贡献才使这一切成为可能。R 语言中包含的强大软件包使其日益强大。许多开源软件包使处理大型数据集和可视化数据变得更加容易和高效。

使用 Shiny 在 R 语言中开发交互式 Web 应用

你可以使用 Shiny 包在 R 语言中构建交互式 Web 应用程序。应用程序可以托管在网站上、嵌入 R Markdown 文档中,或用于开发控制面板板和可视化。CSS 主题、HTML 小部件和 JavaScript 操作都可以用于进一步自定义你的 Shiny 应用程序。

Shiny 是一款 R 语言工具,它可以轻松创建交互式的 Web 应用程序。它允许你将你的 R 代码扩展到 Web 上,从而使更多的人能够使用它,从中获益。

除了 Shiny 内置的功能外,还有许多第三方扩展包可用,例如 shinythemes、shinydashboard 和 shinyjs。

使用 Shiny 可以开发各种应用程序。以下是其中一些:

  • 基于 Web 应用的机器学习
  • 具有动态控件的 Web 应用程序
  • 数据驱动的仪表盘
  • 多重数据集的交互式应用
  • 实时数据可视化面板
  • 数据收集表单

Shiny Web 应用程序可以分为以下几类:

  • 用户接口
  • 服务功能逻辑
  • Shiny 应用逻辑

获取更深理解,请访问以下网站 https://shiny.rstudio.com/gallery/

其中某个用 Shiny 开发的应用如图 2(https://shiny.rstudio.com/gallery/radiant.html )。

Figure 2: Shiny based app

销售仪表盘的生成

下面是一个与销售仪表盘相关的 Web 应用程序的代码片段。该仪表板具有多个控件和用户界面模块,用于查看数据。

首先,安装 Shiny 包,然后在代码中调用它,以便将输出呈现为 Web 页面的形式。

library(shiny)
library(dplyr)

sales <- vroom::vroom(“salesdata.csv”, na = “”)
ui <- fluidPage(
    titlePanel(“Dashboard for Sales Data”),
    sidebarLayout(
        sidebarPanel(
            selectInput(“territories”, “territories”, choices = unique(sales$territories)),
            selectInput(“Customers”, “Customer”, choices = NULL),
            selectInput(“orders”, “Order number”, choices = NULL, size = 5, selectize = FALSE),
        ),
        mainPanel(
            uiOutput(“customer”),
            tableOutput(“data”)
        )
    )
)
server <- function(input, output, session) {
    territories <- reactive({
        req(input$territories)
        filter(sales, territories == input$territories)
    })
    customer <- reactive({
        req(input$Customers)
        filter(territories(), Customers == input$Customers)
    })

    output$customer <- renderUI({
        row <- customer()[1, ]
        tags$div(
            class = “well”,
            tags$p(tags$strong(“Name: “), row$customers),
            tags$p(tags$strong(“Phone: “), row$contact),
            tags$p(tags$strong(“Contact: “), row$fname, “ “, row$lname)
        )
    })

    order <- reactive({
        req(input$order)
        customer() %>%
        filter(ORDER == input$order) %>%
        arrange(OLNUMBER) %>%
        select(pline, qty, price, sales, status)
    })

    output$data <- renderTable(order())

    observeEvent(territories(), {
        updateSelectInput(session, “Customers”, choices = unique(territories()$Customers), selected = character())
    })
    observeEvent(customer(), {
        updateSelectInput(session, “order”, choices = unique(customer()$order))
    })
}
shinyApp(ui, server)

运行 Shiny 应用程序的代码后,生成了图 3 所示的输出,可以在任何 Web 浏览器上查看。销售仪表盘具有多个控件,并且具有不同的用户界面模块,非常互动。

Figure 3: Sales dashboard with multiple controls

通过使用 Shiny Cloud,可以将这个应用程序部署和托管在云上,以便随时随地在互联网上使用。

Figure 4: Cloud for hosting and deployment of Shiny app

Shiny Cloud 的免费版本允许在 25 个活动小时内部署五个应用程序。研究人员和数据科学家可以使用 R 的 Shiny 库开发基于实时数据驱动的用户友好应用程序。这个库也可以用于在 Web 平台上部署他们的机器学习应用程序。

(题图:MJ/1a76ad20-e56d-480b-b28b-8cf74d2230a1)


via: https://www.opensourceforu.com/2022/10/using-r-for-building-an-interactive-web-app/

作者:Dr Kumar Gaurav 选题:lkxed 译者:Charonxin 校对:wxy

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