0

I'm aware that i can run each command as a different user with:

su -s /bin/bash "command" - user

But there's several commands to run and i was looking for a neater way to do it than putting su on every line.

How can i say 'all commands from here run as userX' and then 'stop running commands as userX' (and continue running the rest of the script as root)?

Thanks.

Here's the block i'd like to run as a different user (updated from answer given by @Jetchisel):

#!/bin/bash
export BORG_PASSPHRASE="SUPERSECRETPASSWORD"

su - backup-user -s /bin/bash -c '
echo "$USER $(date +%F)" |& tee /pathto/_logs/test.log
borg info               \
    /pathto/repo          \
    |& tee -a /pathto/_logs/test.log
'
info_exit=$?{PIPESTATUS[0]}

if [ ${info_exit} = "0" ]; then
echo ">> test-SUCCESS <<"
elif [ ${info_exit} = "1" ]; then
echo ">> test WARNINGS <<"
else
echo ">> test FAILED <<"
fi

The above works but for two things:

  1. I can't seem to pass the environment variable that Borg normally picks up automatically: $BORG_PASSPHRASE. Is this maybe a permissions issue between users?
  2. It doesn't seem to pass the info=exit correctly. For a test i removed Borg entirely retained echo but misspelled it 'ech' which fails. But the script reports as success regardless.
4
  • Exporting the password into a environment variable is not a good idea. A password shouldn't be in a script or passed to an environment variable. – Shōgun8 May 25 at 10:18
  • I understand, but this is a single-user device that is encrypted. – Derek May 26 at 22:17
  • Then why run commands as another user? And how does it benefit you in any way to put the user's password in a script? When running the script as root, you don't need the user's password, therefore you can avoid the horrible practice of putting a password in a script. – Shōgun8 May 26 at 23:32
  • The reason it doesn't run as root is because the file-set it's working on isn't owned by root. The files are put there over ssh as a different user. It still needs the password because it's a backup-set which is password encrypted and runs to a schedule. – Derek May 28 at 8:08
1

You can try the -c flag

 OPTIONS
       -c, --command=command
            Pass command to the shell with the -c option.

Something like

su - "$user" -s /bin/bash -c 'command1;command1;command3;.....'

Or use new lines instead of ; to separate the commands.

su - "$user" -s /bin/bash -c '
  command1
  command2
  command3
  ...
'

Just need to take care of the quoting if you need to quote the commands with single quotes.

4
  • Unfortunately that didn't work, i think it's because the commands are not one-liners and reasonably complex, one portion checks if a path is available before continuing or exiting, another part has 3 separately run Borg backup commands. Looking in the editor, the text colouring didn't seem right if the syntax was correct. I've updated the post to hopefully be more useful. Thanks for your suggestion. – Derek Apr 10 '20 at 12:07
  • @Derek It should work. The complexity of the commands don't matter at all, but you may want to export your BORG_REPO and LOGFILE variables to be able to access them inside the bash -c script. – Kusalananda Apr 10 '20 at 12:15
  • You're right it does work - i did have variables in the full script, but there were some missing in my test script. Thanks both @Kusalananda and Jetchisel. I've updated the original question because while it works for the ultra-basic, i'm still having trouble with a couple of things that seem to be as a result of 'blocking' the commands inside the single quotes. – Derek Apr 12 '20 at 0:33
  • Exporting the password into a environment variable is not a good idea. A password shouldn't be in a script or passed to an environment variable. – Shōgun8 May 25 at 10:19
-1

You can use functions in your bash script, along with typeset to easily accomplish that;

#!/bin/bash

function1 () {
  echo "this is function1"
 }
function2 () {
  echo "this is function2"
}

su -c "$(typeset -f function1); function1" user1
su -c "$(typeset -f function2); function2" user2


exit 0

Put whatever commands you wish to run inside the function and the respective user will run all of those commands.

NOTE: you will run the script as root to easily avoid any password issues

sudo su -c ./script.sh
-1

Eh. I'm new to stackexchange. Otherwise this would be a comment instead of an answer. I don't have the rep to comment. So guys. Take it easy on me! I recommend that you use ssh instead of su. And I recommend having root and backup-user share a common primary UNIX group.

  1. With ssh the backup-user password can change and your script will still work.
  2. If you use a shared group - later - after your proof-of-concept analysis - you can migrate to a solution where an account other than root can own and execute the script. This has the advantage of making it so you don't have to share the root password.
  3. You can pass environment variables in the ssh command... Like: ssh bla@blah "export BORG_PASSPHRASE=\"SUPERSECRETPASSWORD\"; ./script.sh"
2
  • 1
    Exporting the password into a environment variable is not a good idea. A password shouldn't be in a script or passed to an environment variable. – Shōgun8 May 25 at 5:18
  • 1
    @Shōgun8 While this is certainly true, please note that this approach was actually the one attempted by the OP, so your comment might be better placed under the originap question ... – AdminBee May 25 at 8:30

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.