Alan Smithee 发布的文章

请下载我们的电子书获得在 Linux 和 FreeDOS 上 C 语言编程的提示和技巧。

有许多关于为什么 C 语言能够经久不衰的说法。或许是因为它语法简单明了。又或许是因为它常被认为是实用的语言,因为它不基于其他高级语言,可以在任何平台上编译运行。C 显然是一种强大的语言,并且我认为它经久不衰与它作为其他技术的基础的方式相关。这里有 5 项我喜爱的基于 C 语言的技术,希望它们能够帮助你更多的了解 C 语言。

1、GObject 和 GTK

C 语言不是面向对象编程的语言。它没有 class 关键字。 一些人用 C++ 进行面向对象编程,但是还有一些人坚持用 C 和 GObject 库。GObject 库为 C 语言提供了一个 class 结构体,GTK 项目以提供可通过 C 访问的工具包而闻名。没有 GTK ,就没有 GIMP (GTK 就是为此开发的)、GNOME 和其他成千上百流行的开源应用。

了解更多

GObject 和 GTK 是使用 C 开始进行 GUI 编程的绝佳方式。它们“装备精良”,可以让你用 C 语言进行图形应用的编程,因为开发者为你做了许多“繁重工作”。他们定义了类和数据类型,创建了工具包,你所要做的就是将所有东西放在一起。

2、Ncurses

如果 GTK 超过了你的需求,你或许认为一个 终端用户界面 terminal user interface (TUI)更适合你。Ncurses 库可以在终端创建“小部件”,创建一种在终端窗口上绘制图形的应用程序。你可以使用方向键控制界面,选择按钮和元素,就像不用鼠标来使用 GUI 应用一样。

了解更多

利用 Ncurses 库使用 C 语言写一个 猜数字 游戏。

3、Lua 和 Moonscript

Lua 是一种脚本语言,它可以使用内置的 C API 访问 C 语言库。它十分精巧、快捷以及简单,拥有约 30 个函数和少量内置库。你可以使用 Lua 进行系统自动化、游戏修改和脚本编写、使用 LÖVE 之类的前端进行游戏开发,或者使用 GTK 进行一般应用程序开发(例如 Howl 文本编辑器)。

了解更多

Lua 十分好的一点是你可以从它开始学习掌握基本的编程理念,然后当你有足够勇气直面基础编程语言时,再探索它的 C 语言 API 。另一方面,如果你只会 Lua ,那也没事儿。Lua 有很多的 外部库 ,使其成为各种开发方式的绝佳选择。

4、Cython

Lua 不是唯一带有 C 接口的编程语言。Cython 是一种编译器和编程语言,旨在使为 Python 编写 C 扩展就像编写 Python 代码一样容易。本质上,你可以编写 Python 并最终得到 C 语言程序。最简单的示例:

print("hello world")

创建一个 setup.py 脚本:

from setuptools import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("hello.pyx")
)

运行该 setup 脚本:

$ python3 ./setup.py

最后你会在同一个目录中得到一个 hello.c 和 hello.cpython-39-x86_64-linux-gnu.so 文件。

了解更多

Cython 是 Python 的一个超集,支持 C 语言的函数和数据类型。它不可能帮你直接学习 C 语言,但它为希望学习 C 代码并将其集成到 Python 中的 Python 开发人员开辟了新的可能性。

5、FreeDOS

了解更多 C 语言的最好方式是编写 C 代码,没有什么比写你可以真正使用的代码更令人激动的了。FreeDOS 项目是 DOS 的开源实现, 而 DOS 是 Windows 的前身。或许你已经用过 FreeDOS 了,或者作为运行 BIOS 更新程序的便捷开源方法,或者在模拟器中玩经典的计算机游戏。你可以用 FreeDOS 做更多事情。它是学习 C 语言的理想平台,其中包含一系列工具,鼓励你编写自己的命令和简单(或不那么简单,如果你愿意)的应用程序。当然你可以在任何系统上写 C 代码,但是 FreeDOS 的便利可能会让你感到耳目一新。天空有极限,但即使在地面上,你也可以用 C 做一些非常有趣的事情。

下载电子书

