如何将子 shell 结果(数组)传递给 SSH 命令? [英] How do I pass subshell results (array) to an SSH command?

查看:54
本文介绍了如何将子 shell 结果(数组)传递给 SSH 命令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以这种方式尝试:

#!/bin/bash
myvals=`psql -d mydb -c "select id from table1 where 't'"`

ssh user1@host1.domain.tld "for i in $myvals; do echo \$i >> values; done"

只要 psql 只返回一个值,它就可以正常工作.但是如果它有几个值,我会收到这个回复:

As long as psql returns just one value, it works fine. But if its several values, I receive this response:

bash: -c: line 1: syntax error near unexpected token `2'
bash: -c: line 1: `2'

另外,我尝试:

myvals='1 2 3'

然后它工作正常:值 1 2 3 被附加到远程主机上的值"文件;没有错误信息.如果我尝试另一个子 shell 命令,例如 myvals=ls/bin,错误会再次出现.很明显 $myvals 已经在本地主机上进行了评估,但是是什么让 subshel​​l 结果如此不同?

And then it works fine: the values 1 2 3 are appended to the "values" file on the remote host; no error mesages. If I try another subshell command, such as myvals=ls /bin, errors reappear. It's clear that $myvals is evaluated on the local host already but what makes the subshell results so different?

推荐答案

如果它不是真正的数组...

将字符串当作数组进行迭代是天生的错误.不要这样做. 也就是说,要生成安全转义(eval-safe) 版本的值,使用 printf %q.

If It's Not Really An Array...

Iterating over a string as if it were an array is innately buggy. Don't do it. That said, to generate a safely-escaped (eval-safe) version of your value, use printf %q.

#!/bin/bash

myvals=`psql -d mydb -c "select id from table1 where 't'"`
printf -v myvals_q %q "$myvals"

ssh user1@host1.domain.tld \
  "myvals=$myvals_q;"' for i in $myvals; do echo "$i"; done >>values'

<小时>

如果你真的有一个数组

#!/bin/bash
readarray -t myvals < <(psql -d mydb -c "select id from table1 where 't'")
printf -v myvals_q '%q ' "${myvals[@]}"

ssh user1@host1.domain.tld \
  "myvals=( $myvals_q );"' for i in "${myvals[@]}"; do echo "$i"; done >>values'

<小时>

如果您不需要首先在本地存储值

#!/bin/bash

ssh user1@host1.domain.tld \
  'while read -r i; do echo "$i"; done >>values' \
  < <(psql -d mydb -c "select id from table1 where 't'")

<小时>

一般注意事项

  • 在循环中一遍又一遍地运行 echo "$i" >>values 是低效的:每次运行该行时,它重新打开<代码>值文件.相反,在整个循环中运行重定向>values ;这只会在循环开始时截断文件一次,并附加其中生成的所有值.
  • 未加引号的扩展通常是危险的.例如,如果 foo='*',则 $foo 将替换为当前目录中的文件列表,但 "$foo" 将发出确切的内容——*.同样,制表符、空格符和各种其他内容可能会被不带引号的扩展无意中损坏,即使直接传递给 echo.
  • 您可以在同一个字符串中切换引用类型——因此,"$foo"'$foo' 是一个字符串,其中的第一部分替换为名为 <的变量的值code>foo,其第二部分是 exact 字符串 $foo.

  • General Notes

    • Running echo "$i" >>values over and over in a loop is inefficient: Every time the line is run, it re-opens the values file. Instead, run the redirection >values over the whole loop; this truncates the file exactly once, at the loop's start, and appends all values generated therein.
    • Unquoted expansions are generally dangerous. For example, if foo='*', then $foo will be replaced with a list of files in the current directory, but "$foo" will emit the exact contents -- *. Similarly, tabs, whitespace runs, and various other contents can be unintentionally damaged by unquoted expansion, even when passing directly to echo.
    • You can switch quoting types in the same string -- thus, "$foo"'$foo' is one string, the first part of which is replaced with the value of the variable named foo, and the second component of which is the exact string $foo.
    • 这篇关于如何将子 shell 结果(数组)传递给 SSH 命令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