【问题标题】:Java Jar run as Daemon cant issue exec()Java Jar 作为守护进程运行无法发出 exec()
【发布时间】:2011-10-29 00:32:37
【问题描述】:

我编写了一个 Java 套接字服务器,以使我能够保持 Web 集群代码库同步。当我像这样从 shell 登录运行 init.d 脚本时

[root@web11 www]# /etc/init.d/servermngr start

注销后一切正常,但如果服务器重新启动或我使用类似服务运行 init.d

[root@web11 www]# service servermngr start

任何传递给套接字服务器的 exec() 命令都不会在 linux 机器上执行。我假设它与没有真正外壳的 JVM 有关。如果我登录并运行

[root@web11 www]# /etc/init.d/servermngr start

...并且注销所有运行良好所有 CVS 命令都已执行。

另一个注意事项,当作为服务运行时,套接字服务器响应状态检查,因此它正在运行

这是 init.d 脚本

#!/bin/sh
# chkconfig: 2345 95 1
# description: Starts Daemon Using ServerManager.jar.
# 
# Source function library.
. /etc/init.d/functions


start () {
    echo -n $"Starting ServerManager: "

    # start daemon
    cd /www/servermanager/
    daemon java -jar ServerManager.jar > /www/logs/ServerManager.log &
    RETVAL=$?
    echo
    [ $RETVAL = 0 ] && touch /var/lock/subsys/cups
    echo "";
    return $RETVAL
}

stop () {
    # stop daemon
    echo -n $"Stopping $prog: "
    kill `ps uax | grep -i "java -jar ServerManager.ja[r]" | head -n 1 | awk '{print $2}'`
    RETVAL=$?
    echo "";
    return $RETVAL
}

restart() {
    stop
    start
}

case $1 in
    start)
        start
    ;;
    stop)
        stop
    ;;
    *)

    echo $"Usage: servermngr {start|stop}"
    exit 3
esac

exit $RETVAL

以及负责实际执行代码的Java:

// Build cmd Array of Strings
            String[] cmd = {"/bin/sh", "-c", "cd /www;cvs up -d htdocs/;cvs up -d phpinclude/"};
            final Process process;
            try {
                process = Runtime.getRuntime().exec(cmd);

                BufferedReader buf = new BufferedReader(new InputStreamReader(
                        process.getInputStream()));

                // Since this is a CVS UP we return the Response to PHP
                if(input.matches(".*(cvs up).*")){
                    String line1;
                    out.println("cvsupdate-start");
                    System.out.println("CVS Update" + input);
                    while ((line1 = buf.readLine()) != null) {
                        out.println(line1);
                        System.out.println("CVS:" + line1);
                    }
                    out.println("cvsupdate-end");
                }

            } catch (IOException ex) {
                System.out.println("IOException on Run cmd " + CommandFactory.class.getName() + " " + ex);
                Logger.getLogger(CommandFactory.class.getName()).log(Level.SEVERE, null, ex);
            }

感谢任何帮助

【问题讨论】:

  • 我检查了它写入的日志文件,它正在接收命令。它只是没有在服务器上执行它们
  • [root@web11 ~]# tail -f /www/logs/ServerManager.log 服务器开始于 ip 192.168.56.151 服务器开始于端口 4444 MaxConnections:0 CVS 更新:cd /www;cvs up -d htdocs/;cvs up -d phpinclude/ CVS 更新:cd /www;cvs up -d htdocs/;cvs up -d phpinclude/ 所以命令会到达process = Runtime.getRuntime().exec(cmd);@Ingo

标签: java linux jar daemon runtime.exec


【解决方案1】:

您尝试运行的命令是什么? cd 不是一个程序,如果你有 ; 你有多个命令。您只能运行一个程序!