你可以从我们编写的新 电子书 中学到更多 C 语言,并在我们的电子书中了解有关 FreeDOS 上 C 语言的更多信息。这些是编程文章的集合,可帮助你学习 C 语言,并演示如何以有用的方式用 C 写一些代码。

下载电子书

via: https://opensource.com/article/22/7/learn-c-linux

作者:Alan Smithee 选题:lkxed 译者:Donkey 校对:wxy

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

如果你是容器的新手,不要被那些术语所吓倒。这些关键原则将帮助你把应用迁移到云中。

 title=

一般来说,人们想使用你的应用程序这是一件好事。然而,当应用程序在服务器上运行时,应用程序受欢迎是有代价的。随着用户对资源需求的增加,在某些时候,你可能会发现你需要扩展你的应用程序。一种选择是在这种情况下增加更多的服务器,建立一个像 Nginx 这样的 负载平衡器,以满足需求。但是,这种方法的成本可能很昂贵,因为当需求低的时候,在没有流量的服务器上运行你的应用程序的实例并不会节省资源。容器的优点是它是非持久的,在有需求时启动新实例,而随着需求的减少逐渐消失。如果这听起来像是你需要的功能,那么现在可能是将你的应用程序迁移到容器的时候了。

将应用程序迁移到容器中,很快就会变得迷失方向。虽然容器内的环境可能感觉很熟悉,但许多容器镜像是最小化的,而且它们被设计为无状态的。不过在某种程度上,这也是容器的优势之一。就像 Python 虚拟环境一样,它是一块白板,可以让你构建(或重建)你的应用程序,而没有许多其他环境所提供的无形的默认值。

每一次向云服务的迁移都是独一无二的,但在将你的应用程序移植到容器之前,你应该注意以下几个重要原则。

1、理解你的依赖关系

将你的应用程序移植到容器中是一个很好的机会,可以了解你的应用程序实际依赖的东西。由于除了最基本的系统组件外,很少有默认安装的组件,你的应用程序一开始不太可能在容器中运行。

在重构之前,确定你的依赖关系。首先,在你的源代码中用 grep 查找 include、import、require、use 或你选择的语言中用来声明依赖关系的任何关键词。

$ find ~/Code/myproject -type f \
    -iname ".java" \
    -exec grep import {} \;

不过,仅仅识别你使用的特定语言的库可能是不够的。审计依赖关系,这样你就能知道是否有语言本身运行所需的低级库,或者特定的模块以预期的功能运行。

2、评估你的数据存储

容器是无状态的,当一个容器崩溃或停止运行时,该容器的实例就永远消失了。如果你要在该容器中保存数据,这些数据也会消失。如果你的应用程序存储用户数据,所有的存储必须发生在容器之外,在你的应用程序的实例可以访问的某个位置。

你可以使用映射到容器内某个位置的本地存储来存储简单的应用程序配置文件。这是一种常见的技术,适用于需要管理员提供简单配置值的 Web 应用程序,如管理员的电子邮件地址、网站标题等。比如说:

$ podman run \
    --volume /local/data:/storage:Z \
    mycontainer

然而,你可以配置一个数据库,如 MariaDB 或 PostgreSQL,将大量数据在几个容器中的共享存储。对于私人信息,如密码,你可以配置一个机密存储。

对于你需要如何重构你的代码,相应地调整存储位置,这可能意味着改变路径到新的容器存储映射,移植到不同的数据库,甚至是纳入容器特定的模块。

3、准备好你的 Git 仓库

容器在构建时通常会从 Git 仓库中拉取源代码。一旦你的 Git 仓库成为你的应用程序的生产就绪代码的标准来源,你必须有一个管理 Git 仓库的计划。要有一个发布分支或生产分支,并考虑使用 Git 钩子 来拒绝意外的未经批准的提交。

4、了解你的构建系统

容器化应用程序可能没有传统的发布周期。当容器被构建时,它们会被从 Git 中拉取出来。你可以启动任何数量的构建系统作为容器构建的一部分,但这可能意味着调整你的构建系统,使其比过去更加自动化。你应该重构你的构建过程,使你完全有信心它能在无人值守的情况下工作。

5、构建镜像

构建镜像不一定是复杂的任务。你可以使用 现有的容器镜像 作为基础,用一个简单的 Docker 文件对其进行调整。另外,你也可以使用 Buildah 从头开始构建你自己的镜像。

