0

I've looked at How do I run a 'sudo' command inside a script? but this seems to be a different issue.

I want to run a script to change from root to the mastodon user using su, run Rails commands, and then exit back to the root account and restart mastodon.

Manually, I can log into root via ssh root@123.456.78.90 which gives me the root@Mastodon:~# shell. Then I use sudo su - mastodon to change to the mastodon account (I am not prompted for a password) and then cd live. Then I can run the Rails commands, etc., and they work, and then I can exit and run systemctl restart mastodon-*.

But my shell script to do the same thing doesn't work. The restartall script is

#!/bin/bash

sudo su - mastodon

cd live

RAILS_ENV=production bundle exec rake tmp:cache:clear

RAILS_ENV=production bundle exec rails assets:generate_static_pages

RAILS_ENV=production bundle exec rails assets:precompile

exit

systemctl restart mastodon-*

and I run it this way root@Mastodon:~# ./restartall

The terminal user and path change to mastodon@MyMastodon, but that's all; the script fails wth: ./restartall: line 5: cd: live: No such file or directory

I also tried root@Mastodon:~# sudo ./restartall

What am I doing wrong in using su to change to the mastodon user?

Will simply using exit correctly take the script back to root@Mastodon before systemctl restart mastodon-* ?

1 Answers1

2

The reason this fails is that sudo su - mastodon starts a new interactive shell as user mastodon. Any commands that follow are not executed until that shell exits.

You could pass the commands to su via its -c option, as described in the previous question after su, the script stops working, so

#!/bin/bash

sudo su -l mastodon -c ' cd live RAILS_ENV=production bundle exec rake tmp:cache:clear RAILS_ENV=production bundle exec rails assets:generate_static_pages RAILS_ENV=production bundle exec rails assets:precompile '

systemctl restart mastodon-*

(you don't need an explicit exit at the end of the commands passed via -c since the non-interactive su shell will exit naturally when it runs out of commands to execute).

Alternatively, you could use a here-document to pass the commands to the su shell via standard input, as described in how to write a script that will run commands after su, without using -c but please note the warning about commands that themselves read from stdin.

However you could consider avoiding su altogether, and writing your script so that it checks who is running it, and re-executes itself as the target user if required, like

#!/bin/bash

rails_user=mastodon

if [[ $EUID -ne $(id -u $rails_user) ]]; then echo "Switching to user '$rails_user' to perform tasks" exec sudo -iu "$rails_user" "$(realpath $0)" fi

cd live

etc.

steeldriver
  • 136,215
  • 21
  • 243
  • 336
  • Thanks! The first example works. Though I'm still getting "bundle: command not found" errors even though the script completes, exits and runs systemctl restart mastodon-*; that must be a different issue? – BlueDogRanch Feb 25 '23 at 22:41
  • @BlueDogRanch that sounds like an issue with how PATH is set for user mastodon's login shell - remember non-interactive bash shells don't process ~/.bashrc so you should be using ~/.bash_login or ~/.profile for things like that – steeldriver Feb 25 '23 at 22:46
  • Ok, I'm still learning shells. There is a .profile file, and with a file mod date in 2019, it obviously wasn't modified by the mastodon install. – BlueDogRanch Feb 25 '23 at 22:55