Linux / Bash文件描述符在执行守护进程时

我正在为我正在编写的C项目编写一个服务脚本,并在启动时执行一些实用程序。 我想要使​​用日志工具捕获所有的输出。 我在/ etc / rc5 / myscript中有类似的内容

#!/bin/bash #save fd 1 in fd 3 for use later exec 3<&1 $SERVICESCRIPT | logger 

logging器只是从stdin读取,直到碰到EOF。 第二个脚本是检查一堆公用程序是否正在运行,并触发它自己的一些。 在这些公用事业中,有一个分叉并成为守护进程。 现在,我从脚本运行它,它inheritance了所有的脚本fds。 这会导致脚本在被调用后永远不会返回到命令行。

我试图用几种方法来解决这个问题:

首先,在我的脚本中,我已经完成了以下工作:

 ( exec 4<&- exec 3<&- $daemon_process ) 

这应该启动一个下标,closures3和4(分别用于存储标准输出和pipe道输出)并运行程序。 但是当我试图回到命令行的时候,我仍然觉得这是一个悬而未决的问题,这使我相信pipe道并没有closures。 经过进一步调查,如果我在closures后发出回声,并将它们redirect到input到logging器的fd,我会在日志中看到它们,告诉我fd确实仍然是机智的。 如果我在c程序中closuresfds 2-4,我会看到它返回到命令行,但这是一个非常混乱和不愉快的修复。

其次我尝试了以下内容:

 $daemon_process 4<&- 3<&- 

在调用这个程序的时候应该closuresfds,但是我看到了脚本永远不会回到命令行的结果。

当脚本手中我可以“CTRL-C”它把它回到命令行,但这绝不是一个解决scheme。

有任何想法吗?

谢谢!!!!

您的/etc/rc5/myscript不会因为$SERVICESCRIPT的任何内容而被阻塞。 这是阻塞,因为它正在等待logger终止,这是不会直到写入到它的STDIN的一切都终止(这是你的守护进程,在这种情况下)。

你可以看到这个简单的例子。 考虑这个简单的C程序,孤儿自己,然后永远不会做任何事情:

 #include <stdlib.h> int main( int argc, char *argv[] ){ if( fork() ){ exit( 0 ); } while( 1 ){ sleep( 1 ); } return EXIT_SUCCESS; } 

和这个简单的“记录器”,从STDIN直到EOF读取:

 #include <stdio.h> int main( int argc, char *argv[] ){ char c; while( 1 ){ c = getc( stdin ); if( c == EOF ){ break; } } return 0; } 

如果我一起运行,我不会得到我的命令提示符。

 $ ./forktest | ./logger <hangs> 

这是因为我的外壳正在等待整个管道完成。 forktest “完成”(它杀死自己),但logger器没有完成,这就是我们正在等待的。 forktest的孤儿过程是打开logger的STDIN。 在上面的运行过程中,通过检查另一个终端中的/proc/$pid/fd ,您可以看到从孤立的STDOUT(fd 1)(通知其父进程是1)到logger的STDIN(fd 0)

 $ ps -ef | grep forktest cneylan 25451 1 0 16:27 pts/7 00:00:00 ./forktest $ ps -ef | grep logger cneylan 25450 24379 0 16:27 pts/7 00:00:00 ./logger $ ls -l /proc/25451/fd total 0 lrwx------ 1 cneylan cneylan 64 Jul 2 16:28 0 -> /dev/pts/7 l-wx------ 1 cneylan cneylan 64 Jul 2 16:28 1 -> pipe:[944400] lrwx------ 1 cneylan cneylan 64 Jul 2 16:28 2 -> /dev/pts/7 lrwx------ 1 cneylan cneylan 64 Jul 2 16:28 3 -> /dev/pts/7 $ ls -l /proc/25450/fd total 0 lr-x------ 1 cneylan cneylan 64 Jul 2 16:28 0 -> pipe:[944400] lrwx------ 1 cneylan cneylan 64 Jul 2 16:28 1 -> /dev/pts/7 lrwx------ 1 cneylan cneylan 64 Jul 2 16:28 2 -> /dev/pts/7 lrwx------ 1 cneylan cneylan 64 Jul 2 16:28 3 -> /dev/pts/7 

作为一个侧面说明,当发生这种情况时,只会发出logger进程的信号,因为守护进程[应该有]调用setsid(2) ,这是守护进程本身的一个必要步骤。 所以要么^ C杀死你的守护进程,你需要让你的代码调用setsid(2)或者你的代码已经调用setsid(2)并且你有一堆流氓守护进程在后台运行:)

正如您正确地认识到的那样, logger的阻塞是读端处的管道和写端处的$daemon_process (最终)之间的管道问题。 既然你想把后者的输出写到屏幕上,

 $daemon_process >/dev/tty 

会解决问题。