Trying it this way:
#!/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"
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'
Also, I tried to:
myvals='1 2 3'
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?
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
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. 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
. "$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
. You can send the output as a file:
#!/bin/bash
psql -d mydb -c "select id from table1 where 't'" > /tmp/values
scp values user1@host1.domain.tld:/tmp/
or pipe it to the remote host:
psql -d mydb -c "select id from table1 where 't'" | \
ssh user1@host1.domain.tld 'while read line; do echo $line; done'
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.