bash - 如何在 bash 中编写动态生成的定界文档?

标签 bash shell ssh heredoc

我有一个连接到远程计算机以执行操作的 shell 脚本。其中一项操作是设置一个或多个 DNS 服务器。虽然大部分静态数据很容易捕获并通过 SSH 通过管道传送到远程计算机:

config_ntp()
{
    ssh -T admin@server_ip <<-NTPSERVER
    sysconf ntp addserver $NTPSERVER
    NTPSERVER
}

创建动态大小的命令列表比我想象的要棘手。我有什么:

DNSSERVERS=(8.8.8.8 8.8.8.7)

config_dns()
{
    cmd=""
    for server in ${DNSSERVERS[@]}; do
        cmd+="network dns add nameserver $server$'\n' "
    done
    cmd+="service dns restart$'\n'"
    echo -e "cmd: $cmd"
    ssh -T admin@server_ip $cmd
}

调用的结果:

$ sh setup.sh
cmd: network dns add nameserver 8.8.8.8$'
' network dns add nameserver 8.8.8.7$'
' service dns restart$'
'
Syntax Error: Invalid character detected: '\'.
Command Result : 22 (Invalid argument)
Exiting...

那是我的最新化身。我按照其他地方的建议使用 $'\n'...以前,我只使用 \n,这导致了同样的错误。

如何创建一个包含命令列表(可变长度,动态生成)的变量,以通过 ssh 通过管道传输到远程计算机?

最佳答案

您为什么想要或需要此处的文档?如果它不仅仅是一个带有一些用变量填充的占位符的静态模板,那么通过其他方式向流程提供标准输入几乎肯定会更容易。

ssh <<____HERE
commands
more commands "$variable"
____HERE

完全等同于

printf "commands\nmore commands \"%s\"\n" "$variable" | ssh

如果某些部分比仅仅打印某些内容更复杂,您可以使其任意复杂:

{ complex_function --with --options and arguments  -o stdout
  printf "echo 'anything we send to stdout goes into the pipe'\n"
  if command; then
      while another command; do
          for arguments in $(something to drive a loop); do
               complex stuff
          done
      done
  fi
  : and etc
} | ssh

在管道之前使用大括号(commands)而不是大括号{commands}在子shell中运行commands

您的具体问题是您无法将 $'\n' 放入常规双引号字符串内。 echo 已经产生了一个换行符,因此您似乎正在采取一种非常迂回的方式来构建事物。但试试这个:

# Does this really need to be in a separate variable?
DNSSERVERS=(8.8.8.8 8.8.8.7)
config_dns()
{
    {
      # To be completely correct, notice quoting around array
      for server in "${DNSSERVERS[@]}"; do
        echo "network dns add nameserver $server"
      done
      echo "service dns restart"
    } |
    # maybe add a tee /dev/stderr or something here to see what's going on
    ssh -T admin@server_ip
}

为了美观,我可能会重构

config_dns()
{
    {
        printf 'network dns add nameserver %s\n' "${DNSSERVERS[@]}"
        printf 'service dns restart\n'
    } |
    ssh -T admin@server_ip
}

关于bash - 如何在 bash 中编写动态生成的定界文档?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47805775/

相关文章:

git - Hudson(Jenkins) 和远程 git 存储库获得权限被拒绝

linux - 从脚本运行远程命令

r - 指定在 R 中使用哪个 shell

python - 并行运行 Python Trainer 脚本

linux - 如何使用 python 代码中的变量命令运行 linux cp -r

Java Process.waitFor() 与 Process.exitValue()

bash - Linux pgrep 事件 xsession

linux - 使用 bash 获取特定列的总和?

linux - 从 bash 脚本发送 "ENTER"

linux - 连接到远程网络上的 Raspberry Pi(XFinity 路由器)