从 /etc/init.d 启动的 Ubuntu 服务最终使用错误的 PID

从 /etc/init.d 启动的 Ubuntu 服务最终使用错误的 PID

这个问题源于我的上一个问题. 回顾一下

  • 我想在我的 Ubuntu 14.04 服务器上使用 OpenResty 而不是原始 Nginx。
  • 我已按照说明安装 OpenResty这里
  • 编译nginx结果最终位于 `/usr/local/openresty/nginx/sbin'
  • 我现在可以./nginx从该文件夹启动 nginx。

问题是我需要能够执行一些像使用通过等方式service nginx status|reload|start|stop安装的 Nginx 原始版本时通常执行的操作一样的操作。apt-get install nginx|nginx-extras

我对这些问题的了解很基础。然而,通过破解/etc/init.d/nginx所创建的脚本apt-get install nginx并修改所述的想法这里我已经创建了自己的/etc/init.d/nginx脚本,如下所示

#!/bin/sh

NAME="nginx"
PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
APP="/usr/local/openresty/nginx/sbin/nginx"

if [ -r /etc/default/nginx ]; then
 . /etc/default/nginx
fi

. /lib/init/vars.sh
. /lib/lsb/init-functions

PID=$(cat /usr/local/openresty/nginx/conf/nginx.conf | grep -Ev '^\s*#' | 
awk 'BEGIN { RS="[;{}]" } { if ($1 == "pid") print $2 }' | head -n1)
if [ -z "$PID" ]
then
   PID=/var/run/nginx.pid
fi

if [ -n "$ULIMIT" ]; then
 ulimit $ULIMIT
fi

start() {
 printf "Starting '$NAME'... "
 start-stop-daemon --start --background --make-pidfile --pidfile    
 /var/run/$NAME.pid --exec "$APP"
 printf "done\n"
}

killtree() {
 local _pid=$1
 local _sig=${2-TERM}
 for _child in $(ps -o pid --no-headers --ppid ${_pid}); do
    killtree ${_child} ${_sig}
 done
 kill -${_sig} ${_pid}
}

stop() {
 printf "Stopping '$NAME'... "
 [ -z `cat /var/run/$NAME.pid 2>/dev/null` ] || \
 while test -d /proc/$(cat /var/run/$NAME.pid); do
  killtree $(cat /var/run/$NAME.pid) 15
  sleep 0.5
 done 
 [ -z `cat /var/run/$NAME.pid 2>/dev/null` ] || rm /var/run/$NAME.pid
 printf "done\n"
}

case "$1" in
 start)
   start
   ;;
 stop)
  stop
  ;;
 restart)
  stop
  start
  ;;
reload)
  start-stop-daemon --stop --signal HUP --quiet --pidfile /var/run/nginx.pid 
  --name nginx
  ;;            
status)
 status_of_proc -p /var/run/nginx.pid "nginx" "nginx" && exit 0 || exit $?
    ;;

*)
 echo "Usage: $NAME {start|stop|restart|reload|status}" >&2
 exit 1
 ;;
esac

exit 0

有了这个,如果我重新启动服务器并发出一个lsof -nP -i | grep LISTEN输出

nginx     2247     root    6u  IPv4  14166      0t0  TCP *:80 (LISTEN)
nginx     2248   nobody    6u  IPv4  14166      0t0  TCP *:80 (LISTEN)

我不明白的一件事是,为什么有两个用户:root 和 nobody?因此,如果我从浏览器访问服务器并执行 PHP 脚本,它将作为以下方式运行:没有人...?

我检查了一下/var/run/nginx.pid。那里记录的PID是2146,即1较少的比上面报告的和当我运行时netstat -anp | grep 80

我尝试了最后一步好几次 - 多次重启 - 但结果总是一样。当然,这意味着后续尝试通过 Nginx 重新加载或停止 Nginx 都service nginx reload失败service nginx stop了:错误的 PID!

当我手动编辑/var/run/nginx.pid以确保它具有正确的PID 工作如预期。

我必须承认,我所做的工作超出了我对这些事情的了解范围。如果能帮助我解决在这里遇到的问题,我将不胜感激。

答案1

我在这里发布答案,希望它能为其他人节省我所忍受的数小时的挫败感。这里容易处理的问题是nobody我上面提到的用户。发生这种情况的原因很简单,因为nginx.confopenresty 创建的文件 - 请参阅

/usr/local/openresty/nginx/conf/nginx.conf

无需指定用户。只需编辑第一行

#user nobody如此读取user www-data www-data,并且该特定问题已解决。

第二个问题是init.d脚本。我担心 openresty 文档应该为此承担责任。他们不遗余力地解释了如何获取 openresty 以及如何编译它。关于如何将其守护进程化的几句话也不错。

在黑暗中摸索了几个小时后,我想寻找openresty 初始化文件。出现的第一个结果是这个.我在下面重现了该脚本

#!/bin/sh


PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="Nginx Daemon"
NAME=nginx
PREFIX=/usr/local/openresty/nginx
DAEMON=$PREFIX/sbin/$NAME
CONF=$PREFIX/conf/$NAME.conf
PID=$PREFIX/logs/$NAME.pid
SCRIPT=/etc/init.d/$NAME

. /lib/lsb/init-functions

if [ ! -x "$DAEMON" ] || [ ! -f "$CONF" ]; then
 echo -e "\033[33m $DAEMON has no permission to run. \033[0m"
 echo -e "\033[33m Or $CONF doesn't exist. \033[0m"
 sleep 1
 exit 1
fi

do_start() {
 if [ -f $PID ]; then
    echo -e "\033[33m $PID already exists. \033[0m"
    echo -e "\033[33m $DESC is already running or crashed. \033[0m"
    echo -e "\033[32m $DESC Reopening $CONF ... \033[0m"
    $DAEMON -s reopen -c $CONF
    sleep 1
    echo -e "\033[36m $DESC reopened. \033[0m"
 else
    echo -e "\033[32m $DESC Starting $CONF ... \033[0m"
    $DAEMON -c $CONF
    sleep 1
    echo -e "\033[36m $DESC started. \033[0m"
 fi
}

do_stop() {
 if [ ! -f $PID ]; then
    echo -e "\033[33m $PID doesn't exist. \033[0m"
    echo -e "\033[33m $DESC isn't running. \033[0m"
 else
    echo -e "\033[32m $DESC Stopping $CONF ... \033[0m"
    $DAEMON -s stop -c $CONF
    sleep 1
    echo -e "\033[36m $DESC stopped. \033[0m"
 fi
}

do_reload() {
 if [ ! -f $PID ]; then
    echo -e "\033[33m $PID doesn't exist. \033[0m"
    echo -e "\033[33m $DESC isn't running. \033[0m"
    echo -e "\033[32m $DESC Starting $CONF ... \033[0m"
    $DAEMON -c $CONF
    sleep 1
    echo -e "\033[36m $DESC started. \033[0m"
 else
    echo -e "\033[32m $DESC Reloading $CONF ... \033[0m"
    $DAEMON -s reload -c $CONF
    sleep 1
    echo -e "\033[36m $DESC reloaded. \033[0m"
 fi
}

do_quit() {
 if [ ! -f $PID ]; then
    echo -e "\033[33m $PID doesn't exist. \033[0m"
    echo -e "\033[33m $DESC isn't running. \033[0m"
 else
     echo -e "\033[32m $DESC Quitting $CONF ... \033[0m"
     $DAEMON -s quit -c $CONF
     sleep 1
     echo -e "\033[36m $DESC quitted. \033[0m"
  fi
}

do_test() {
 echo -e "\033[32m $DESC Testing $CONF ... \033[0m"
 $DAEMON -t -c $CONF
}

do_info() {
 $DAEMON -V
}

case "$1" in
 start)
  do_start
  ;;
 stop)
  do_stop
  ;;
 reload)
  do_reload
  ;;
 restart)
  do_stop
  do_start
  ;;
status)
    status_of_proc -p $PID "$DAEMON" "$NAME" && exit 0 || exit $?
    ;;
 quit)
  do_quit
  ;;
 test)
  do_test
  ;;
 info)
  do_info
  ;;
 *)
  echo "Usage: $SCRIPT {start|stop|reload|restart|quit|test|info}"
  exit 2
  ;;
 esac

 exit 0

原始脚本中有一个遗漏,我已经将其更正 - 没有status方法。

相关内容