一种 shell 脚本很酷的写法——多行字符串变量

在看 Kubernetes 的文档时,看到一种定义多行字符串作为变量的写法,感觉挺有意思,如下:kubectl apply -f - <<EOFapiVersion: v1kind: Podmetadata: name: private-image-test-1spec: conta

在看 Kubernetes 的文档时,看到一种定义多行字符串作为变量的写法,感觉挺有意思,如下:

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: private-image-test-1
spec:
  containers:
    - name: uses-private-image
      image: $PRIVATE_IMAGE_NAME
      imagePullPolicy: Always
      command: [ "echo", "SUCCESS" ]
EOF

# Create a secret with several keys from stdin
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  password: $(echo -n "s33msi4" | base64 -w0)
  username: $(echo -n "jane" | base64 -w0)
EOF

看起来很是牛逼的感觉,实际上也避免了一些不必要的文件创建、可以让命令更加地精简。

Here document

Wikipedia 定义

In computing, a here document (here-document, here-text, heredoc, hereis, here-string or here-script) is a file literal or input stream literal:
it is a section of a source code file that is treated as if it were a separate file. The term is also used for a form of multiline string literals that use similar syntax, preserving line breaks and other whitespace (including indentation) in the text.

简单理解

它是一种特殊的表达方式,它本质上是源代码的一部分,但是表现出来像是真的从独立文件里面获取到的一样。

格式:

[n]<<word
    here-document
delimiter
  • n 为文件描述符,省略是默认为0,即标准输入;
  • word 被引号括住,不解析变量、数据计算等;
  • << 不省略 ;<<- 会忽略 。

worddelimiter 被称为 here tag,它们之间的文字叫做 here doc

使用场景示例

下面几种是 here doc 的常见使用模板

多行输出

cat << EOF
heredoc> biubiubiu
heredoc> bala
heredoc> EOF

# 输出
biubiubiu
bala

定义多行变量

sql=$(cat <<EOF
SELECT foo, bar FROM db
WHERE foo='baz'
EOF
)

echo $sql

# 输出
SELECT foo, bar FROM db
WHERE foo='baz'

将多行数据重定向到文件

cat <<EOF > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
EOF

cat print.sh

# 输出
#!/bin/bash
echo $PWD
echo /Users/feiv

将多行数据通过管道传递给后续命令

cat <<EOF | grep 'b' | tee b.txt
foo
bar
baz
EOF

# 输出
bar
baz

思考与尝试

here tag 即常用的 EOF 是只要求前后匹配即可,不一定非得要 EOF,如下:

cat << BALABALA
biubiubiu
bala
BALABALA

# 输出
biubiubiu
bala

关于引号把 word 括起来的效果,可以参考如下示例:

a=0
cat <<EOF
$a
EOF

# 输出
0

#################

a=0
cat <<'EOF'
$a
EOF

# 输出
$a

#################

a=0
cat <<"EOF"
$a
EOF

# 输出
$a

cat 后面其实可以接多个 << word,但目前还未发现其用途,如下:

cat <<eof1; cat <<eof2
Hi,
eof1
Helene.
eof2

Reference

Read more

容器镜像(4):镜像的常用工具箱

容器镜像(4):镜像的常用工具箱

前几篇在讲多架构镜像时已经用过 skopeo 和 crane 做镜像复制,这篇系统整理这两个工具的完整能力,同时介绍几个日常操作镜像时同样好用的工具。 一、skopeo:不依赖 Daemon 的镜像瑞士军刀 skopeo 的核心价值是绕过 Docker daemon,直接与 Registry API 交互。上一篇用它做镜像复制和离线传输,但它的能力远不止于此。 1.1 安装 # Ubuntu / Debian sudo apt install -y skopeo skopeo --version # skopeo version 1.15.1 1.2 inspect:免拉取检查镜像元数据 docker inspect 需要先把镜像拉到本地,skopeo inspect 直接向 Registry

容器镜像(3):多架构镜像构建

容器镜像(3):多架构镜像构建

一、什么是多架构镜像 1.1 OCI Image Index 上一篇介绍了单平台镜像的结构:一个 Manifest 指向 Config 和若干 Layer blob。多架构镜像在此之上多了一层——OCI Image Index(也叫 Manifest List),是一个轻量的索引文件,把多个单平台 Manifest 组织在一起: $ docker manifest inspect golang:1.22-alpine { "schemaVersion": 2, "mediaType": "application/vnd.oci.image.index.v1+json", "manifests&

容器镜像(2):containerd 视角下的镜像

容器镜像(2):containerd 视角下的镜像

一、为什么需要了解 containerd 如果你只用 docker run 跑容器,从来不关心底层,那可以不了解 containerd。但如果你在用 Kubernetes,或者想真正理解"容器运行时"是什么,containerd 是绕不开的。 事实上,当你执行 docker run 的时候,containerd 早就在后台悄悄工作了——Docker 从 1.11 版本开始,就把核心运行时剥离出来交给 containerd 负责。 1.1 Docker 的架构演变 早期的 Docker(1.10 及之前)是一个"大一统"的单体程序:一个 dockerd