我可以在此处文档中使用 Bash 脚本逻辑吗?

我可以在此处文档中使用 Bash 脚本逻辑吗?

我有 50 个 Linux 服务器的列表,我需要通过 SSH 访问这些服务器并检查 .conf 文件中的键值对配置参数是否已设置。我需要检查键值对是否存在。如果键值对确实存在,我需要将布尔值修改为FALSE。如果键值对不存在,我需要创建值设置为 FALSE 的键值对。

我对 SSH 部分以及使用此处文档在远程服务器上执行命令列表没有任何问题。然而,这个特定的解决方案需要远程服务器上的一些 bash 逻辑来检查键值对并根据结果执行操作。有没有办法将 bash 脚本逻辑合并到此处文档中?如果没有,处理这种特殊情况的替代方法是什么?

我想我可以在每台服务器上都有一个 bash 脚本,然后从此处文档中调用该脚本,该脚本在远程服务器上执行我需要的逻辑,但我希望找到一个不需要额外文件并在 50 上管理所述文件的解决方案服务器。

下面的示例代码显示了我正在考虑使用一些伪代码实现的逻辑。预先感谢您的帮助和建议。

#! /bin/bash

SERVER_LIST=/path/to/servers_list.txt

for server in $(cat ${SERVER_LIST}); do
    ssh ${server} <<CommandList
    # if key-value pair exists in my.conf
        # modify value to FALSE
    # else
        # add key-value pair with value set to FALSE
CommandList
done

配置文件示例

[general]
setting1 = true
setting2 = false
setting3 = true

答案1

正如评论中所说,更好的解决方案是使用ansible.

另一种解决方案是保留现有的特雷多克,并正确解析您的TOML文件,您可以使用awk

要测试setting3它是否是false或是否是true(然后,您可以在 in 之后应用任何逻辑if/then/else/fi):

#! /bin/bash

while read -r server; do
    ssh ${server} <<'CommandList'
    if awk '($1 == "setting3"){exit ($3 == "true") ? 0 : 1}' file.toml; then
        echo "true case"
    else
        echo "false case"
    fi
CommandList
done < /path/to/servers_list.txt

如果您更喜欢真正的TOML解析器而不是awk

perl -MTOML::XS -MFile::Slurper -E '
  my $file = shift;
  my $toml = File::Slurper::read_binary($file)
    or die "arg1 need to be TOML file\n";
  my $struct = TOML::XS::from_toml($toml)->to_struct();
  if ($struct->{general}->{setting3}) {
    say "true";
    exit 0;
  }
  else {
    say "false";
    exit 1;
  }
' file.toml

另一个TOML解析器是 Python 实现yq(该go版本不解析TOML):蟒蛇yq


编辑到位,你可以使用

gawk -i inplace .......

答案2

使用<<something将解释一些内容,直到在行首看到“某物”。

例如,您可以$var将其解释为 $var 值并替换为 $var 值,也可以$( some shell script here possibly multiline, or with ; or with pipes, all will be interpreted and the resulting output placed as its place in the heredocument )

举个例子:

cat <<EOF
  Hello, I am process $$ running on $( hostname ), and here is a few informations about it:
$( printf "%s\n" "$PATH" | tr ':' '\n' | while read dir; do
    printf "PATH entry %-40s: is on %s filesystem" "$dir" "$( df "$dir" | tail -n 1  | awk '{print $NF}' )"
   done
)
EOF

# this will output something like :
Hello, I am process 25592 running on myhostname, and here is a few informations about it:
PATH entry /usr/local/bin                          : is on / filesystem
PATH entry /usr/bin                                : is on /usr/bin filesystem
...

这个例子很糟糕,但只是为了说明 shell 确实在heredoc内部进行解释。

如果你不想解释,你可以使用:<<'something'

cat <<'EOF' # only line different from previous ex.
  Hello, I am process $$ running on $( hostname ), and here is a few informations about it:
$( printf "%s\n" "$PATH" | tr ':' '\n' | while read dir; do
    printf "PATH entry %-40s: is on %s filesystem\n" "$dir" "$( df "$dir" | tail -n 1  | awk '{print $NF}' )"
   done )
# will output:
  Hello, I am process $$ running on $( hostname ), and here is a few informations about it:
$( printf "%s\n" "$PATH" | tr ':' '\n' | while read dir; do
    printf "PATH entry %-40s: is on %s filesystem\n" "$dir" "$( df "$dir" | tail -n 1  | awk '{print $NF}' )"
   done )

是的, cat <<something我们可以在线上做其他事情,例如对输出的heredoc的一些内容进行着色:

cat <<something | grep -E --color=always '^|this_will_be_red|this_too'
blah blih
and this_will_be_red ...
and other things
and this_too will be red
foo bar
something

相关内容