我正在为我正在编写的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
会解决问题。