Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从另一个程序控制C守护进程_C_Linux_Daemon_Interprocess - Fatal编程技术网

从另一个程序控制C守护进程

从另一个程序控制C守护进程,c,linux,daemon,interprocess,C,Linux,Daemon,Interprocess,我试图从另一个用户空间程序控制一个C守护程序 -简单C守护进程 这个守护进程只是一个C程序,它对自身进行守护并通过syslog每秒记录一条消息 #include <stdlib.h> #include <stdio.h> #include <syslog.h> #include <unistd.h> #include <signal.h> void bye(); int main() { printf("Daemon start

我试图从另一个用户空间程序控制一个C守护程序

-简单C守护进程 这个守护进程只是一个C程序,它对自身进行守护并通过syslog每秒记录一条消息

#include <stdlib.h>
#include <stdio.h>
#include <syslog.h>
#include <unistd.h>
#include <signal.h>

void bye();

int main()
{
  printf("Daemon starting ...\n");
  openlog("daemon-test", LOG_PID, LOG_DAEMON);
  signal(SIGTERM, bye);

  if(0 != daemon(0, 0))
  {
    syslog(LOG_ERR, "Can't daemonize\n");
    return EXIT_FAILURE;
  }

  syslog(LOG_INFO, "Daemon started !\n");

  while(1)
  {
    syslog(LOG_INFO, "Daemon alive\n");
    sleep(1);
  }

  return EXIT_SUCCESS;
}

void bye()
{
  syslog(LOG_INFO, "Daemon killed !\n");
  exit(EXIT_SUCCESS);
}
测试程序日志:

系统日志:

因此,我可以从我的C程序中启动并杀死守护进程,但是我希望在某些特定情况下改进其行为

-处理守护进程崩溃 守护进程可能会在某个点失败,在这种情况下,应该通知控制程序,以便重新启动它。我的问题是检测守护进程是否已停止

我曾经考虑过通过调用
pclose
来启动一个等待守护进程终止的线程,但是它不会工作,因为守护进程已经关闭了文件描述符并分离了进程

因此,我正在寻找在守护进程退出时通知程序的最佳方法

我可以使用带有
exec
系列的linux调用进行轮询(例如
pgrep daemon test
ps aux|grep daemon test
),但我认为有更有效的方法来实现这一点

-处理测试程序错误 如果测试程序在杀死守护进程之前被杀死或失败,那么在下一次执行时,守护进程的两个实例将同时运行

测试程序日志:

系统日志:

我想通过检查是否已经有守护进程实例在运行来避免这种情况。如果没有,我可以从控制程序启动守护进程

否则,如果守护进程的一个或多个实例正在运行,我将在启动新实例之前杀死它们

这可以通过调用
killall daemon test
来实现,但是每次执行时调用这个命令并不能满足我的要求,因为它在大多数情况下都是无用的

此外,我想明确记录每次执行时的情况,尽管我想知道在这种情况下有多少实例正在运行

同样,这可以通过linux命令调用轻松解决,但我正在寻找最有效的方法

有人知道我如何在不依赖linux命令调用的情况下实现守护进程控制吗?


编辑:2018年6月26日

我应该从一开始就对其进行精确化,但我的目标是能够监控守护进程,而不必修改其代码


因此,守护进程不会将其pid写入文件,并且始终与调用程序分离。

与其通过
popen
运行程序,不如使用旧的POSIX
fork
+
exec
?它给了你更多的灵活性

现在,回答你的问题:

我的问题是检测守护进程是否已停止

要做到这一点,您必须在父/控制过程中收听
SIGCHLD
信号。这已经足够好了,因为您直接调用了流程。但是,如果您调用一个shell脚本,然后将其分叉给您的守护进程,这将变得很困难。这就是为什么大多数守护进程都会编写一个名为
pid
文件的文件——一个早期由守护进程编写的文件,其pid是该文件中唯一的内容。通常,人们会把它放在
/tmp/mydaemon.pid
之类的地方

在Linux上,您的控制进程可以从该文件中读取PID,然后您可以每秒测试
/proc//exe
文件是否存在。如果没有,你就知道守护进程死了。例如,如果子程序的PID为1234,则
/proc/1234/exe
将是指向子程序可执行文件实际位置的软链接

大概是这样的:

FILE *f;
pid_t pid_child;
char proc_path[256];

f = fopen("/tmp/mydaemon.pid", "r");
fscanf(f, "%d", &pid_child);
fclose(f);
sprintf(proc_path, "/proc/%d/exe", pid_child);

while(1) {
    if (access(proc_path, F_OK) == 0) {
        printf("Program alive !\n");
        sleep(1);
    } else {
        printf("Program dead!\n");
        break;
    }
}