在某种程度上,构建容器的过程与实际重构代码一样,都是开发的一部分。容器的构建是为了获取、组装和执行你的应用程序,所以这个过程必须是自动化的、健壮的。建立一个好的镜像,你就为你的应用程序建立了一个坚实可靠的基础。

容器化

如果你是容器的新手,不要被术语所吓倒。容器只是另一种环境。容器化开发的感知约束实际上可以帮助你专注于你的应用程序,并更好地了解它是如何运行的、它需要什么才能可靠地运行,以及当出错时有哪些潜在的风险。相反,这导致系统管理员在安装和运行你的应用程序时受到的限制要少得多,因为从本质上讲,容器是一个受控的环境。仔细审查你的代码,了解你的应用程序需要什么,并相应地重构它。


via: https://opensource.com/article/22/2/migrate-application-containers

作者:Alan Smithee 选题:lujun9972 译者:wxy 校对:wxy

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

最好的聊天应用是一个不属于聊天应用的应用。

 title=

请考虑一下,当用户的数据被发布到互联网上,或通过互联网发布时,他们的数据究竟去了哪里。古老的聊天应用是互联网通信领域的一个手工行业,似乎在潮流中起起落落。人们使用聊天应用进行各种形式的对话,大多数人不会想到机器人正在记录和监控他们所说的话,无论是为了有效地定位广告还是只是为了建立一个档案供将来使用。这使得聊天应用特别容易受到不良的隐私做法的影响,但幸运的是,现在有几个开源的、注重隐私的应用,如 Signal、Rocket.Chat 和 Mattermost。我运行过 Mattermost 和 Rocket.Chat,我也在使用 Signal,但我最兴奋的应用是 Delta Chat,这个聊天服务非常方便,甚至不使用聊天服务器。相反,Delta Chat 使用的是你已经使用的最大规模和最多样化的开放信息系统:它使用电子邮件,通过聊天应用发送和接收信息,并以 Autocrypt 的端到端加密为特色。

安装 Delta Chat

Delta Chat 使用标准的电子邮件协议作为它的后端,但对于作为普通用户的你和我来说,它的外观和行为完全像一个聊天应用。也就是说你需要安装一个开源的 Delta Chat 应用。

在 Linux 上,你可以从 Flatpak 包或你的软件库中安装 Delta Chat。

在 macOS 和 Windows 上,从 delta.chat/downloads 下载一个安装程序。

在安卓系统上,你可以从 Play Store 或开源的 F-droid 仓库 安装 Delta Chat。

在 iOS 系统中,从 App Store 安装 Delta Chat。

因为 Delta Chat 使用电子邮件来传递信息,所以如果你不在你的聊天应用中,你也可以在收件箱中收到信息。是的,即使没有安装 Delta Chat,你也可以使用 Delta Chat!

配置 Delta Chat

当你第一次启动 Delta Chat 时,你必须登录到你的电子邮件账户。这往往是 Delta Chat 最难的部分,因为它要求你了解你的电子邮件服务器的详细信息,或者在你的电子邮件提供商的安全设置中创建一个“应用密码”。

如果你使用的是自己的服务器,并且所有配置都是默认的(993 端口用于 IMAP 接收,465 端口用于 SMTP 发出,启用了 SSL/TLS),那么你可以直接输入你的电子邮件地址和密码,然后继续。

 title=

如果你运行自己的服务器,但你有自定义设置,那么点击“ 高级 Advanced ”按钮,输入你的设置。如果你使用一个不寻常的子域来用作你的邮件服务器,或一个自定义端口,或一个复杂的登录和密码配置,你可能需要这样做。

如果你使用的是 Gmail、Fastmail、Yahoo 或类似的电子邮件供应商,那么你必须创建一个应用密码,这样你就可以通过 Delta Chat 而不是网络浏览器登录到你的账户。许多电子邮件供应商限制登录,以避免无休止的机器人和脚本试图用暴力手段进入人们的账户,所以对你的供应商来说,Delta Chat 看起来很像机器人。当你授予 Delta Chat 特殊权限时,你就是在提醒你的电子邮件提供商,从一个远程应用发出大量的短信息是预期的行为。

