C 后台监控从另一个程序通过脚本启动的进程

C 后台监控从另一个程序通过脚本启动的进程,c,perl,bash,daemon,background-process,C,Perl,Bash,Daemon,Background Process,我很犹豫是否要发布这个问题,因为我以为某个地方已经有人问过了,但经过反复的搜索,我的答案是空的,所以就在这里 背景:我正在运行一个本地代理(用C编写,通过TCP监听),它允许远程执行少量脚本/命令。脚本本身是二进制文件、bash或perl脚本的混合体,代理本身并不在意,只要它们在列表中是允许的 (这是在公司内部网络上进行的,而且还处于非常早期的阶段,所以现在请不要讨论安全性的优点。) 启动流程的C代理代码如下: sprintf(mrun, "%s %s 2>&1", file, a

我很犹豫是否要发布这个问题,因为我以为某个地方已经有人问过了,但经过反复的搜索,我的答案是空的,所以就在这里

背景:我正在运行一个本地代理(用C编写,通过TCP监听),它允许远程执行少量脚本/命令。脚本本身是二进制文件、bash或perl脚本的混合体,代理本身并不在意,只要它们在列表中是允许的

(这是在公司内部网络上进行的,而且还处于非常早期的阶段,所以现在请不要讨论安全性的优点。)

启动流程的C代理代码如下:

sprintf(mrun, "%s %s 2>&1", file, args);
mexec = popen(mrun, "r");
[read some returned buffer]
pclose(mexec);
这种方法适用于外部bash和perl脚本,只要脚本只执行命令(或在前台执行操作)。然而,我最近需要扩展一个脚本,以包含一个守护进程的重新启动,在本例中,名为

脚本本身(bash)很简单:

#!/bin/bash
pkill -9 named
/local/mnt/named/sbin/named -c /local/mnt/named/var/named.conf &
echo "restarted"
我遇到的问题是,当通过C代理运行时,脚本永远不会完成(即,重新启动时永远不会回显),因此控件永远不会返回,TCP套接字也永远不会释放。就代理而言,进程仍在运行。如果我从终端运行脚本,它工作正常,控制权返回给我

我是否遗漏了一些东西,在从C守护进程派生脚本时,与从bash终端调用脚本时,它们会允许脚本正常执行


我知道nohup,我想如果其他方法都失败了,我可以使用它,但我很好奇是否有其他的解决方法。根据以上评论的反馈,我能够让脚本在启动守护进程后继续工作,这要感谢一些额外的重定向:

/local/mnt/named/sbin/named -c /local/mnt/named/var/named.conf </dev/null &> /dev/null &
/local/mnt/named/sbin/named-c/local/mnt/named/var/named.conf/dev/null&
所以,多亏了fork0的知识

之后,我注意到TCP套接字连接无法正常关闭,即使脚本已完成工作。在下面提供了更多信息并进行了大量研究之后,子进程将从父进程(包括套接字)继承(并保持打开)文件描述符

我到处寻找否认子进程的方法,但没有真正找到任何对我有用的方法(或者没有完全重写代理)

最后,我偶然发现了这个问题,这个问题与我使用的编程语言相关,但与我使用的编程语言无关:

这基本上涉及到子进程关闭代码中任何打开的文件描述符,从而释放它们以供父进程关闭。(我想是吧?)

在启动named之前,我在bash脚本中添加了几行代码来完成这项工作,它确实可以工作

for i in `nawk 'BEGIN{ for(i=1;i<=255;i++) print i}'`
do
eval exec `echo $i | sed -e 's/.*/&<\&-/'`
done

对于'nawk'中的i开始{for(i=1;我是你的“C代理”读取所有输出?IOW,它是否正在等待其输入被另一方关闭?如果是,它可能永远不会完成:在后台启动的命名脚本保持stdout的句柄并正在运行。因此,即使重新启动脚本已完成,仍有要等待的输出(来自命名脚本)。请尝试为named提供自己的句柄:
../named…/dev/null&
,并查看它是否有帮助。它只读取缓冲区一次,因此不等待输入。您建议的更改在某种程度上有所帮助。脚本本身似乎已完成,我现在收到回音。但这带来了另一个问题:它似乎没有这样做脚本完成后,代理可以关闭套接字连接。它只是挂起,直到我杀死named。因此,现在看来,生成的进程保持原始TCP连接打开还有一个完全不同的问题,即使它不应该并且它们不使用相同的端口。@Randy:尝试执行
关闭
传入
关闭\RDWRclose
之前,查看套接字上的操作。套接字
fd
可能已复制到子进程。不幸的是,这并没有修复它。连接仍然保持打开状态。不过,可能与正在发生的事情很接近。您可能泄漏了不止一个stdio句柄。而且name甚至可以将它们作为hi来提取s、 在C代理执行脚本之前,您是否可以修改它以关闭所有句柄并将stdio句柄重定向到
/dev/null
(或者您记录/跟踪句柄)并将信号重置为默认值(以防设置了SIGALRM等)?