Ubuntu run script as non-root user - linux

I've an init script (/etc/init.d) that should run a my executable jar file as a serviceat boot. I need that this script is runned by a specified user.
With su & sudo is possibile but it split the process and I don't like this.
There is another way to run this script as limited user?
This is the relevant part of my init script:
#!/bin/bash
APP_NAME="myapp"
APP_HOME=/home/user1/jetty
JAVA_HOME=/opt/local/java/latest
echo "Service $APP_NAME - [$1]"
echo "JAVA_HOME -> $JAVA_HOME"
echo "APP_HOME -> $APP_HOME"
echo "APP_NAME -> $APP_NAME"
function start {
if pkill -0 -f $APP_NAME.jar > /dev/null 2>&1
then
echo "Service [$APP_NAME] is already running. Ignoring startup request."
exit 1
fi
echo "Starting application..."
cd $APP_HOME
nohup $JAVA_HOME/bin/java -jar $APP_HOME/$APP_NAME.jar\
< /dev/null > $APP_HOME/logs/app.log 2>&1 &
}

On Ubuntu you should use the program start-stop-daemon for this. It has options for launching daemons as different users, managing pid files, changing the working directory, and pretty much anything else that is usually needed by init scripts.

Related

Crontab not recognising command

I have a bash script which I want to run as a cron job.
It works fine except one command.
I redirected its stderr to get the error and found out that the error it shows was the command not recognized.
It is a root crontab.
Both the current user and root execute the command successfully when I type it in the terminal.
Even the script executes the command when I run it through the terminal.
Startup script :
#!/bin/bash
sudo macchanger -r enp2s0 > /dev/null
sudo /home/deadpool/.logkeys/logger.sh > /dev/null
logger.sh :
#!/bin/bash
dat="$(date)"
echo " " >> /home/deadpool/.logkeys/globallog.log
echo $dat >> /home/deadpool/.logkeys/globallog.log
echo " " >> /home/deadpool/.logkeys/globallog.log
cat /home/deadpool/.logkeys/logfile.log >> /home/deadpool/.logkeys/globallog.log
cat /dev/null > /home/deadpool/.logkeys/logfile.log
cat /dev/null > /home/deadpool/.logkeys/error.log
logkeys --start --output /home/deadpool/.logkeys/logfile.log 2> /home/deadpool/.logkeys/error.log
error.log
/home/deadpool/.logkeys/logger.sh: line 10: logkeys: command not found
Remember cron runs with a different environment then your user account or root does and might not include the path to logkeys in its PATH. You should try the absolute path for logkeys (find it with which logkeys from your user) in your script. Additionally I recommend looking at this answer on serverfault about running scripts like they are running from cron when you need to find out why it's working for you and not in a job.

ssh does not return even after execution

The following ssh command does not return to terminal. It hangs though the execution is completed. The execution hangs after echo hi command.
ssh user#testserver "echo hello;source .profile;source .bash_profile;/apps/myapp/deploytools/ciInstallAndRun.sh; echo hi"
Output
hello
<outoutfrom remote script"
hi
ciInstallAndRun.sh
echo 'starting'
cd /apps/myapp/current
./tctl kill
cd /apps/myapp
mv myapp_v1.0 "myapp_v1.0_`date '+%Y%m%d%H%M'`"
unzip -o /apps/myapp/myappdist-bin.zip
java -classpath .:/apps/myapp/deploytools/cleanup.jar se.telenor.project.cleanup.Cleanup /apps/myapp myapp_v1.0_ 3
cd /apps/myapp/myapp_v1.0
echo 'Done with deploy'
chmod -R 775 *
echo 'Done'
./tctl start test
Source OS: Redhat
Dest Os: Solaris 10 8/07
Any idea to fix this.
Any idea to fix this.
Your installation script has spawned a child process.
Add a ps -f or ptree $$ command before echo hi. You'll see a child process or multiple child processes spawned by your install script.
To stop the SSH command from hanging, you need to detach such child process(es) from your terminal's input/output. You can sedirect your script's output to a file - both stdout and stderr with > /some/output/file 2>&1, and also redirect its input with < /dev/null.
Or you can use the nohup command.
You haven't provided an MCVE, as others have noted, but this is likely the problem command in you install script, since your question implies that you see the expected output from your install script:
./tctl start test
You probably would do better to replace it with something like:
./tctl start test </dev/null >/some/log/file/path.log 2>&1

Upstart node.js working directory