每个电子邮件提供商都有不同的提供应用密码的方式,但 Fastmail(在我看来)是最简单的:

  1. 进入“ 设置 Settings ”
  2. 点击“ 密码和安全 Passwords & Security ”
  3. 在“ 第三方应用 Third-party apps ”的旁边,点击“ 添加 Add ”按钮

验证你的密码,并创建一个新的应用密码。使用你创建的应用密码登录 Delta Chat。

 title=

使用 Delta Chat 聊天

当你克服了登录的障碍,剩下的就很容易了。因为 Delta Chat 只使用电子邮件,你可以通过电子邮件地址而不是通过聊天程序的用户名或电话号码来添加朋友。从技术上讲,你可以在 Delta Chat 上添加任何电子邮件地址。毕竟,它只是一个有特定使用场景的电子邮件应用。不过,告诉你的朋友 Delta Chat 是很有礼貌的,而不是期望他们通过他们的电子邮件客户端与你进行随意的聊天。

无论你是在手机还是在电脑上运行这个应用,其外观都与你所期望的聊天应用完全一样。你可以发起聊天,发送消息,并通过加密文本与朋友闲聊。

 title=

开始聊天

Delta Chat 是去中心化的、完全加密的,并依赖于一个成熟的基础设施。多亏 Delta Chat,你可以选择你和你的联系人之间的服务器,你可以在私下里交流。没有需要安装的复杂的服务器,没有需要维护的硬件。这是一个看似复杂问题的简单解决方案,而且是开源的。我们有充分的理由去尝试它。


via: https://opensource.com/article/22/1/delta-chat-software-privacy-day

作者:Alan Smithee 选题:lujun9972 译者:geekpi 校对:wxy

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

Rust 的高性能、高可靠性和高生产力使它适合于嵌入式系统。

 title=

在过去的几年里,Rust 在程序员中获得了热情的追捧。技术潮流来来去去,所以很难将仅仅因为某项新技术而产生的兴奋与对某项技术的优点的兴奋区分开来,但我认为 Rust 是一种真正设计良好的语言。它的目标是帮助开发者建立可靠和高效的软件,而且它从一开始就是为这个目的设计的。你可能听过一些 Rust 的关键特性,在这篇文章中,我会证明这些特性正是 Rust 也恰好适合嵌入式系统的原因。比如:

  • 高性能:它速度快,内存利用率高
  • 可靠性:在编译过程中可以消除内存错误
  • 生产力:很棒的文档,友好的编译器,有用的错误信息,以及一流的工具化。它有一个集成的包管理器和构建工具,智能的多编辑器支持自动补完和类型检查、自动格式化等等。

为什么使用 Rust 进行嵌入式开发?

Rust 的设计是为了保证安全和高性能。嵌入式软件会出现的问题主要是内存的问题。从某种程度上说,Rust 是一种面向编译器的语言,所以你可以确保在编译时安全使用内存。以下是使用 Rust 在嵌入式设备上开发的一些好处:

  • 强大的静态分析
  • 灵活的内存
  • 无畏的并发性
  • 互操作性
  • 可移植性
  • 社区驱动

在这篇文章中,我使用开源的 RT-Thread 操作系统 来演示如何使用 Rust 进行嵌入式开发。

如何在 C 语言中调用 Rust

在 C 代码中调用 Rust 代码时,你必须将 Rust 源代码打包成静态库文件。当 C 代码编译时,将其链接进去。

用 Rust 创建一个静态库

在这个过程中,有两个步骤:

1、使用 cargo init --lib rust_to_c 在 Clion 中建立一个 lib 库。在 lib.rs 中加入以下代码。下面的函数计算两个类型为 i32 的值的总和并返回结果:

#![no_std]
use core::panic::PanicInfo;

#[no_mangle]
pub extern "C" fn sum(a: i32, b: i32) -> i32 {
    a + b
}

#[panic_handler]
fn panic(_info:&PanicInfo) -> !{
    loop{}
}

2、在你的 Cargo.toml 文件中添加以下代码,以告诉 Rustc 要生成什么类型的库:

[lib]
name = "sum"
crate-type = ["staticlib"]
path = "src/lib.rs"

交叉编译

