【问题标题】:Running daemon through rsh通过 rsh 运行守护进程
【发布时间】:2011-02-13 09:20:15
【问题描述】:

我想在 Unix 的远程机器上将程序作为守护进程运行。我有 rsh 连接,我希望程序在断开连接后运行。

假设我有两个程序:util.cpp 和 forker.cpp。

util.cpp 是一些实用程序,为了我们的目的,让它只是无限根。

util.cpp

int main() {
    while (true) {};
    return 0;
}

forker.cpp 获取一些程序并通过 fork() 和 execve() 在单独的进程中运行它:

forker.cpp

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char** argv) {
  if (argc != 2) {
    printf("./a.out <program_to_fork>\n");
    exit(1);
  }

  pid_t pid;

  if ((pid = fork()) < 0) {
    perror("fork error.");
    exit(1);
  } else if (!pid) {
    // Child.
    if (execve(argv[1], &(argv[1]), NULL) == -1) {
      perror("execve error.");
      exit(1);
    }
  } else {
    // Parent: do nothing.
  }
  return 0;
}

如果我跑:

./forker util

forker 很快就完成了,bash '没有暂停',而 util 正在作为守护进程运行。

但如果我跑:

scp forker remote_server://some_path/
scp program remote_server://some_path/
rsh remote_server 'cd /some_path; ./forker program'

那么一切都是一样的(即在 remote_sever 分叉器正在快速完成,util 正在运行)但是我在本地机器上的 bash 被暂停了。 它正在等待 util 停止(我检查了它。如果 util.cpp 正在返回,那就没问题了。),但我不明白为什么?!

有两个问题:

1) Why is it paused when I run it through rsh?

我确信我选择了一些愚蠢的方式来运行守护进程。所以

2) How to run some program as daemon in C/C++ in unix-like platforms.

Tnx!

【问题讨论】:

    标签: c unix fork daemon rsh


    【解决方案1】:

    1) 为什么我通过 rsh 运行它会暂停?

    当您派生一个进程时,子进程拥有自己的父文件描述符副本。子文件的每个文件描述符与父文件的相应文件描述符引用相同的打开文件描述。在您调用fork() 之后,您不会在调用execve() 之前关闭子进程中的标准流(stdinstdoutstderr),因此它们仍然连接到 rsh。只要远程服务器上的任何进程都持有对这些流的引用,rsh 就可能不会返回。您可以在调用execve() 之前尝试使用fclose() 关闭标准流,或者在执行forker 程序时重定向它们(即./forker program &gt;/dev/null 2&gt;/dev/null &lt;/dev/null)。

    2) 如何在类 unix 平台中以 C/C++ 的守护进程运行某些程序。

    根据wikipedianohup 最常用于在后台作为守护进程运行命令。这个网站上还有几个daemon related questions,你可以参考一下。

    来自wikipedia

    nohup 是一个忽略 HUP(挂起)信号的 POSIX 命令,使命令在发出命令的用户注销后继续运行。 HUP(挂断)信号按照惯例是终端根据注销进程发出警告的方式。

    如果您的程序将始终作为守护程序运行,您可以研究从程序中调用daemon() 的可能性。 daemon() 便利功能存在于某些 UNIX 系统中。

    来自daemon(3) man page

    daemon() 函数适用于希望将自身与控制终端分离并作为系统守护进程在后台运行的程序。

    如果您不存在此功能,或者您的程序不作为守护程序运行,您的 forker 程序也可以修改为“守护”您的其他程序。


    在不对代码进行任何更改的情况下,您可以尝试以下操作:

    rsh remote_server 'cd /some_path; nohup ./forker program &gt;program.out 2&gt;program.err &lt;/dev/null &amp;'

    【讨论】:

    • 嗯,rsh remote_host './forker program >/dev/null 2>/dev/null /null' 解决了它。你能告诉我“/null &”是什么吗?
    • 关于第二个问题,我认为您的意思是 nohup ./program,而不是 nohup ./forker 程序。无论如何,nohup 在程序运行之前不会返回。这就是我需要 forker 的原因。如果您 rsh 到服务器并在此之后写入“nohup ./program”,如果您关闭会话,则程序仍在运行。但是,如果您尝试运行 'rsh server "nohup ./program"',则会再次暂停。如果按 ctrl-c,程序将停止。无论如何,我对第一个问题很感兴趣。
    • &lt;/dev/nullstdin 重定向到/dev/null&amp; 在后台启动进程
    • 好吧,虽然有目标,但还是不太明白。 rsh server './program 1>pr.out 2>pr.err &' 也解决了我的问题,没有分叉。对我来说,我刚刚得到 './program &' 比 'nohup ./program' 然后注销要容易得多。正如我通常理解的那样,对你来说没有区别。