通过ssh获取使用nohup启动的进程的PID

8

我想通过ssh在远程机器上使用nohup启动一个进程。问题是如何获取使用nohup启动的进程的PID,以便获得“正在实际运行”的进程,而不是一些外层shell实例或类似的东西。此外,我想将stdout和stderr存储在文件中,但这不是本文的重点...

在本地,可以无缝使用以下命令:

nohup sleep 30 > out 2> err < /dev/null & echo $!

它正向我回显"sleep 30"命令的确切 PID 值,我也可以使用 "top" 或 "ps aux|grep sleep" 查看。

但是我在通过 SSH 远程执行时遇到了麻烦。我尝试了一些类似于

ssh remote_machine 'nohup bash -c "( ( sleep 30 ) & )" > out 2> err < /dev/null'

但是我找不到放置“echo $!”的位置,以便在本地shell中显示它。它总是显示错误的PID,例如“bash”实例的PID等。

有人有解决办法吗?

编辑: 好的,“bash -c”可能在这里不需要。正如Lotharyx指出的那样,我可以很好地使用以下方法获取正确的PID:

ssh remote 'nohup sleep 30 > out 2> err < /dev/null & echo $!'

但问题是,如果您用“echo Hello World!”替换“sleep 30”,那么输出不会出现在“out”文件中,无论是本地还是远程。有人知道为什么吗?
编辑2:我的错!另一台设备上没有剩余空间,这就是为什么“out”和“err”文件保持为空的原因!
所以这是有效的。此外,如果想要调用多个命令,用分号(;)隔开,仍然可以使用“bash -c”,像这样:
ssh remote 'nohup bash -c "echo bla;sleep 30;echo blupp" > out 2> err < /dev/null & echo $!'

然后它会打印出本地端“bash -c”的PID,这很好。 (无法获取“最内部”或“繁忙”进程的PID,因为每个程序本身都可以生成新的子进程,没有办法找到...)

1个回答

9

我尝试了以下内容(本地机器是Debian;远程机器是CentOS),它正如我认为你期望的那样工作:

    ~# ssh someone@somewhere 'nohup sleep 30 > out 2> err < /dev/null & echo $!'
    someone@somewhere's password:
    14193
    ~#

在远程机器上,我运行了ps -e命令,并看到了这行输出:

    14193 ?        00:00:00 sleep

因此很明显,在我的本地机器上,输出的是在远程机器上执行的“sleep”进程的PID。

为什么在通过SSH隧道发送命令时要添加bash?


嗯,你说得对,但是stdout似乎仍然存在问题。例如,如果我用像“echo Hello World!”这样产生输出的东西替换“sleep 30”,它不会出现在文件“out”中,而是像PID一样返回给我。 - proggy
我认为我添加了“bash -c”,是因为我想要连续执行多个命令,比如“echo foo;sleep 30;echo bar”。 - proggy
你好Lotharyx,你能解释一下重定向流吗?我猜>是主要输出,2>是错误输出,但是< /dev/null流是什么? - JesusTheHun
@JesusTheHun:就像 > 重定向标准输出,2> 重定向标准错误一样,< 重定向标准输入;在这种情况下,使用 /dev/null 作为输入源。 - Brian A. Henning
但是为什么需要向 sleep 函数提供输入源呢? - JesusTheHun
@JesusTheHun:在这种特定情况下,您不需要这样做;更重要的是,nohup 自动执行了这个精确的重定向,所以这是多余的。我只是尽可能原样使用 OP 的命令;实际上,在这个例子中并不需要它。 - Brian A. Henning

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接