首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >获取subshell命令的pid

获取subshell命令的pid
EN

Stack Overflow用户
提问于 2016-01-16 04:53:09
回答 3查看 1.2K关注 0票数 1

我正在尝试为一个java程序写一个init服务脚本。我在init脚本中有以下内容。

代码语言:javascript
复制
$USER = awesomeuser

$PROGRAM_CMD = "java -server com.test.TestClass"

$PROGRAM_LOG = "/var/log/awesome_log"

sudo -u $USER nohup $PROGRAM_CMD >> $PROGRAM_LOG 2>&1 </dev/null &
server_pid=$!
echo $server_pid > $pidfile

现在的情况是,我得到了父进程的pid,但我真的希望从子subshell中运行java进程的pid。

有没有什么方法我可以构造命令,这样我就可以得到subshell命令pid?

谢谢!

EN

回答 3

Stack Overflow用户

发布于 2016-01-16 05:56:45

而不是

代码语言:javascript
复制
sudo -u $USER nohup $PROGRAM_CMD >> $PROGRAM_LOG 2>&1 </dev/null &

试试这个:

代码语言:javascript
复制
sudo -u $USER bash -c "nohup $PROGRAM_CMD >> $PROGRAM_LOG 2>&1 & </dev/null; echo "'$!'

sudo通常生成子进程并在其中调用exec。通过正确配置sudo (请参阅sudo(1)),可以避免fork-ing。但对我来说,设置用户并运行另一个shell似乎更容易。

在我看来,这种方法比通过ps | grep | blabla获取进程的pid更好,因为它避免了竞争条件:一旦shell运行了后台进程,获得pid的唯一正确方法就是打印$!变量。否则,我们可能会得到错误程序的pid,或者如果java快速终止,甚至根本没有pid。

顺便说一句,为了给变量分配适当的值,脚本的开始行应该是

代码语言:javascript
复制
USER=awesomeuser
PROGRAM_CMD="java -server com.test.TestClass"
PROGRAM_LOG="/var/log/awesome_log"

而不是

代码语言:javascript
复制
$USER = awesomeuser
$PROGRAM_CMD = "java -server com.test.TestClass"
$PROGRAM_LOG = "/var/log/awesome_log"
票数 2
EN

Stack Overflow用户

发布于 2016-01-16 05:38:15

使用另一个脚本有什么问题:

findpid.sh

代码语言:javascript
复制
#!/bin/bash
pid=""
pidfile="pid.log"

while [ -z "${pid}" ]; do
    pid=`ps -U "${1}" | grep "${2}" | xargs | cut -d" " -f 1`
done

echo "${pid}" > ${pidfile}

然后在脚本中调用findpid.sh。您可以在调用java时使用时间戳,以确保使用ps标识正确的进程。

代码语言:javascript
复制
#!/bin/bash
USER=awesomeuser
TIME=`date +"%s"`
PROGRAM_CMD="java -server com.test.TestClass java -Dtime=${TIME}"
PROGRAM_LOG="awesome_log"

bash findpid.sh "${USER}" "${PROGRAM_CMD}" &
sudo -u $USER nohup $PROGRAM_CMD >> $PROGRAM_LOG 2>&1 </dev/null &
wait
票数 1
EN

Stack Overflow用户

发布于 2016-01-16 07:03:43

如果没有shell支持,您就不能做到这一点,而且bash也没有提供正确的原语。更改感兴趣的进程以输出或存储其自己的PID是正确的方法。

如果你不能修改应用程序代码,你可以使用一个简单的包装器,比如:

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

/*
 * pidder cmd args - launch cmd with args and print its pid
 */

int
main(int argc, char *argv[])
{
    if (argc < 2) {
        fprintf(stderr, "usage: pidder command [args]\n");
        exit(2);
    }

    switch(fork()) {
        case -1:
            perror("fork");
            exit(2);
        case 0:
            printf("%d\n", getpid());
            /* launch cmd with path search if relative path */
            execvp(argv[1], argv+1);
            perror("exec");
            exit(1);
        default:
            exit(0);
    }

}

如果您使用它,请注意$ ./pidder some_command将与$ some_command有细微的不同,一个简单的例子是,在第一种情况下,PPID将不是调用的外壳。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34819671

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档