Tag: linux

7 notes found.

当 Kubernetes 将 ConfigMap 挂载为 volume 时,pod 内的文件其实是 symlink,直接 kubectl cp 会跳过所有文件导致拷不出内容。用 kubectl exec + tar 管道即可复制真实文件。

问题

# 这样拷贝会失败:目录内全是 symlink,无 .conf 文件落地
kubectl cp platform/${POD}:/app/config/ /home/laborant/config/

warning: skipping symlink: "/home/laborant/config/server.conf" -> "..data/server.conf"
# ...
# kubectl cp 退出码为 0 却什么都没拷出来

原因:kubectl cp 内部用 tar 流式传输,但没传 --dereference。挂载路径下的条目全是 symlink,tar 视其为符号链接而跳过。kubectl cp 即使失败也返回 0,必须 ls 验证结果。

解决方案

在 pod 内部 tar 打包(内核 VFS 透明解析 symlink),再管道给本地 tar 解包:

# 左侧在 pod 内打包并写 stdout,右侧本地解包并剥离前两级路径
kubectl exec -n platform "$POD" -- tar cf - /app/config \
  | tar xf - --strip-components=2 -C /home/laborant/config
  • --strip-components=2:去掉 app/config 两级前缀,只留裸文件名
  • tar xf -:从 stdin 读取归档,-C 指定解包目录
ls /home/laborant/config/
# database.conf  feature-flags.conf  logging.conf  server.conf

通用注意点与变体

  • exec 不要加 -t(TTY):TTY 会对输出做换行转换,污染二进制归档流;无 TTY 的 exec 才是干净的 stdin/stdout 回传
  • -C 目标目录必须先存在tar 不会自动创建目录,会报 Cannot open 之类错误,先 mkdir -p /home/laborant/config
  • 等价写法:左侧 tar cf - -C /app config 时归档成员只有 config/... 一级前缀,右侧只需 --strip-components=1;与”绝对路径 + strip 2”语义等价,任选一种保持一致
  • 压缩变体:网络较慢时左侧 tar czf -(gzip 压缩),右侧 tar xzf - 解压
  • 依赖:Pod 内需装有 tar(busybox/distroless 镜像可能没有,报 exec: tar: not found);本地的 --strip-components 由 GNU tar / bsdtar 提供,macOS / Linux 均有
  • 权限:非 root 解包时文件 owner 会变成当前用户(tar 仅在 root 下默认保留 owner),通常无碍

获取运行中的 pod 名

POD=$(kubectl get pod -n platform \
  -l app=config-service \
  -o jsonpath='{.items[0].metadata.name}')
原子更新机制:两层级联导致 kubectl cp 失效

ConfigMap 以 volume 挂载时,目录结构是两层间接:

/app/config/
├── ..2026_08_19_10_19_29.2041564214/   ← 真实目录,存真实字节
├── ..data -> ..2026_08_19_10_19_29.2041564214   ← 指向真实目录
└── server.conf -> ..data/server.conf    ← 每个文件都是 symlink
  • 权限串首字符 l 表示 symlink(lrwxrwxrwx
  • kubelet 更新 ConfigMap 时写入新时间戳目录,再通过一次原子 rename() 重指 ..data,保证运行中的 pod 立即看到新内容且不出现新旧混合
  • tar 默认不跟随 symlink,kubectl cp 因此全部跳过

/usr/bin/env 是 Unix/Linux 系统中用于查找并运行程序的工具,主要用于 Shebang 中以提高脚本可移植性。

核心作用与用法

核心作用:提高脚本的可移植性

1. 硬编码路径(不推荐)

#!/usr/bin/python3 - 直接指定路径,跨系统兼容性差。

2. 使用 env(推荐)

#!/usr/bin/env python3 - 在 $PATH 中搜索,兼容性极佳。

工作流程

  1. 内核读取 Shebang,运行 env
  2. env 查看 $PATH 环境变量
  3. 按顺序搜索 python3
  4. 找到后启动该程序

对比表

特性直接路径使用 env
可移植性极佳
虚拟环境支持不支持完美支持
灵活性

进阶技巧:临时设置环境变量

# 临时设置语言
env LANG=en_US.UTF-8 check_system_status

# 查看所有环境变量
env

注意事项

env 不支持传递多个参数,如 #!/usr/bin/env python3 -u 在旧系统上可能失效。

配置方法

在所有的 git 全局配置中,配置:

# Configure Git to ensure line endings in files you checkout are correct for macOS
git config --global core.autocrlf input

或者在对应的 ~/.gitconfig 中配置:

[core]
	autocrlf = input

但是 github 推荐在 windows 中将这个选项设置为 true,我查了下觉得在三端均采用 input 是非常合理的。

配置说明

配置值含义
true双向转换:
 • 输入(commit)时:CRLF → LF
 • 输出(checkout)时:LF → CRLF
input仅输入时转换:
 • 输入(commit)时:CRLF → LF
 • 输出(checkout)时:不做转换(保留 LF)
false完全不转换

参考链接:https://docs.github.com/en/get-started/git-basics/configuring-git-to-handle-line-endings?platform=linux

vps 内存爆炸了,上来查原因,使用 bottom 查看之后发现是 uwsgi 进程占用高内存,但我印象中我是我没有部署类似的服务的,因为我基本都是使用 docker 来部署的。

通过 cgroup 信息定位问题

Linux 通过 cgroup 来管理容器资源,每个进程都会记录自己属于哪个 cgroup。我们可以利用这一点来找到它所属的容器。

  1. 找到 uwsgi 进程的 PID (Process ID)

    pidof uwsgi

    这个命令会返回一个或多个数字,就是 uwsgi 的进程 ID。我们假设返回的是 12345

  2. 查看该 PID 的 cgroup 信息

    cat /proc/12345/cgroup

    在输出中,你会看到类似下面这样的行:

    11:perf_event:/docker/a1b2c3d4e5f6...
    10:cpuset:/docker/a1b2c3d4e5f6...
    ...
    1:name=systemd:/docker/a1b2c3d4e5f6...

    注意 /docker/ 后面那串以 a1b2c3d4e5f6 开头的字符串,这就是容器的完整 ID

  3. 根据容器 ID 找到容器名

    docker inspect a1b2c3d4e5f6 | grep "Name"

    或者更简单地,列出所有容器,手动找到这个 ID:

    docker ps

    CONTAINER ID 列中找到对应的 ID,它旁边的 NAMES 列就是你容器的名字,例如 my-web-app

小技巧: 你可以组合成一条命令,一步到位: cat /proc/$(pidof uwsgi)/cgroup | grep -o '[0-9a-f]\{64\}' | xargs -I {} docker inspect {} | grep "Name"