1

I am trying to append a multiline text containing some single quotes(') to a file which is present on a different machine and can be only accessed through a different user. Here is my code snippet:

element_list=("element1" "element2")
for element in ${element_list[@]} 
do

read -r -d '\n' CONTENT << EOM
field1 = on
field2 = '$element'
field3 = '$element-random-text'
EOM

    CONFIG_FILE=/tmp/config.txt
    sshpass -p vm_password ssh -t vm_user@<vm-ip> "sudo su - other_user -c 'echo \"$CONTENT\" >> $CONFIG_FILE'"

done

Though, the scripts execute successfully, the single quotes present in the field2 and field3 values disappear. The output appended to the file looks like:

field1 = on
field2 = element1
field3 = element1-random-text
field1 = on
field2 = element2
field3 = element2-random-text

I want those single quotes to dumped in the file too. Expected output:

field1 = on
field2 = 'element1'
field3 = 'element1-random-text'
field1 = on
field2 = 'element2'
field3 = 'element2-random-text'

Any help would be appreciated.

Note: There is a requirement to execute this command from a different machine and using the other_user(not the vm_user).

Kalit Inani
  • 59
  • 1
  • 10
  • The single quotes are matching the `'` before `echo`. – Barmar Apr 26 '23 at 15:43
  • Mixing `ssh` and `sudo` commands like this is going to be tricky, because there are so many levels of quoting required, and they don't nest cleanly. – Barmar Apr 26 '23 at 15:48
  • Right @Barmar, but this is the requirement. I cannot execute this script on the same machine and only the other_user can write to the CONFIG_FILE. – Kalit Inani Apr 26 '23 at 15:52
  • Do you have to do it with `echo`? Can't you copy the content as a file to the remote machine? – Barmar Apr 26 '23 at 15:56
  • I have to append to an existing file present on the other machine. The existing file cannot be completely overritten. – Kalit Inani Apr 26 '23 at 15:59
  • I never said otherwise. `scp filename remote:/tmp/new; sudo other_user "cat /tmp/new >> $CONFIG_FILE"` – Barmar Apr 26 '23 at 16:06
  • Learn to check your code at https://shellcheck.net . If that doesn't fix it, then used updated code in your question. Good luck. – shellter Apr 26 '23 at 17:56

1 Answers1

3

A much simpler solution is to perform all the expansion locally, and then just write the result at the end of the pipeline.

config_file=/tmp/config.txt
element_list=("element1" "element2")
for element in "${element_list[@]}"
do
    read -r -d '\n' content <<____EOM
field1 = on
field2 = '$element'
field3 = '$element-random-text'
____EOM
    echo "$content"
done |
sshpass -p vm_password ssh -t vm_user@<vm-ip> "sudo su - other_user -c \"cat >> '$config_file'\""

Capturing the here document only so you can then immediately echo it is obviously a waste of memory; I imagine your real loop body looks more involved.

Don't use upper case for your private variables; see Correct Bash and shell script variable capitalization. For robustness, I also added double quotes around ${element_list[@]}; see When to wrap quotes around a shell variable

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Thanks, this was helpful. An additional change which was required was wrapping the command sudo su - other_user -c "cat >> '$config_file'" in double quotes. Final command looked like: sshpass -p vm_password ssh -t vm_user@ "sudo su - other_user -c \"cat >> '$config_file'\"" – Kalit Inani Apr 27 '23 at 04:38
  • I removed unnecessary quotes around the `sudo su` command to simplify the command line. There are no shell metacharacters in the command so `ssh` will happily allow you to reduce the quoting. – tripleee Apr 27 '23 at 04:39
  • I tried without quotes at first, but it gave this error: `bash: /tmp/config.txt: Permission denied.` Wrapping the entire command in double quotes fixes this though. Maybe it is because I have used `ssh -t` – Kalit Inani Apr 27 '23 at 04:44
  • Ahhh I see, the `sudo` command needs to be separately quoted to prevent the remote shell from attempting to append to the file before getting privileges. I'll update the answer - thanks for the feedback! – tripleee Apr 27 '23 at 04:46