此问题是此问题的后续问题:
Controlling a C daemon from another program
我的目标是从另一个程序控制守护进程的执行。
守护进程的代码非常简单。
int main()
{
printf("Daemon starting ...\n");
openlog("daemon-test", LOG_PID, LOG_DAEMON);
syslog(LOG_INFO, "Daemon started !\n");
while(1)
{
syslog(LOG_INFO, "Daemon alive - pid=%d, pgid=%d\n", getpid(), getpgrp());
sleep(1);
}
return EXIT_SUCCESS;
}
我为这个守护进程实现了一个systemv init脚本,如下所示
#!/bin/sh
NAME=daemon-test
DAEMON=/usr/bin/${NAME}
SCRIPTNAME=/etc/init.d/${NAME}
USER=root
RUN_LEVEL=99
PID_FILE=/var/run/${NAME}.pid
RETRY=3
start_daemon()
{
start-stop-daemon --start --background --name ${NAME} --chuid ${USER} --nicelevel ${RUN_LEVEL} --make-pidfile --pidfile ${PID_FILE} --exec ${DAEMON}
ret=$?
if [ "$ret" -eq 0 ]; then
echo "'${NAME}' started"
elif [ "$ret" -eq 1 ]; then
echo "'${NAME}' is already running"
else
echo "An error occured starting '${NAME}'"
fi
return ${ret}
}
stop_daemon()
{
start-stop-daemon --stop --retry ${RETRY} --remove-pidfile --pidfile ${PID_FILE} --name ${NAME} --signal 9
ret=$?
if [ "$ret" -eq 0 ]; then
echo "'${NAME}' stopped"
elif [ "$ret" -eq 1 ]; then
echo "'${NAME}' is already stopped"
elif [ "$ret" -eq 2 ]; then
echo "'${NAME}' not stopped after ${RETRY} tries"
else
echo "An error occured stopping '${NAME}'"
fi
return ${ret}
}
status_daemon()
{
start-stop-daemon --status --pidfile ${PID_FILE} --name ${NAME}
ret=$?
if [ "$ret" -eq 0 ]; then
echo "'${NAME}' is running"
elif [ "$ret" -eq 1 ]; then
echo "'${NAME}' stopped but pid file exits"
elif [ "$ret" -eq 3 ]; then
echo "'${NAME}' stopped"
elif [ "$ret" -eq 4 ]; then
echo "Unable to get '${NAME}' status"
else
echo "Unknown status : ${ret}"
fi
return ${ret}
}
case "$1" in
start)
echo "Starting '${NAME}' deamon :"
start_daemon
;;
stop)
echo "Stopping '${NAME}' deamon :"
stop_daemon
;;
status)
echo "Getting '${NAME}' deamon status :"
status_daemon
;;
restart|reload)
"$0" stop
"$0" start
;;
*)
echo "Usage: $0 {start|stop|status|restart}"
exit 1
esac
exit $?
从命令行使用这个脚本来控制守护进程的执行效果良好。
所以现在的目标是使用另一个C程序中的这个脚本来启动守护进程,并从这个程序控制它的执行。
我已经实现了一个简单的C程序,它:
-
使用“start”参数启动脚本
-
等待PID文件创建
-
从pid文件读取守护进程的pid
-
通过检查文件是否存在,定期检查守护进程是否处于活动状态
/proc/<daemon_pid>/exec
-
如果守护进程被杀死,重新启动它
这就是我面临的问题。只有当我不打电话的时候,程序才能正常工作
pclose
.
这是程序代码
#define DAEMON_NAME "daemon-test"
#define DAEMON_START_CMD "/etc/init.d/" DAEMON_NAME " start"
#define DAEMON_STOP_CMD "/etc/init.d/" DAEMON_NAME " stop"
#define DAEMON_PID_FILE "/var/run/" DAEMON_NAME ".pid"
int main()
{
char daemon_proc_path[256];
FILE* daemon_pipe = NULL;
int daemon_pid = 0;
FILE* fp = NULL;
int ret = 0;
int i = 0;
printf("Launching '%s' program\n", DAEMON_NAME);
if(NULL == (daemon_pipe = popen(DAEMON_START_CMD, "r")))
{
printf("An error occured launching '%s': %m\n", DAEMON_START_CMD);
return EXIT_FAILURE;
}
#ifdef USE_PCLOSE
else if(-1 == (ret = pclose(daemon_pipe)))
{
printf("An error occured waiting for '%s': %m\n", DAEMON_START_CMD);
return EXIT_FAILURE;
}
#endif
else
{
printf("Script exit status : %d\n", ret);
while(0 != access(DAEMON_PID_FILE, F_OK))
{
printf("Waiting for pid file creation\n");
sleep(1);
}
if(NULL == (fp = fopen(DAEMON_PID_FILE, "r")))
{
printf("Unable to open '%s'\n", DAEMON_PID_FILE);
return EXIT_FAILURE;
}
fscanf(fp, "%d", &daemon_pid);
fclose(fp);
printf("Daemon has pid=%d\n", daemon_pid);
sprintf(daemon_proc_path, "/proc/%d/exe", daemon_pid);
}
while(1)
{
if(0 != access(daemon_proc_path, F_OK))
{
printf("\n--- Daemon (pid=%d) has been killed ---\n", daemon_pid);
printf("Relaunching new daemon instance...\n");
if(NULL == (daemon_pipe = popen(DAEMON_START_CMD, "r")))
{
printf("An error occured launching '%s': %m\n", DAEMON_START_CMD);
return EXIT_FAILURE;
}
#ifdef USE_PCLOSE
else if(-1 == (ret = pclose(daemon_pipe)))
{
printf("An error occured waiting for '%s': %m\n", DAEMON_START_CMD);
return EXIT_FAILURE;
}
#endif
else
{
printf("Script exit status : %d\n", ret);
while(0 != access(DAEMON_PID_FILE, F_OK))
{
printf("Waiting for pid file creation\n");
sleep(1);
}
if(NULL == (fp = fopen(DAEMON_PID_FILE, "r")))
{
printf("Unable to open '%s'\n", DAEMON_PID_FILE);
return EXIT_FAILURE;
}
fscanf(fp, "%d", &daemon_pid);
fclose(fp);
printf("Daemon has pid=%d\n", daemon_pid);
sprintf(daemon_proc_path, "/proc/%d/exe", daemon_pid);
}
}
else
{
printf("Daemon alive (pid=%d)\n", daemon_pid);
}
sleep(1);
}
return EXIT_SUCCESS;
}
据我所知
锁相环
应该等待子进程终止,只有当子进程返回时,它才会关闭管道。
所以我不明白为什么我的实现
锁相环
不打电话就不工作。
这是带和不带
锁相环
块注释
没有
锁相环
打电话:
# ./popenTest
Launching 'daemon-test' program
Script exit status : 0
Waiting for pid file creation
Daemon has pid=435
Daemon alive (pid=435)
Daemon alive (pid=435)
Daemon alive (pid=435)
Daemon alive (pid=435)
用
锁相环
打电话:
# ./popenTest
Launching 'daemon-test' program
Script exit status : 36096
Waiting for pid file creation
Waiting for pid file creation
Waiting for pid file creation
Waiting for pid file creation
如您所见,守护进程从不启动,PID文件也从不创建。
即使我的程序没有
锁相环
我想了解呼叫的潜在问题
锁相环
.
为什么使用
锁相环
如果行为良好而不调用程序,会导致程序失败?
编辑:
以下是错误案例的更多信息
errno是
Success
wifexited宏返回true
wexitstatus宏返回141
通过进一步的调试,我已经注意到修改init脚本以将输出记录到一个文件中可以使它工作…
为什么?