合并 bash 个命令/在 bash 中简化一个长命令

Merge bash command(s)/simplification of a long command in bash

您好,我正在制作一个我想要的脚本,通过一个命令可以制作一个更复杂的命令或函数。问题是我有三个 docker 容器,它们具有相同的名称,但只有数字发生变化。只是 docker 容器在日志中有一个条目,这是正确的 Cloudflared URL,我需要通过 子命令 [=36] 来获取它=] 或 函数 超过 1 次。因为我有 三个 docker 个容器 每个容器的 urllogs.

我知道这是通过经典方式进行的!唯一的问题是,如果我重复相同的命令,它会在脚本中造成一点混乱(至少我是这么想的)。

#!/bin/bash
function test {
    docker_container_proxy_name="cloudflared"
    real_domain_of_cloudflared="https://([a-z0-9]{1,60})(-[a-z0-9]{1,60})(-[a-z0-9]{1,60})(-[a-z0-9]{1,60}).trycloudflare.com"
    docker_container_1_uri_outside="$(docker logs ${docker_container_proxy_name}1 2>&1 | grep -Eo $real_domain_of_cloudflared | tail -n 1)"
    docker_container_2_uri_outside="$(docker logs ${docker_container_proxy_name}2 2>&1 | grep -Eo $real_domain_of_cloudflared | tail -n 1)"
    docker_container_3_uri_outside="$(docker logs ${docker_container_proxy_name}3 2>&1 | grep -Eo $real_domain_of_cloudflared | tail -n 1)"
}
test

有什么方法可以像整个长命令一样简化它,但只有docker容器数字 变化。像这样(在我眼里更干净):

#!/bin/bash
function test {
    docker_container_proxy_name="cloudflared"
    real_domain_of_cloudflared="https://([a-z0-9]{1,60})(-[a-z0-9]{1,60})(-[a-z0-9]{1,60})(-[a-z0-9]{1,60}).trycloudflare.com"
    command="$(docker logs ${docker_container_proxy_name} 2>&1 | grep -Eo $real_domain_of_cloudflared | tail -n 1)"
    docker_container_1_uri_outside="${command}1"
    docker_container_2_uri_outside="${command}2"
    docker_container_3_uri_outside="${command}3"
}
test

我很乐意回答。 也许类似的问题已经存在,但我承认我没有寻找它并直接写下我的问题,我很抱歉这可能是一个类似的 post.

Docker 个容器:

$ docker container ps | grep "cloudflared"
<id_of_container> cloudflare/cloudflared:2022.4.1-amd64 "cloudflared --no-au…" 11 days ago Up 2 days cloudflared3
<id_of_container> cloudflare/cloudflared:2022.4.1-amd64 "cloudflared --no-au…" 11 days ago Up 2 days cloudflared2
<id_of_container> cloudflare/cloudflared:2022.4.1-amd64 "cloudflared --no-au…" 11 days ago Up 2 days cloudflared1

#1 for XFCE_noVNC
#2 for filebrowser
#3 for code-server
#i want this services in my "pocket/everywhere" without my public ipv4.

几乎正确:

建议:

#!/bin/bash
docker_container_proxy_name="cloudflared"
real_domain_of_cloudflared="https://([a-z0-9]{1,60})(-[a-z0-9]{1,60})(-[a-z0-9]{1,60})(-[a-z0-9]{1,60}).trycloudflare.com"

function command {
    echo "$(docker logs "${docker_container_proxy_name}" 2>&1 | grep -Eo "$real_domain_of_cloudflared" | tail -n 1)"
}

function test {
    docker_container_1_uri_outside=$(command 1)
    docker_container_2_uri_outside=$(command 2)
    docker_container_3_uri_outside=$(command 3)
}
test

变量是用来存储数据的,不是可执行代码。一般来说,存储可执行代码的最佳方式是在函数中:

#!/bin/bash
get_container_uri() {
    docker_container_proxy_name="cloudflared"
    real_domain_of_cloudflared="https://([a-z0-9]{1,60})(-[a-z0-9]{1,60})(-[a-z0-9]{1,60})(-[a-z0-9]{1,60}).trycloudflare.com"
    docker logs "${docker_container_proxy_name}" 2>&1 | grep -Eo "$real_domain_of_cloudflared" | tail -n 1
}

docker_container_1_uri_outside="$(get_container_uri 1)"
docker_container_2_uri_outside="$(get_container_uri 2)"
docker_container_3_uri_outside="$(get_container_uri 3)"

请注意,该函数只是直接运行 docker logs ... 命令,而不是捕获其输出;这样命令的输出就变成了函数的输出,这正是我们想要的。

此外,一些一般的脚本建议:您应该(几乎)总是将变量引用放在 double-quotes 中(例如 grep -Eo "$real_domain_of_cloudflared"),以防止 shell 以意想不到的方式解析它们。 function 关键字是非标准的;定义函数的标准方法是将 () 放在名称后面(就像我在这里所做的那样)。不要使用 test 作为函数的名称,因为这是一个相当重要的 built-in 命令的名称,覆盖它可能会破坏其他东西。

shellcheck.net 将指出其中的一些(以及许多其他常见错误)。我建议 运行 你的脚本通过它并修复它指出的内容。