【讨论】:

  • 套接字服务器获取发送给它的命令并以这种方式发出命令: String[] cmd = {"/bin/sh", "-c","cd /www;cvs up -d htdocs/;cvs up -d phpinclude/"} process = Runtime.getRuntime().exec(cmd);
  • 没关系。 sh 是一个命令。如果失败,您会收到什么错误消息?如果你想执行远程命令,你有没有考虑ssh是为此而设计的?
  • 套接字服务器现在运行正常,但那是因为我登录了所有 10 个服务器并发出 /etc/init.d/servermngr start 然后注销。如果他们的服务器出现故障或重新启动,操作系统将启动服务 servermngr start(我也尝试添加到 rc.local),之后命令不再传递给服务器操作系统 Linux。我没有从 Linux 或 Java 得到错误。一旦我登录到服务器并执行服务 servermngr stop 和 /etc/init.d/servermngr start 它将再次工作,但我需要它通过服务工作
  • 是的,我也是这么想的。然而,我没有看到我编辑并发布了负责运行 exec() 命令的代码。我在其中硬编码和示例命令“cd /www;cvs up -d htdocs/;cvs up -d phpinclude/”。通常这是在发送到每个服务器的 JSON 字符串中发送的
  • 你的回答让我开始思考,所以我向 Java 服务器添加了一些代码,发现 CVSROOT 环境变量没有设置。我添加了 export CVSROOT=":pserver:cvs@cvs.xyz.net:/cvsroot";到启动脚本并且有效。
【解决方案2】:

您是否以 root 身份启动该进程?系统上正在运行什么版本的(bash?)?您可能想试一试 csh 以排除 shell 本身的问题。我还建议使用 '&' 而不是 ';' 链接命令。最后,您可能会发现创建一个包含所有命令并由您的 java 进程调用的 shell 脚本更容易。您可能还想调查 nohup 并检查 /etc/security/limits

【讨论】:

  • bash --version GNU bash,版本 3.2.25(1)-release (x86_64-redhat-linux-gnu)
  • 我看到的唯一问题是我无法向操作系统发出任何命令。我想知道是否是因为 java 程序在重新启动或通过服务启动时没有在 shell 中运行。我将尝试 cmds 之间的 &
  • 是的,它以 root 身份运行
【解决方案3】:

您可能更乐意使用 http://akuma.kohsuke.org/ 来帮助您解决这些问题,或者至少使用 Apache Commons Exec。

【讨论】:

    【解决方案4】:

    如果有人遇到问题,这是解决我的问题的启动脚本

    #!/bin/sh
    # chkconfig: 2345 95 1
    # description: Starts Daemon Using ServerManager.jar.
    # 
    # Source function library.
    . /etc/init.d/functions
    
    RETVAL=0
    prog="ServerManager"
    servermanager="java"
    serveroptions=" -jar ServerManager.jar"
    pid_file="/var/run/servermanager.pid"
    
    launch_daemon()
    {
      /bin/sh << EOF
         java -Ddaemon.pidfile=$pid_file $serveroptions <&- &
         pid=\$!
         echo \${pid}
    EOF
    }
    
    start () {
        echo -n $"Starting $prog: "
     if [ -e /var/lock/subsys/servermanager ]; then
                    if [ -e /var/run/servermanager.pid ] && [ -e /proc/`cat /var/run/servermanager.pid` ]; then
                    echo -n $"cannot start: servermanager is already running.";
                    failure $"cannot start: servermanager already running.";
                    echo
                    return 1
                    fi
            fi
        # start daemon
        cd /www/voodoo_servermanager/
        export CVSROOT=":pserver:cvsd@cvs.zzzzz.yyy:/cvsroot";
        daemon "$servermanager $serveroptions > /www/logs/ServerManager.log &"
        #daemon_pid=`launch_daemon`
        #daemon ${daemon_pid}
        RETVAL=$?
        echo
        [ $RETVAL = 0 ] && touch /var/lock/subsys/servermanager && pidof $servermanager > $pid_file
        echo "";
        return $RETVAL
    }
    
    stop () {
        # stop daemon
        echo -n $"Stopping $prog: "
            if [ ! -e /var/lock/subsys/servermanager ]; then
                echo -n $"cannot stop ServerManager:  ServerManager is not running."
                failure $"cannot stop ServerManager:  ServerManager is not running."
            echo
            return 1;
            fi
            killproc $servermanager
            RETVAL=$?
            echo
            [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/servermanager;
            return $RETVAL
    }
    
    restart() {
        stop
        start
    }
    
    case $1 in
        start)
            start
        ;;
        stop)
            stop
        ;;
        restart)
            restart
        *)
    
        echo $"Usage: servermngr {start|stop|restart}"
        RETVAL=1
    esac
    
    exit $RETVAL
    

    【讨论】:

      猜你喜欢
      • 2023-03-02
      • 2015-06-02
      • 2014-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-15
      • 2014-08-07
      • 2012-12-03
      相关资源
      最近更新 更多