你可以针对你的目标平台进行交叉编译。假设你的嵌入式系统是基于 Arm 的,步骤很简单:

$ rustup target add armv7a-none-eabi

生成静态库文件:

$ cargo build --target=armv7a-none-eabi --release --verbose
Fresh rust_to_c v0.1.0
Finished release [optimized] target(s) in 0.01s

生成头文件

你也需要头文件:

1、安装 cbindgen。cbindgen 工具会从 Rust 库中生成一个 C 或 C++11 的头文件:

$ cargo install --force cbindgen

2、在你的项目文件夹下创建一个新的 cbindgen.toml 文件。

3、生成一个头文件:

$ cbindgen --config cbindgen.toml --crate rust_to_c --output sum.h

调用 Rust 库文件

现在你可以对你的 Rust 库进行调用了。

1、把生成的 sum.h 和 sum.a 文件放到 rt-thread/bsp/qemu-vexpress-a9/applications 目录下。

2、修改 SConscript 文件并添加一个静态库:

   from building import *
   
   cwd     = GetCurrentDir()
   src     = Glob('*.c') + Glob('*.cpp')
   CPPPATH = [cwd]
   
   LIBS = ["libsum.a"]
   LIBPATH = [GetCurrentDir()]
   
   group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH, LIBS = LIBS, LIBPATH = LIBPATH)
   
   Return('group')

3、在主函数中调用 sum 函数,得到返回值,并 printf 该值:

   #include <stdint.h>
   #include <stdio.h>
   #include <stdlib.h>
   #include <rtthread.h>
   #include "sum.h"
   
   int main(void)
   {
       int32_t tmp;
   
       tmp = sum(1, 2);
       printf("call rust sum(1, 2) = %d\n", tmp);
   
       return 0;
   }

4、在 RT-Thread Env 环境中,使用 scons 来编译项目并运行:

$ scons -j6
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
[...]
scons: done building targets.

$ qemu.sh
 \ | /
- RT -     Thread Operating System
 / | \     4.0.4 build Jul 28 2021
2006 - 2021 Copyright by rt-thread team
lwIP-2.1.2 initialized!
[...]
call rust sum(1, 2) = 3

加、减、乘、除

你可以在 Rust 中实现一些复杂的数学运算。在 lib.rs 文件中,使用 Rust 语言来实现加、减、乘、除:

#![no_std]
use core::panic::PanicInfo;

#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
    a + b
}

#[no_mangle]
pub extern "C" fn subtract(a: i32, b: i32) -> i32 {
    a - b
}

#[no_mangle]
pub extern "C" fn multiply(a: i32, b: i32) -> i32 {
    a * b
}

#[no_mangle]
pub extern "C" fn divide(a: i32, b: i32) -> i32 {
    a / b
}

#[panic_handler]
fn panic(_info:&PanicInfo) -> !{
    loop{}
}

构建你的库文件和头文件,并把它们放在应用程序目录中。使用 scons 来编译。如果在链接过程中出现错误,请在官方 Github 页面 中找到解决方案。

修改 rtconfig.py 文件,并添加链接参数 --allow-multiple-definition:

       DEVICE = ' -march=armv7-a -marm -msoft-float'
       CFLAGS = DEVICE + ' -Wall'
       AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -D__ASSEMBLY__ -I.'
       LINK_SCRIPT = 'link.lds'
       LFLAGS = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors,--allow-multiple-definition'+\
                         ' -T %s' % LINK_SCRIPT
   
       CPATH = ''
       LPATH = ''

编译并运行 QEMU 来看看你的工作。

在 Rust 中调用 C 语言

Rust 可以在 C 代码中调用,但是如何在你的 Rust 代码中调用 C 呢?下面是一个在 Rust 代码中调用 rt_kprintf C 函数的例子。

首先,修改 lib.rs 文件:

    // The imported rt-thread functions list
    extern "C" {
        pub fn rt_kprintf(format: *const u8, ...);
    }
   
    #[no_mangle]
    pub extern "C" fn add(a: i32, b: i32) -> i32 {
        unsafe {
            rt_kprintf(b"this is from rust\n" as *const u8);
        }
        a + b
    }

接下来,生成库文件:

