问题
I have a script in bash to start a java program and I want to get the pid of the program after it executes. The pid will be saved in a text file.
Right now I have something like this:
if [ "$USER" == "root" ]
then
su $APP_USER -c "nohup java $JAVA_OPTS >> $LOG_OUT 2>> $LOG_ERR &"
su $APP_USER -c "echo $! > $PID_PATH/$CAT.pid"
else
nohup java $JAVA_OPTS >> $LOG_OUT 2>> $LOG_ERR &
echo $! > "$PID_PATH/$CAT.pid"
fi
I also tried like this but it doesn't work neither.
if [ "$USER" == "root" ]
then
su $APP_USER -c "(nohup java $JAVA_OPTS >> $LOG_OUT 2>> $LOG_ERR &); (echo $! > $PID_PATH/$CAT.pid)"
else
nohup java $JAVA_OPTS >> $LOG_OUT 2>> $LOG_ERR &
echo $! > "$PID_PATH/$CAT.pid"
fi
when I run as my APP_USER all works great, when I run as root my java program starts but the pid file is created empty.
回答1:
try
su $APP_USER -c "nohup java $JAVA_OPTS >> $LOG_OUT 2>> $LOG_ERR & echo \$! > $PID_PATH/$CAT.pid"
\ behind $! prevents expansion of the variable, before passing to the su command.
回答2:
The problem is that each su command is a separate invocation of the user, so $! won't store your last PID since there isn't one.
What you have to do is save your PID in the same invocation as the first su. The easiest way to do this is to put quotation marks around both commands and separate them by a semicolon
su $APP_USER -c "nohup java $JAVA_OPTS >> $LOG_OUT 2>> $LOG_ERR &; "echo $! > $PID_PATH/$CAT.pid"
Now su will invoke both commands in the same environment.
回答3:
If your system provides start-stop-daemon it may be easier to use that instead of creating crazy wrappers. By default you get the user changing (--user) and nohup behaviour (--background). Additionally you can use --make-pidfile that will do the right thing - whether you switch the user or not.
来源:https://stackoverflow.com/questions/16542417/bash-get-pid-of-a-process-using-a-different-user