I have a bash script my_script.sh created as a root user that has a part where it has to be switched to a sudo user.

I have tried heredocs and it's working, but the issue with it is I can't use variables to and fro with the bash script.

#Name of my Script is my_script

read -p "Enter hostname : " hostname
hostnamectl set-hostname $hostname
sudo -i -u my_username bash << 'EOF'
mkdir  ~/.ssh
chmod 700 ~/.ssh
nano ~/.ssh/authorized_keys
read -p "Enter Database Name : " dbname
echo "Database $dbname has been added to system!"

The problem with this approach is I can't use the variable $hostname inside heredocs if I use 'EOF' and if I don't use 'EOF' then I won't be able to use other variables e.g. $dbname created inside heredocs.

I am trying the approach mentioned here

if [ $(id -u) -eq 0 ]; then
  cd "$dir"
  exec su "$user" "$0" -- "$@"

On the terminal: ./my_script.sh my_username

Error: sh: 0: Can't open ./my_script.sh

my_username has sudo privileges.
System info: Ubuntu 20.04

How do I work out the error?

  • I use this to run unison as me: su - ajgringo619 -c "unison -terse" Sep 9 at 23:00
  • The top case seems like it'd be solved by passing through $hostname as an argument to bash << 'EOT' "$hostname", but your question down the bottom doesn't seem related to that. What are you actually asking about? Sep 9 at 23:48
  • Break your script into two (or more) parts. The part(s) that need to be run as root, and the part that doesn't. Write separate script(s) for the root part(s), and call them as needed with sudo from the non-root part. Be ultra-paranoid with the root parts - try to hard-code as much as possible and sanity-check any user-supplied input (stdin, args) before doing anything with them. Be extremely strict, only allow known-good values and exit with an error for anything else (i.e. don't just reject known-bad values - there will always be more bad values and exploits than you will think of).
    – cas
    Sep 10 at 10:26
  • and, of course, the script should not be writable by the user who is allowed to run it with sudo - otherwise they could edit it and make it do whatever they want as root.
    – cas
    Sep 10 at 10:28

There is no need to run these inside a single shell.

You can run the following as root:

mkdir  ~my_username/.ssh
chmod 700 ~my_username/.ssh
nano ~my_username/.ssh/authorized_keys
chown -Rh my_username ~my_username/.ssh

And the following with a single invocation of sudo:

read -p "Enter Database Name : " dbname
echo "Database $dbname has been added to system!"

Alternatively, try specifying your variables in the format ${dbname}

  • ${dbname} will not help here. Curly-braces are not a substitute for quoting, nor do they allow interpolation of variables in single-quoted strings/here-docs. Aside from parameter expansion and shell arrays, the only reason to use ${} to wrap a variable name is to disambiguate the variable from adjacent text. e.g. $var1 is a variable called var1, while ${var}1 is a variable called var followed by a literal 1. As useful as that is when it's needed, you still need to double-quote your variables when you use them, with or without ${}.
    – cas
    Sep 10 at 10:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.