关于bash:如何在heredoc部分中设置和扩展变量

How to set AND expand variables in a heredoc section

我有一个HereDoc,需要从主脚本调用现有变量,并设置自己的变量供以后使用。像这样:

1
2
3
4
5
6
7
8
9
10
count=0

ssh $other_host <<ENDSSH
  if [["${count}" =="0" ]]; then
    output="string1"
  else
    output="string2"
  fi
  echo output
ENDSSH

这不起作用,因为"输出"没有设置为任何内容。

我尝试使用这个问题的解决方案:

1
2
3
4
5
6
7
8
9
10
count=0

ssh $other_host << \ENDSSH
  if [["${count}" =="0" ]]; then
    output="string1"
  else
    output="string2"
  fi
  echo output
ENDSSH

它也不起作用。$output设置为"string2",因为$count未展开。

如何使用从父脚本扩展变量并设置自己变量的HereDoc?


你可以使用:

1
2
3
4
5
6
7
8
9
10
11
count=0

ssh -t -t"$other_host" << ENDSSH
  if [["${count}" =="0" ]]; then
    output="string1"
  else
    output="string2"
  fi
  echo"\$output"
  exit
ENDSSH

我们使用\$output,以便在远程主机上扩展,而不是在本地扩展。


最好不要使用stdin(例如使用here docs)将命令传递给ssh

如果使用命令行参数来传递shell命令,则可以更好地分离本地展开的内容和远程执行的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Use a *literal* here-doc to read the script into a *variable*.
# Note how the script references parameter $1 instead of
# local variable $count.
read -d '' -r script <<'EOF'
  [[ $1 == '0' ]] && output='zero' || output='nonzero'
  echo"$output"
EOF


# The variable whose value to pass as a parameter.
# With value 0, the script will echo 'zero', otherwise 'nonzero'.
count=0

# Use `set -- '$<local-var>'...;` to pass the local variables as
# positional parameters, followed by the script code.
ssh localhost"set -- '$count'; $script"


您可以像@anubhava所说的那样对变量进行转义,或者,如果您有太多的变量需要转义,您可以分两步进行转义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# prepare the part which should not be expanded
# note the quoted 'EOF'
read -r -d '' commands <<'EOF'
if [["$count" =="0" ]]; then
    echo"$count - $HOME"
else
    echo"$count - $PATH"
fi
EOF


localcount=1
#use the unquoted ENDSSH
ssh me@nox.local <<ENDSSH
count=$localcount # count=1
#here will be inserted the above prepared commands
$commands
ENDSSH

将打印如下内容:

1
1 - /usr/bin:/bin:/usr/sbin:/sbin