I have an obvious problem with quoting in bash such that I couldn't really solve for a while. Here is a loop with executing a remote command in a sudo-subshell on a remote server via ssh:
for HOST in $RUNNER_LIST; do
ssh -t $HOST "sudo bash -c \"sed -i '$a 10.10.40.29 myhost' /etc/hosts\""
done 2>/dev/null
Now, this simple approach, of course, doesn't work. That $a gets expanded by the local shell, and since that's an unset variable sed executes the expression ' 10.10.40.29 myhost'
I've tried out several approaches, and during writing this question, I somehow found out that this worked:
ssh -t $HOST "sudo bash -c \"sed -i '"'\$'"a 10.10.40.29 myhost' /etc/hosts\""
and using prepended set -x, I see that on the remote shell, it's expanded to
sudo bash -c 'sed '\''$a 10.10.40.29 myhost'\'' /etc/hosts'
I was surprised since my intention was to escape $. Instead of it, the quotes got escaped. So I would like to have a clear explanation of how this expansion worked. And maybe there is a way to make this command more readable?
bash -c? Why notsudo sed …? (2) How can I single-quote or escape the whole command line in Bash conveniently? – Kamil Maciorowski Feb 28 '22 at 22:01bash -cin this loop because usually I want to execute a command group as root, for instancebash -c "yum update -y && reboot"– Danny Lo Mar 01 '22 at 11:04sed '$ a blah'because shell won't treat that as a variable but sed will treat it as a valid command. Or can doecho 10.1.2.3 name | sudo tee -a /etc/hostswhich doesn't need any$or internal quoting. – dave_thompson_085 Mar 05 '22 at 09:57