I have the following script which sets the hostname for a remote host.
#!/bin/bash
ssh -T user@$1 << \EOF1
sudo sh -c "echo "hostname=\"$1\"" >> /etc/rc.conf"
sudo /etc/rc.d/hostname start
EOF1
When I run ./filename.sh host, the hostname isn't populated. How do I pass a variable to remote execution commands?
Parameter expansion is performed in here-docs if the delimiter is entirely unquoted.
So in the here-doc for
ssh -T user@$1 << \EOF1
where the E in the delimiter is quoted, $1 is not expanded: it is passed as $1 to ssh and then to sh. On the remote execution, $1 is replaced with the empty string, since there are no positional arguments.
If you don't quote the E, the $1 will be expanded in the here-doc:
ssh -T user@$1 << EOF1
I might write this as
printf 'hostname="%s"\n' "$1" | ssh -T user@"$1" <<\EOF1
sudo tee -a /etc/rc.conf > /dev/null
sudo /etc/rc.d/hostname start
EOF1
to simplify the quoting. ssh passes its standard input to the remote shell, from which tee inherits its standard input. Now you can safely quote the here document, because it is independent of the value of $1.
It's also safer, as now $1 is no longer an opening for code injection. It's just data input to the script, rather than code that is part of the script.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With