事实上,这大概是实现了多少init系统。请参阅rc、systemd、upstart等,以更好地了解它们是如何实现此功能的。您可以在守护进程中运行套接字服务器,然后使用control client作为普通CLI。CLI向守护进程发送测试消息或控制命令,守护进程给出响应。根据来自守护进程的响应,CLI可以监视守护进程的状态并控制它。

是否尝试过系统调用:?
kill()
如果我有它的pid,或者它与调用方在同一进程组中,则最好杀死守护进程。因此,这可能是一个解决方案,但是守护进程已将守护进程与其父进程分离,因此它不再位于同一进程组中,因此我必须获取守护进程pid。这就是为什么守护进程将其pid写入/var/run.um的原因。。。从系统管理员的角度来看,发行版的init服务(upstart、systemd等等)不应该负责启动守护进程并保持其运行吗?当然,您的其他启动/停止代码-就像
apache2ctl
。同样,从系统管理员的角度来看,我会给你的控制器程序添加一个状态检查,然后编写systemd配置文件,并将其打包成任何发行版。@Ivan通常我会使用systemd unit file或system V init脚本,但是我想克服这种init系统的使用。在使用
fork
+
execl
重新实现
popen
后,我尝试了返回子pid,只要守护进程将其pid写入文件或不进行守护,这似乎是一个很好的解决方案。我宁愿不修改守护程序的代码,所以我会记住这个解决方案,以防没有其他解决方案能更好地满足我的需要
start-stop-daemon
与您的解决方案相结合,允许我在不修改守护程序代码的情况下执行此操作。
$ ./popenTest 
Launching 'daemon-test' program
Program 'daemon-test' launched
Program alive !
Program alive !
Program alive !
Program alive !
Program alive !
Program 'daemon-test' killed
Jun 25 13:58:15 PC325 daemon-test[4445]: Daemon started !
Jun 25 13:58:15 PC325 daemon-test[4445]: Daemon alive
Jun 25 13:58:16 PC325 daemon-test[4445]: Daemon alive
Jun 25 13:58:17 PC325 daemon-test[4445]: Daemon alive
Jun 25 13:58:18 PC325 daemon-test[4445]: Daemon alive
Jun 25 13:58:19 PC325 daemon-test[4445]: Daemon alive
Jun 25 13:58:20 PC325 daemon-test[4445]: Daemon alive
Jun 25 13:58:20 PC325 daemon-test[4445]: Daemon killed !
$ ./popenTest 
Launching 'daemon-test' program
Program 'daemon-test' launched
Program alive !
Program alive !
Program alive !
^C
$ ./popenTest 
Launching 'daemon-test' program
Program 'daemon-test' launched
Program alive !
Program alive !
Program alive !
Program alive !
Program alive !
Program 'daemon-test' killed
Jun 25 14:17:25 PC325 daemon-test[4543]: Daemon started !
Jun 25 14:17:25 PC325 daemon-test[4543]: Daemon alive
Jun 25 14:17:26 PC325 daemon-test[4543]: Daemon alive
Jun 25 14:17:27 PC325 daemon-test[4543]: Daemon alive
Jun 25 14:17:28 PC325 daemon-test[4543]: Daemon alive
Jun 25 14:17:29 PC325 daemon-test[4543]: Daemon alive
Jun 25 14:17:29 PC325 daemon-test[4547]: Daemon started !
Jun 25 14:17:29 PC325 daemon-test[4547]: Daemon alive
Jun 25 14:17:30 PC325 daemon-test[4543]: Daemon alive
Jun 25 14:17:30 PC325 daemon-test[4547]: Daemon alive
Jun 25 14:17:31 PC325 daemon-test[4543]: Daemon alive
Jun 25 14:17:31 PC325 daemon-test[4547]: Daemon alive
Jun 25 14:17:32 PC325 daemon-test[4543]: Daemon alive
Jun 25 14:17:32 PC325 daemon-test[4547]: Daemon alive
Jun 25 14:17:33 PC325 daemon-test[4543]: Daemon alive
Jun 25 14:17:33 PC325 daemon-test[4547]: Daemon alive
Jun 25 14:17:34 PC325 daemon-test[4543]: Daemon alive
Jun 25 14:17:34 PC325 daemon-test[4547]: Daemon alive
Jun 25 14:17:34 PC325 daemon-test[4543]: Daemon killed !
Jun 25 14:17:34 PC325 daemon-test[4547]: Daemon killed !
FILE *f;
pid_t pid_child;
char proc_path[256];

f = fopen("/tmp/mydaemon.pid", "r");
fscanf(f, "%d", &pid_child);
fclose(f);
sprintf(proc_path, "/proc/%d/exe", pid_child);

while(1) {
    if (access(proc_path, F_OK) == 0) {
        printf("Program alive !\n");
        sleep(1);
    } else {
        printf("Program dead!\n");
        break;
    }
}