$ cargo build --target=armv7a-none-eabi --release --verbose
Compiling rust_to_c v0.1.0
Running `rustc --crate-name sum --edition=2018 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type staticlib --emit=dep-info,link -C opt-level=3 -C embed-bitcode=no -C metadata=a
Finished release [optimized] target(s) in 0.11s

而现在,要运行代码,将 Rust 生成的库文件复制到应用程序目录中,然后重新构建:

$ scons -j6 scons: Reading SConscript files ... scons: done reading SConscript files. [...]
scons: Building targets ... scons: done building targets.

再次运行 QEMU,可以在你的嵌入式镜像中看到结果。

你可以拥有这一切

在你的嵌入式开发中使用 Rust,你可以获得 Rust 的所有功能,而不需要牺牲灵活性或稳定性。今天就在你的嵌入式系统上试试 Rust 吧。关于嵌入式 Rust 的过程(以及 RT-Thread 本身)的更多信息,请查看 RT-Thread 项目的 YouTube 频道。请记住,嵌入式也可以是开放的。


via: https://opensource.com/article/21/10/rust-embedded-development

作者:Alan Smithee 选题:lujun9972 译者:wxy 校对:wxy

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

学习 kubectl,提升你与 Kubernetes 的互动方式。

 title=

Kubernetes 可以帮你编排运行有大量容器的软件。Kubernetes 不仅提供工具来管理(或者说 编排)运行的容器,还帮助这些容器根据需要进行扩展。有了 Kubernetes 作为你的中央 控制面板 control panel (或称 控制平面 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 子命令不仅仅对吊舱和容器有用。它也有关于节点、命名空间、发布、服务和副本的信息。

2、创建资源

如果你只通过类似 OpenShift、OKD 或 Kubernetes 提供的 Web 用户界面(UI)创建过发布,但你想从 Linux 终端控制你的集群,那么可以使用 kubectl create。kubectl create 命令并不只是实例化一个新的应用发布。Kubernetes 中还有很多其他组件可以创建,比如服务、配额和 计划任务。

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 由于 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 速查表,以获得快速参考,其中包括命令示例,以帮助你学习,并在为你提供注意细节。


via: https://opensource.com/article/21/7/kubectl

作者:Alan Smithee 选题:lujun9972 译者:geekpi 校对:turbokernel

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

每种编程语言都有其独特的完成任务的方式,这也说明了为什么有这么多语言可供选择。

 title=

在 Jim Hall 的《不同的编程语言如何完成相同的事情》文章中,他演示了 13 种不同的语言如何使用不同的语法来完成同一个任务。经验是,编程语言往往有很多相似之处。一旦你了解了一种编程语言,你就可以通过理解它的语法和结构来学习另一种。

本着同样的精神,Jim 的文章比较了不同编程语言如何读写数据。无论数据来自配置文件还是用户创建的文件,在存储设备上处理数据都是程序员的常见任务。以这种方式涵盖所有编程语言是不切实际的,但最近的 Opensource.com 系列文章提供了对这些编程语言采用的不同方法的深入了解:

读写数据

用计算机读写数据的过程和你在现实生活中读写数据的过程类似。要访问书中的数据,你首先要打开它,然后阅读单词或将生词写入书中,然后合上书。

当程序需要从文件中读取数据时,你向程序传入一个文件位置,然后计算机将该数据读入内存中并解析它。同样,当程序需要将数据写入文件时,计算机会将新数据放入系统的内存写入缓冲区,然后将其同步到存储设备上的文件中。

下面是这些操作的一些伪代码:

  1. 在内存中加载文件。
  2. 读取文件内容,或将数据写入文件。
  3. 关闭文件。

从文件中读取数据

从 Opensource.com 系列文章的语言中,你可以看到读取文件的三种趋势。

C

在 C 语言中,打开文件可能涉及检索单个字符(直到 EOF 指示符,表示文件结束)或一个数据块,具体取决于你的需求和方法。根据你的目标,它可能感觉像一个主要是手工的过程,但这正是其他语言所模仿的。

FILE *infile;
int ch;

infile = fopen(argv[1], "r");
 
do {
  ch = fgetc(infile);
  if (ch != EOF) {
    printf("%c", ch);
  }
 } while (ch != EOF);

fclose(infile);

你还可以选择将文件的某些部分加载到系统缓冲区中,然后在缓冲区外工作。

FILE *infile;
char buffer[300];
 
infile = fopen(argv[1], "r");

while (!feof(infile)) {
  size_t buffer_length;
  buffer_length = fread(buffer, sizeof(char), 300, infile);
}

printf("%s", buffer);
fclose(infile);

C++

C++ 简化了一些步骤,允许你将数据解析为字符串。

std::string sFilename = "example.txt";

std::ifstream fileSource(sFilename);
std::string buffer;

while (fileSource >> buffer) {
  std::cout << buffer << std::endl;
}

Java

Java 和 Groovy 类似于 C++。它们使用名为 Scanner 的类来设置数据流或对象,这样就会包含你选择的文件内容。你可以通过标记(字节、行、整数等)扫描文件。

File myFile = new File("example.txt");

Scanner myScanner = new Scanner(myFile);
  while (myScanner.hasNextLine()) {
    String line = myScanner.nextLine();
    System.out.println(line);
  }

myScanner.close();

Groovy

def myFile = new File('example.txt')

def myScanner = new Scanner(myFile)
  while (myScanner.hasNextLine()) {
    def line = myScanner.nextLine()
    println(line)
  }

myScanner.close()

Lua

Lua 和 Python 进一步抽象了整个过程。你不必有意识地创建数据流,你只需给一个变量赋值为 open 函数的返回值,然后解析该变量的内容。这种方式快速,最简且容易。

myFile = io.open('example.txt', 'r')

lines = myFile:read("*all")
print(lines)

myFile:close()

Python

f = open('example.tmp', 'r')

for line in f:
    print(line)

f.close()

向文件中写入数据

就写代码来说,写入是读取的逆过程。因此,将数据写入文件的过程与从文件中读取数据基本相同,只是使用了不同的函数。

C

在 C 语言中,你可以使用 fputc 函数将字符写入文件:

fputc(ch, outfile);

或者,你可以使用 fwrite 将数据写入缓冲区。

fwrite(buffer, sizeof(char), buffer_length, outfile);

C++

因为 C++ 使用 ifstream 库为数据打开缓冲区,所以你可以像 C 语言那样将数据写入缓冲区(C++ 库除外)。

std::cout << buffer << std::endl;

Java

在 Java 中,你可以使用 FileWriter 类来创建一个可以写入数据的对象。它的工作方式与 Scanner 类非常相似,只是方向相反。

FileWriter myFileWriter = new FileWriter("example.txt", true);
myFileWriter.write("Hello world\n");
myFileWriter.close();

Groovy

类似地,Groovy 使用 FileWriter,但使用了稍微 “groovy” 的语法。

new FileWriter("example.txt", true).with {
  write("Hello world\n")
  flush()
}

Lua

Lua 和 Python 很相似,都使用名为 open 的函数来加载文件,writer 函数来写入数据,close 函数用于关闭文件。

myFile = io.open('example.txt', 'a')
io.output(myFile)
io.write("hello world\n")
io.close(myFile)

Python

myFile = open('example.txt', 'w')
myFile.write('hello world')
myFile.close()

File 模式

许多语言在打开文件时会指定一个“模式”。模式有很多,但这是常见的定义:

  • w 表示写入
  • r 表示读取
  • r+ 表示可读可写
  • a 表示追加

某些语言,例如 Java 和 Groovy,允许你根据用于加载文件的类来确定模式。

无论编程语言以何种方式来确定文件模式,你都需要确保你是在 追加 数据,除非你打算用新数据覆盖文件。编程语言不像文件选择器那样,没有内置的提示来警告你防止数据丢失。

新语言和旧把戏

每种编程语言都有其独特完成任务的方式,这就是为什么有这么多语言可供选择。你可以而且应该选择最合适你的语言。但是,你一旦了解了编程的基本结构,你可以随意尝试其他语言,而不必担心不知道如何完成基本任务。通常情况下,实现目标的途径是相似的,所以只要你牢记基本概念,它们就很容易学习。


via: https://opensource.com/article/21/7/programming-read-write

作者:Alan Smithee 选题:lujun9972 译者:MjSeven 校对:wxy

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