我有 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