我试图从另一个用户空间程序控制一个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测试程序启动和终止守护进程
为了测试的目的,我开发了一个最小的例子。我在用
popen
启动守护进程,因为我希望我的程序继续执行。
5秒后,测试程序应该会终止守护进程。
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#define DAEMON_NAME "daemon-test"
int main()
{
FILE* pipe = NULL;
int i = 0;
printf("Launching '%s' program\n", DAEMON_NAME);
if(NULL == (pipe = popen(DAEMON_NAME, "re")))
{
printf("An error occured launching '%s': %m\n", DAEMON_NAME);
return EXIT_FAILURE;
}
printf("Program '%s' launched\n", DAEMON_NAME);
while(i<5)
{
printf("Program alive !\n");
sleep(1);
i++;
}
if(NULL == (pipe = popen("killall " DAEMON_NAME, "re")))
{
printf("An error occured killing '%s' program: %m\n", DAEMON_NAME);
return EXIT_FAILURE;
}
printf("Program '%s' killed\n", DAEMON_NAME);
return EXIT_SUCCESS;
}
测试程序日志:
$ ./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 !
所以我可以从我的c程序中启动并杀死守护进程,但是我想在某些特定情况下改进行为。
-处理守护进程崩溃
守护进程可能在某个时刻失败,在这种情况下,应该通知控制程序,以便可以重新启动它。我的问题是检测守护进程是否已停止。
我想启动一个线程,等待通过调用
pclose
但是,它不能工作,因为子进程已经关闭文件描述符并分离进程。
所以我在寻找在后台程序退出时通知程序的最佳方法。
我可以使用linux调用
exec
家庭(例如
pgrep daemon-test
或
ps aux | grep daemon-test
)但我认为有更有效的方法来实现这一点。
-处理测试程序错误
如果测试程序在杀死守护进程之前被杀死或失败,在下一次执行时,守护进程的两个实例将同时运行。
测试程序日志:
$ ./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 !
我想通过检查是否已经有守护进程实例在运行来避免这种情况。如果没有,我可以从控制程序启动守护进程。
否则,如果守护进程的一个或多个实例正在运行,我将在启动新的守护进程之前杀死它们。
这可以通过调用
killall daemon-test
但是每次执行时调用这个命令并不满足我,因为大部分时间都是无用的。
此外,我想显式地记录每次执行时的情况,尽管我想知道在这种情况下到底有多少实例在运行。
再次强调,使用linux命令调用很容易解决这个问题,但我正在寻找最有效的方法来解决这个问题。
有人知道我如何实现后台进程控制而不必依赖Linux命令调用吗?
编辑:
2018年6月26日
我应该从一开始就对它进行精确化,但我的目标是能够监视守护进程
没有
必须修改代码。
因此守护进程不会将其pid写入文件,并且始终与其调用程序分离。