Starting Node.js with Upstart, when trying to access files within Node.js it cannot access them without using the full path. I need it to use the working directory.
start on startup
stop on shutdown
script
echo $$ > /var/run/mynodeapp.pid
exec sudo -u mynodeapp node server.js >> /var/log/mynodeapp.sys.log 2>&1
end script
pre-start script
echo "Starting" >> /var/log/mynodeapp.sys.log
end script
pre-stop script
rm /var/run/mynodeapp.pid
echo "Stopping" >> /var/log/mynodeapp.sys.log
end script
The solution is to change directory within the script. In my case, the user is mynodeapp and the node files are in the users directory (/home/mynodeapp/).
script
chdir /home/mynodeapp/
echo $$ > /var/run/mynodeapp.pid
exec sudo -u mynodeapp node server.js >> /var/log/mynodeapp.sys.log 2>&1
end script
I have yet to find out what $$ means on the echo line or 2>&1. Maybe somebody could chime in with this if they know!
You should use the chdir stanza as per the Upstart docs: http://upstart.ubuntu.com/cookbook/#chdir

Upstart script for node.js app

I'm having trouble starting an Upstart script.
Here's the script (app.conf in /etc/init/)
description "node.js server"
author "kvz"
start on startup
stop on shutdown
script
# We found $HOME is needed. Without it, we ran into problems
export HOME="/root"
exec sudo -u /usr/local/bin/node \
/var/www/vhosts/travelseguro.com/node/app.js \
2>&1 >> /var/log/node.log
end script
When I run sudo start app, I get:
start: Unknown job: app
How can I make this work?
I was having the same problem running on the latest Amazon (AWS) linux which is Redhat based.
I have my upstart file in /etc/init called node.conf and when I ran sudo start node I would get a similar error to you start: Unknown job: node.
It turns out that the job won't start if there's an error in your .conf file. So I started out by commenting out all the lines and slowly building up to find the error. The error message isn't very clear and makes it look like upstart can't find your conf file.
Tailing your '/var/log/messages' will help you debug as Upstart logs to there (It may be somewhere different on Ubuntu. Mine said init: /etc/init/node-upstart.conf:8: Unknown stanza which helped me get to the bottom of it. In my particular case I was declaring variables incorrectly.
See on AskUbuntu for a similar thread.
Here's my edited working script:
<!-- language: lang-sh -->
#!upstart
# using upstart http://upstart.ubuntu.com/getting-started.html and node forever https://github.com/nodejitsu/forever/
# to run server
# redhat has additional sudo restrictions, you must comment out 'Default requiretty' from /etc/sudoers
#startup monitoring script derived from http://stackoverflow.com/questions/11084279/node-js-setup-for-easy-deployment-and-updating
description "node.js server"
author "jujhar"
env PROGRAM_NAME="node"
env FULL_PATH="/home/httpd/buto-middleman/public"
env FILE_NAME="forever.js"
env NODE_PATH="/usr/local/bin/node"
env USERNAME="springloops"
start on startup
stop on shutdown
script
export HOME="/root"
export NODE_ENV=staging #development/staging/production
echo $$ > /var/run/$PROGRAM_NAME.pid
cd $FULL_PATH
#exec sudo -u $USERNAME $NODE_PATH $FULL_PATH/$FILE_NAME >> /var/log/$PROGRAM_NAME.sys.log 2>&1
exec $NODE_PATH $FULL_PATH/$FILE_NAME >> /var/log/$PROGRAM_NAME.sys.log 2>&1
end script
pre-start script
# Date format same as (new Date()).toISOString() for consistency
echo "[`date -u +%Y-%m-%dT%T.%3NZ`] (sys) Starting" >> /var/log/$PROGRAM_NAME.sys.log
end script
pre-stop script
rm /var/run/$PROGRAM_NAME.pid
echo "[`date -u +%Y-%m-%dT%T.%3NZ`] (sys) Stopping" >> /var/log/$PROGRAM_NAME.sys.log
end script
-- Edit 2013-06-01 --
If you're on Centos or Amazon Linux like me, take a look at this init.d script.
-- Edit 2013-10-14 --
Here's a link to a gist of an init.d script that I actually use in production on Amazon Linux(Redhat Based). I simply keep it in my project under an init.d folder and then symlink to it in the /etc/init.d folder and now it's a daemon/service!
-- Edit 2014-06-05 --
Check out this awesome blog artcile by Jeff Dickey on Node.js in production using systemd which is much cleaner and easier than all the stuff we've been doing here (IMHO). He also uses Ansible to control his cluster (which I love) but you don't have to go that far if you're not ready.
After a few attempts I implemented working .conf file for upstart which works as a service with automatic start after reboot and restart (respawn) in case of crash. Also it can start my app with unprivileged user permissions. The name of the file is /etc/init/my-app.conf.
To start / stop service please use
sudo start my-app / sudo stop my-app
If you have an error like
start: Unknown job: my-app
exec the following command
sudo initctl reload-configuration
My /etc/init/my-app.conf file:
#my-app
description "node.js my-app website"
env FULL_PATH="/home/myuser/app.prod/app"
env NODE_PATH="/usr/bin/node"
start on filesystem or runlevel [2345]
stop on [!2345]
script
export HOME="/root"
export NODE_ENV=production
echo $$ > /var/run/my-app.pid
cd $FULL_PATH
#Use exec below if you want to launch it under myuser,
#don't forget to create /var/log/my-app.sys.log with appropriate permissions
#exec sudo -u myuser sh -c "$NODE_PATH server.js >> /var/log/my-app.sys.log 2>&1"
exec $NODE_PATH server.js >> /var/log/my-app.sys.log 2>&1
end script
pre-start script
echo "[`date`] (sys) Starting" >> /var/log/my-app.sys.log
end script
pre-stop script
rm /var/run/my-app.pid
echo "[`date`] (sys) Stopping" >> /var/log/my-app.sys.log
end script
#uncomment respawn if you want to restart your service in case of crash
#respawn
#respawn limit 50 30
I do recommend to uncomment respawn after you will make sure that everything works ok.
UPDATE
I improved my script (please keep in mind that it works not under root but under regular user zn ):
#znapi.conf
description "node.js zn api"
env FULL_PATH="/home/zn/app.prod"
env NODE_PATH="/usr/bin/node"
env LOG="/var/log/znapi.log"
env PIDFILE="/var/run/znapi.pid"
# Start up when the system hits any normal runlevel, and
#start on filesystem or runlevel [2345]
#start when mongod started
start on started mongod
# shuts down when the system goes to shutdown or reboot.
stop on runlevel [06]
respawn
respawn limit 50 5
pre-start script
# check that log file exist or create it
test -f $LOG || { touch $LOG; chown zn:zn $LOG; }
# Date format same as (new Date()).toISOString() for consistency
echo "[`date`] (sys) Starting" >> $LOG
end script
script
export NODE_ENV=production
exec start-stop-daemon --start -m -p $PIDFILE -c zn -d $FULL_PATH -x server.js >> $LOG 2>&1
end script
pre-stop script
rm $PIDFILE
echo "[`date`] (sys) Stopping" >> $LOG
end script

Adding a service startup script for Amazon linux AMI

I am using an Amazon Linux AMI and doing some custom modifications(added an axis2server, etc) on it and saving it as a new AMI. Now what I want to do is when the AMI boots up, start up axis2server(ie.axis2server should automatically start when the instance boots up). For that I used a init script like below and ran the following command:
chkconfig --add axisservice
But when I launch a new instance from my image, the axis2server is not getting started.
I just only need to execute the script /home/ec2-user/axis2-1.6.1/bin/axis2server.sh at startup. Am I missing anything here?
#! /bin/sh
# Basic support for IRIX style chkconfig
###
# chkconfig: 235 98 55
# description: Manages the services you are controlling with the chkconfig command
###
case "$1" in
start)
echo -n "Starting axisservice"
touch ~/temp.txt
cd /home/ec2-user/axis2-1.6.1/bin
./axis2server.sh &
echo "."
;;
stop)
echo -n "Stopping axisservice"
echo "."
;;
*)
echo "Usage: /sbin/service axisservice {start|stop}"
exit 1
esac
exit 0
I went through https://help.ubuntu.com/community/CloudInit as well and it provides a mechanism called User-Data Scripts, where a user can execute a script when launching the script.
$ euca-run-instances --key mykey --user-data-file myscript.sh ami-axxxx
This is a command line option and what I want is something like when I launch the instance through the UI, the script should be started.Therefore, I think the above option can not be used in my case. Please correct me if I am wrong.
Thanks,
H.
I bet the environment is not set(up correctly). This means that I am guessing that your shell script tries to start another program and it's not to be found.
So at first, I'd adjust the start part of your script (current):
echo -n "Starting axisservice"
touch ~/temp.txt
cd /home/ec2-user/axis2-1.6.1/bin
./axis2server.sh &
echo "."
Edited:
echo -n "Starting axisservice"
touch ~/temp.txt
cd /home/ec2-user/axis2-1.6.1/bin
./axis2server.sh
RETVAL=$?
[ $RETVAL -eq 0 ] && echo Success
[ $RETVAL -ne 0 ] && echo Failure
echo "."
So what did I do?
removed & so script waits for your shell script (axis2server.sh) to complete
checked the return status ($?) of your shell script
Further debugging:
Add set -x to your scripts to enable tracing and log both stderr and stdout.
Questions:
Are you are aware that stop (in your service script) doesn't do anything?
touch ~/temp.txt is that supposed to create /root/temp.txt? (I'm guessing root runs this script.)
If none of my suggestions work, can you share axis2server.sh and paste stderr and stdout?

Resources