0

Here's the problem.
I'm trying as "root" user to execute a command as "myusername" user.

That's why I'm using su - $USERNAME -c <command>
The <command> itself is something like sudo sed -i 's|SEARCH_REGEX|REPLACEMENT|' /etc/cloud/cloud.cfg

But each time I execute my script I got an error which seems to be due to the REPLACEMENT part.
I guess this is something around carriage return or spaces.

Here's the code:

#!/bin/bash
$USERNAME="myusername"
$USERPWD="p@ssw0rd123"
PATTERN='s|preserve_hostname:\sfalse|preserve_hostname: true\nmanage_etc_hosts: false|'
su - $USERNAME -c 'sudo -S bash -c "sed -i '$PATTERN' /etc/cloud/cloud.cfg"' <<< $USERPWD

And here's the error I get:

 true\nmanage_etc_hosts:: -c: line 0: unexpected EOF while looking for matching `"'
 true\nmanage_etc_hosts:: -c: line 1: syntax error: unexpected end of file

The ressources that helped me:
https://linuxize.com/post/how-to-use-sed-to-find-and-replace-string-in-files/
https://linuxhint.com/50_sed_command_examples/

What am I doing wrong ?

TwystO
  • 109
  • 5
  • 1
    So you have a sed inside a bash inside a sudo inside a su! It couldn't but lead to problems with quoting. The first thing is that `$PATTERN` is not double-quoted, so it will wreck havoc upon expansion. E.g., the pipe character will indeed create a pipeline. Try to clean it up a bit: You can put the sed program in a file, and if you have `su` why would you need `sudo` too? – Quasímodo Aug 04 '20 at 22:33
  • I'm not questioning your skills, but maybe you're not aware that `su` doesn't give root privileges. Many people think that `su` means `super user` but in fact `su` means `switch user` (or `substitute user`). You still need root privileges to edit a file for which you don't have the appropriate rights. In addition for `sed` it does not cause any problem to use the separator of your choice, as long as it does not break the strings. It can be `|` or `@` or `:` whatever. Anyway thank you, your comment helped me and I was able to find a solution. I will post it during the day. – TwystO Aug 05 '20 at 13:02
  • Glad it helped. I am aware of that, but you can also switch user with sudo with the `-u` flag. I should have been clearer, sorry! But maybe I'm indeed missing a reason that would require you to use both. Yes, sed separator is arbitrary, but since `$PATTERN` was not double-quoted, upon expansion the pipe character is unprotected and would spawn a pipeline: sed would never see it. – Quasímodo Aug 05 '20 at 17:32

1 Answers1

1

Thanks to @Quasimodo I finally managed to solve this issue.

First I enhanced the PATTERN readability by splitting the REGEXP and REPLACEMENT into two distinct variables.
Then basically what I made is to change single-quotes to double-quotes and vice versa.

REGEXP="preserve_hostname:\sfalse"
REPLACEMENT="preserve_hostname: true\nmanage_etc_hosts: false"
PATTERN="s/$REGEXP/$REPLACEMENT/"
su - $USERNAME -c "sudo -S bash -c 'sed -n -i \"$PATTERN\" /etc/cloud/cloud.cfg'" <<< $USERPWD

Note that I escaped the double-quotes around $PATTERN in the sed command.
And that's it!

TwystO
  • 109
  • 5
  • I'm still not convinced you need both sudo and su. Why not `sudo -u $USERNAME ...` instead? It would help. Also, shows how to put the sed script in a file, so that you can get rid of one more level of quotes. You may want to try those changes for better readability and reliability. But nice to see you've come to a solution yourself! – Quasímodo Aug 05 '20 at 17:36