
本文初衷是要专注在 Docker 内的应用进程如何与外部发过来的 Linux 信号进行响应。具体应用在当运行为一个 ECS 的 Docker 容器时,对 ECS 的 AutoScaling 以及部署时如何让应用能正确收到相应的信号。可是一提及这一话题,思维就产生了极大的发散,很想好好捋一捋进程与 Linux 信号之间关系和相关的概念。 关于 Linux 的 Signal 请参考 Wikipedia 的 Signal(IPC).
本文以渐进的方式,从信号的简介,本地 C, Bash, Java 程序与信号,然后将在下一篇学习本地 Docker 容器内进程与信号的处理,ECS 的容器与 ASG,部署行为的信号响应。
Read More
本想用一篇日志记录下在 Docker 容器中使用 Java 调用 C++ 动态库时,当 C++ Crash 时如何自动生成 core dump, 不想分成了至少三篇来完成这一研究。 可以回顾一下前两篇日志
本文是基于第二篇进一步推进,继续探索如何在 Docker 容器中 Java 调用 C++ 动态库时的 core dump 如何生成。首先测试的平台依然是 AWS EC2 实例, OS 为 Amazon Linux 2023, Docker 版本为 25.0.14。为叙事方便,本文所用代码与上篇一样,但还是重复一遍,省却了连接跳转。
Read More
在 Java 应用程序通过 JNA 调用 C++ 动态库时,C++ 代码运行在与 Java 同一进程中,当 C++ 代码 Crash 的时候,将会导致整个 Java 应用程序崩溃。 对于一个 Web 应用,这不是我们期望的结果,由于某一个请求输入的数据导致 C++ 代码崩溃了当前 Java 进程,从而造成该 Web 服务已接受到的所有请求全部失败, 这是非常糟糕的用户体验。如果是 Java 代码本身的异常我们可用 try/catch 进行保护,影响只限制在当前请求。如果是 C++ 代码崩溃的话,Java 应用程序无法捕获到这个异常,以致于整个 Java 应用程序崩溃,甚至发生这种情况时连 hs_err.log 文件都来不及生成,更别说生成 HeapDump, 或 CoreDump 了。
如果是用原始 JNI 的方式来调用动态库,我们还能在 JNI 相关的 C++ 代码中捕获到异常,并抛给 Java 去处理。而用 JNA, 我们贪图了它的方便, 比如一个 Java 进程中同时加载同一接口的不同动态库版本(JNI 要同样的实现必须用自定义的 ClassLoader),但在 C++ 代码崩溃时, Java 就显得无能为力了, 只能跟随着立即死亡, 并且在控制台下找不到关于 C++ 因何失败的线索。比如 C++ 中内存被多次释放,或地址越界访问破坏了内存数据等。
Read More
本文初衷是为了解决 Java 应用程序通过 JNA 调用 C++ 动态库时,C++ 代码运行崩溃导致整个 Java 应用程序崩溃而进行的研究。从一个 C++ 调用 C++ 写的动态库起步,记录它在什么情况下产生 core dump 文件,如何分析 core dump 文件等过程。可惜篇幅无法控制,不足以再加入 Java->JNA->C++ 动态库内容了,所以不得不单列此篇,并更名为 'C++ 调用 C++ 动态库时问题诊断'. 关于 Java JNA 到 C++ 的问题诊断只能另立一篇了。
下面我们来用 JNA 的方式来调用 C++ 动态库,演示当 C++ 代码崩溃时会发生什么,并试图找到好的诊断办法。以下演示在 Linux 下进行, 并且 Linux 发行版是 Amazon Linux 2023.
Read More
前年记录过一篇 创建可直接用 root 用户 ssh 登陆的 Docker 镜像, 采用了基础镜像是 Ubuntu:20.04. 因为在 AWS 使用 AmazonLinux 2023 更为频繁,为贴近生产环境,本地开发也使用基本 AmazonLinux 2023 为基础镜像的容器,与 IDE 连接以 SSH 协议, 容器的操作由自己的控制,而非直接使用 devcontainer 的方式。比如可以在 Windows 或 macOS 进行 Linux 相关的开发。
当今 Linux 主要还是两个发行版,一个是 RedHat 的家族,一个是 Debian 的家族,之前验证过 Debian 族的 Ubuntu, 这次要验证 RedHat 族的 AmazonLinux 2023, 也作为将来不时之需。
创建允许 root + 密码登陆的镜像
Dockerfile 内容为
Read More
各种 AI 编程工具,如 Codex, Claude Code, Gemini 等提供了一些类似的斜线命令,每个斜线命令大约也是对应着一段特定的提示词。由于工作中更方便的使用 Copilot, 所以本文来探讨如何定义自己的 Copilot 斜线命令。比如想要定义一个命令
/c2py-dataclass用于实现把 C/C++ 的类或结构转换成 Python 的 @dataclass 类,并遵循 Python 的命名规则和设置默认字段值, 也就是采用如下提示词Covert following C/C++ class/struct to Python dataclass, following Python naming convention, and set default field values.
<C/C++ source code goes here>
有了自定义的
/c2py-dataclass命令的话,就不需要每次重复上面的描述,而只用输入/c2py-dataclass然后指定某个 C++ 代码文件或粘贴 C/C++ 代码就能实现转换需求。实现方式可以借鉴几天前写的一篇 准备迎接 Vibe Coding - 相关工具与资源 中关于 Spec Kit 一节。
实现方法
开门见山吧,想要添加一个自定义的命令,如
/c2py-dataclass, 仅需在项目目录中添加.github/prompts/c2py-dataclass.prompt.md文件, 立马就会在 Copilot 中出现一个/c2py-dataclass命令,在.github/prompts/c2py-dataclass.prompt.md添加所需的提示词即可。要像
Read MoreSpec Kit那样的话可以使用两个文件.github/agents/c2py-dataclass.agent.md和.github/prompts/c2py-dataclass.prompt.md来配合。
最近在紧锣密鼓的用 Python 写代码,不是 Vibe Coding 那种,因为在真实的敲代码才能碰到一些与 Python 语言相关且容易踏入的坑,记录如下
Python 3.8 引入的 Walrus 操作
即赋值表达式,
:=的使用形式,像海象的两个牙。:=让赋值有了返回值, 该赋值语句的返回值就是右边的值。C/C++ 的=同时具有 Python 的=和:=的功能。我们在 Python 中的
=与:=对比1>>> print(a=1) 2Traceback (most recent call last): 3 File "<python-input-0>", line 1, in <module> 4 print(a=1) 5 ~~~~~^^^^^ 6TypeError: print() got an unexpected keyword argument 'a' 7>>> print(a:=1) 81Python 的这种赋值又有返回值的
Read More:=功能就可以应用到if或while语句中,例如
前篇 MacOS/Linux C++ GDB 远程调试基础 演示了如在 macOS 开发调试远程 Linux 下的 C++ 程序, 本篇将结合 C 语言静态库与动态库的生成和使用 练习如何调试含动态库,静态库的 C++ 程序, 并了解如何指定符号文件。
示例源码
本文将用以下的目录结构, 分别验证主程序与动态库,静态库的源代码断点调试,以及把源文件放在不同目录中是否有特别之处。
Read More1├── dynamic # 动态库 2│ └── add.cpp 3├── static # 静态库 4│ └── sub.cpp 5└── main.cpp # 主程序
有那么一个古老的项目,编译用的是 g++, 目标平台的是 Linux x86_64, 构建工具是 make. 本地开发环境是 macOS, 硬件为 Arm64 的苹果芯片 M4, IDE 尝试用 CLion, 如果喜欢的话,也可以选择 VSCode.
想要单步调试的目的就是想让代码跑起来,然后逐步理解代码执行的逻辑。所以不想对现有项目构建过程进行改造,如换成 CMake, 使用 LLVM 编译之类的。 只想使用远程 Linux 机器, 仍然使用原来的
make命令编译,然后在 Linux 下启动程序,由 Clion 连到的 Linux 上进程, 关联源代码进行调试。因为编译用的 g++, 所以采用 gdbserver 和 gdb 进行远程调用,llvm 相应的解决方案是 lldb-server + lldb. 下面是关键的步骤
. 本地 Clion 中编辑代码 . 代码传到远程 Linux 机器 . 远程 Linux 机器上编译,编译的二进制代码要保留符号信息 . 在 Linux 机器上的符号文件要下载给 Clion . 在远程用 gdbserver 指定端口启动程序 . 本地 Clion 配置用 GDB 连接到远程 Linux 机器上的 gdbserver . 在 Clion 中断点单步调试
上面是基本的操作,当我们用某个客户端工具(比配置运行 Clion 的 Remote GDB Server) 就自动完成以上的某些操作,如自动双向同步源代码与二进制/符号文件, 自动驱动远程端的的编译,启动 gdbserver. 远程 Linux 还能进一步使用 Docker 容器替代。但是在苹果芯片的 macOS 中启动
Read Morex86_64的容器中运行的gdbserver在 macOS 中用 gdb 是连不上的。
前端框架目前基本还是 Vue.js 和 React.js 两大阵营为主流,尽管 Angular.js 版本升的飞快, 事实就是鲜有人问津, 想用 Angular.js 的人何不直接用 Vue.js 呢. 关于 Vue.js 和 React.js 的数据显示, Vue.js 延续了传统模板(如 JSP, Velocity, Freemarker, Thymeleaf)的用法, 通过自定义 Tag, 许多逻辑写到 HTML 里. 而 React.js 则另辟蹊径, 通过 JSX 语法将 HTML 直接写到 JavaScript 里, 页面显示时不夹杂逻辑.
以前算是用 Vue.js 做过一些小项目, 对 React.js 未有多少了解, 现在也算是初学. 刚开始不想从一个
npx create-react-app my-react-app的脚手架开始, 而是想从最原始的 HTML 中引入 React.js 的方式开始学习, 这样可以更清晰地了解 React.js 的工作原理. 也是为使用 React.js 拥抱 Vibe Coding 做准备.基本 React.js Virtual DOM 渲染
用
Read More<script>标签引入 react 和 react-dom 两个核心库的方式已经不推荐了, 官方的 CDN Links 已经变成 Legacy 了, 也找不到引用 react@19 的相关链接了. 但本着要明就里的原则还是希望以这种方式演练一下.