Ubuntu start up Rails on boot up - ruby

I want to start my Rails server with the following command on boot up:
cd /home/ubuntu/app && bundle exec rails server -p 8080 -e production
I placed it inside the /etc/rc.local, but it never starts up the server. If I remove bundle exec then shell complains about not finding the rails command.
Both variants, with and without bundle exec, work if I log in, and execute it manually.
I am totally lost. Any suggestions?

Try to change a user
su ubuntu && cd /home/ubuntu/app && bundle exec rails server -p 8080 -e production

Running your script as root is not a good idea, so you want to change user before starting your code.
su is indeed the command you want to use, but you need to realise that all arguments are passed to the login shell. So the following won't work (assuming fofox is your username):
su fofox pwd
as you're effectively saying
/bin/bash /bin/pwd
but /bin/pwd does not contain a list of shell commands, so both will give an error message:
/bin/pwd: /bin/pwd: cannot execute binary file
Thus you need to add something to the shell saying you're passing a list of commands, like this:
/bin/bash -c /bin/pwd
The last wrinkle is that you want to pass a number of arguments to the su command but protect them from the shell, as
su fofox -c id && id
will show you that the first bit is executed as fofox and the second part as root again. Single quotes are used to prevent the root shell to see the && characters.
So the final command becomes:
su fofox -c 'cd /home/ubuntu/app && bundle exec rails server -p 8080 -e production'

Related

How can I run one line of bash shell script as a specific user

I have a script I run manually (let's say) mylogin. But there's one line that needs to run as user postgres.
What is a good way to do that?
It's ok if I get a password prompt. I just need it to work somehow.
Here's what I have so far...
~/reload_test_data.sh
#!/bin/bash
# Here's the part that needs to run as user `postgres`...
sudo su postgres
export PGDATA=/Library/PostgreSQL/9.4/data && pg_ctl -m fast restart
# And here we should go back to `mylogin`...
cd ~/projects/my_project
echo 'Dropping database'
bundle exec rake db:drop
# More stuff etc...
I'm using Mac OS 10.12.1.
One of the arguments for sudo is the command so you can do something like:
sudo -u <user> bash -c "command_1; command_2; etc"
where -u <user> change to your target user

"sudo su && somecommand" doesn't run somecommand

I have created a Jenkins job today, what it does is the Jenkins user should log into another server and run two commands seperated by &&:
ssh -i /creds/jenkins jenkins#servername.com "sh -c 'sudo su && df'"
The loging part works fine, then it runs the sudo su command and becomes root but it never runs the second command (i.e. df).
I even did this manually and from the Jenkins machine logged into the other server (servername). Then ran sh -c "sudo su && df" with no luck.
Can you please help?
Thanks in advance
If you are trying to run the df command as root, you should instead do sudo df.
This is because with sudo su && df, you are basically executing sudo su first and then df.
Also make sure, your jenkins user can be sudo without password.
The sudo su launches a second shell, and the command containing the && df is waiting to be executed in the non-root shell, just after the sudo su shell exits successfully.
This could be what you're looking for:
sh -c 'sudo su - root -c "df"'
Edit: please note that I don't normally use or advocate the use of sudo su - root -c type of constructions. However, I have seen rare cases in which a program doesn't work properly when called via sudo/gksudo, but does work properly when called via su/gksu -- in such cases, a given user should try to use sudo -i first, and if that does not work, one might have to resort to sudo su - root -c or similar, as a workaround of sorts to deal with a "misbehaving" program. Since the OP used some similar syntax on his post, I assumed that his case could be such a workaround case, so I maintained the sudo su - root -c type of structure on my answer.
when you did sudo su && df , sudo su will start a child process immediately without waiting for the && df part of the command to execute , when you hit Ctrl + D it exits the child process and enters the parent shell , that's when your && df will execute. You should do this using here strings, it might not be the best option but it works and it does not start a new child process
sh -c "sudo su" <<<df
note: don't surround <<< df with any quotes

Bash dropping out of sudo in a script

I need to execute an install script using sudo, but towards the end of the script, the script needs to drop out of sudo and continue as the regular user.
Example:
sudo ./install.sh
script runs and does what it needs to as root
su myscriptuser
service myscript start
Basically, the service myscript start needs to be run by the regular user, not by root.
su myscriptuser starts another shell in the name of myscriptuser and waits until it exits. Then it proceeds to run service myscript start in the name of root again.
What you need instead of the last 2 commands is sudo:
sudo -u myscriptuser service myscript start

Run a command as the standard user, from a sudo elevated script

If a bash script has been executed with sudo, how can a command within the script run as the currently logged in user, instead of root and then revert to root to continue running other commands?
For example: -
#!/usr/bash
touch fileOwnedByRoot.txt
touch fileOwnedByUser.txt
touch otherRootFile.txt
If this script is run with sudo, without changing the order of commands, how can the 2nd touch command be run as the standard user?
The script is only a simple example, so using chmod to change ownership of files created is irrelevant.
The actual script I'm using is being run by an installer, so running with elevated privileges is a requirement, but specific commands must be run as the user running the installer, whose name is not known.
Use su - another_user -c "<command>" to run that specific command:
#!/bin/bash
touch /tmp/f1
su - another_user -c "touch /tmp/f2"
touch /tmp/f3
As commented by chepner below, you need to use $SUDO_USER or $SUDO_UID to get the name of the real user running the sudo command:
su - $SUDO_USER -c "touch /tmp/f2"
This way, the file will be touched by the user running the command.
You can test with:
#!/bin/bash
echo "sudo_user: $SUDO_USER"
echo "sudo_uid: $SUDO_UID"
And run the script either with ./script or sudo ./script. In the second case the values will be populated.
Don't run the script as sudo, just the commands that require elevated privileges.
#!/bin/bash
sudo touch fileOwnedByRoot.txt
touch fileOwnedByUser.txt
sudo touch otherRootFile.txt
According to the man page the environment variable SUDO_USER is set when you run sudo, so you could do something like:
#!/usr/bash
touch fileOwnedByRoot.txt
sudo ${SUDO_USER} touch fileOwnedByUser.txt
touch otherRootFile.txt
I haven't tested this, and don't know if it work differently on OSX, but it's worth a shot.

Changing to root user inside shell script

I have a shell script which needs non-root user account to run certain commands and then change the user to root to run the rest of the script. I am using SUSE11.
I have used expect to automate the password prompt. But when I use
spawn su -
and the command gets executed, the prompt comes back with root and the rest of the script does not execute.
Eg.
< non-root commands>
spawn su -
<root commands>
But after su - the prompt returns back with user as root.
How to execute the remaining of the script.
The sudo -S option does not help as it does not run sudo -S ifconfig command which I need to find the IP address of the machine.
I have already gone through these links but could not find a solution:
Change script directory to user's homedir in a shell script
Changing unix user in a shell script
sudo will work here but you need to change your script a little bit:
$ cat 1.sh
id
sudo -s <<EOF
echo Now i am root
id
echo "yes!"
EOF
$ bash 1.sh
uid=1000(igor) gid=1000(igor) groups=1000(igor),29(audio),44(video),124(fuse)
Now i am root
uid=0(root) gid=0(root) groups=0(root)
yes!
You need to run your command in <<EOF block and give the block to sudo.
If you want, you can use su, of course. But you need to run it using expect/pexpect that will enter password for you.
But even in case you could manage to enter the password automatically (or switch it off) this construction would not work:
user-command
su
root-command
In this case root-command will be executed with user, not with root privileges, because it will be executed after su will be finished (su opens a new shell, not changes uid of the current shell). You can use the same trick here of course:
su -c 'sh -s' <<EOF
# list of root commands
EOF
But now you have the same as with sudo.
There is an easy way to do it without a second script. Just put this at the start of your file:
if [ "$(whoami)" != "root" ]
then
sudo su -s "$0"
exit
fi
Then it will automatically run itself as root. Of course, this assumes that you can sudo su without having to provide a password - but that's out of scope of this answer; see one of the other questions about using sudo in shell scripts for how to do that.
Short version: create a block to enclose all commands to be run as root.
For example, I created a script to run a command from a root subdirectory, the segment goes like this:
sudo su - <<EOF
cd rootSubFolder/subfolder
./commandtoRun
EOF
Also, note that if you are changing to "root" user inside a shell script like below one, few Linux utilities like awk for data extraction or defining even a simple shell variable etc will behave weirdly.
To resolve this simply quote the whole document by using <<'EOF' in place of EOF.
sudo -i <<'EOF'
ls
echo "I am root now"
EOF
The easiest way to do that would be to create a least two scripts.
The first one should call the second one with root privileges. So every command you execute in the second script would be executed as root.
For example:
runasroot.sh
sudo su-c'./scriptname.sh'
scriptname.sh
apt-get install mysql-server-5.5
or whatever you need.

Resources