<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://jackxiang.com/post//</link>
<title><![CDATA[linux获取daemon进程的控制台数据]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[Unix/LinuxC技术]]></category>
<pubDate>Sun, 24 Jul 2016 07:53:45 +0000</pubDate> 
<guid>http://jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	linux提供了一个daemon函数，使得进程可以脱离控制台运行，实现了后台运行的效果。但是进程后台运行后，原本在终端控制台输出的数据就看不到了。那么，怎样才能找回这些数据？<br/> <br/>这里，文章主题就围绕着 如何获得后台进程的控制台数据，其中的原理要从daemon说起。<br/> <br/>daemon主要做两件事：<br/>1、创建子进程，退出当前进程，并且以子进程创建新会话。这样，就算父进程退出，子进程也不会被关闭<br/>2、将标准输入，标准输出，标准错误都重定向/dev/null<br/><br/>daemon 实现大致如下：<br/><br/>int daemonize(int nochdir, int noclose) <br/>&#123; <br/>&nbsp;&nbsp;int fd;<br/><br/>&nbsp;&nbsp;switch (fork()) &#123;<br/>&nbsp;&nbsp;case -1:<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (-1);<br/>&nbsp;&nbsp;case 0:<br/>&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;default:<br/>&nbsp;&nbsp;&nbsp;&nbsp;_exit(EXIT_SUCCESS);<br/>&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;if (setsid() == -1)<br/>&nbsp;&nbsp;&nbsp;&nbsp;return (-1);<br/><br/>&nbsp;&nbsp;if (nochdir == 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(chdir(&quot;/&quot;) != 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;chdir&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return (-1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;if (noclose == 0 &amp;&amp; (fd = open(&quot;/dev/null&quot;, O_RDWR, 0)) != -1) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(dup2(fd, STDIN_FILENO) &lt; 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;dup2 stdin&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return (-1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(dup2(fd, STDOUT_FILENO) &lt; 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;dup2 stdout&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return (-1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(dup2(fd, STDERR_FILENO) &lt; 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;dup2 stderr&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return (-1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if (fd &gt; STDERR_FILENO) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(close(fd) &lt; 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;close&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return (-1);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;return (0);<br/>&#125;<br/>所以，想取回进程的控制台数据，只要将标准输出，标准错误重定向到指定文件，然后读取这个文件就好了。<br/> <br/>文章这里写了个例子，简单演示下（这里通过kill信号完成进程通信，有点粗暴）<br/>代码如下，保存为 daemon_example.c<br/>#include <br/>#include <br/>#include <br/>#include <br/><br/>static int fd = -1;<br/><br/>void sigroutine(int dunno) &#123;<br/>&nbsp;&nbsp;switch (dunno) &#123;<br/>&nbsp;&nbsp;case SIGUSR1:<br/>&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr, &quot;Get a signal -- SIGUSR1 &#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (fd != -1) close(fd);<br/>&nbsp;&nbsp;&nbsp;&nbsp;fd = open(&quot;/tmp/console_temp.log&quot;, O_RDWR&#124;O_APPEND&#124;O_CREAT, 0600);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (fd == -1) break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;dup2(fd, STDIN_FILENO);<br/>&nbsp;&nbsp;&nbsp;&nbsp;dup2(fd, STDOUT_FILENO);<br/>&nbsp;&nbsp;&nbsp;&nbsp;dup2(fd, STDERR_FILENO);<br/>&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;case SIGUSR2:<br/>&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr, &quot;Get a signal -- SIGUSR2 &#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (fd != -1) close(fd);<br/>&nbsp;&nbsp;&nbsp;&nbsp;fd = open(&quot;/dev/null&quot;, O_RDWR, 0);<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (fd == -1) break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;dup2(fd, STDIN_FILENO);<br/>&nbsp;&nbsp;&nbsp;&nbsp;dup2(fd, STDOUT_FILENO);<br/>&nbsp;&nbsp;&nbsp;&nbsp;dup2(fd, STDERR_FILENO);<br/>&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;return;<br/><br/>&#125;<br/><br/>int main() &#123;<br/>&nbsp;&nbsp;signal(SIGUSR1, sigroutine);<br/>&nbsp;&nbsp;signal(SIGUSR2, sigroutine);<br/><br/>&nbsp;&nbsp;daemon(1,0);<br/>&nbsp;&nbsp;for (;;)&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&quot;test &#92;n&quot;) ; // 不断打印test<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep(1);<br/>&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;return 0;<br/>&#125;<br/>然后，编译和执行这个程序：<br/>$ gcc -o daemon_example daemon_example.c<br/>$ chmod +x daemon_example<br/>$ ./daemon_example<br/>$ ps -ef&#124; grep daemon_example<br/>root 11328 1 0 19:15 ? 00:00:00 ./daemon_example<br/>如上，进程后台运行了，拿到pid 11328<br/><textarea name="code" class="php" rows="15" cols="100">
[root@iZ25dcp92ckZ testdemo]# gcc -o daemon_example daemon_example.c
[root@iZ25dcp92ckZ testdemo]#./daemon_example
[root@iZ25dcp92ckZ testdemo]# ps -ef&#124; grep daemon_example
root&nbsp;&nbsp;&nbsp;&nbsp; 16935&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;0 15:51 ?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;00:00:00 ./daemon_example
[root@iZ25dcp92ckZ testdemo]#&nbsp;&nbsp;./test.sh 16935
pid 16935
it works,please wait..
test 
test 
test 
test 
test 
test 
</textarea><br/>按ctrl+c 退出脚本，这时脚本会通知进程将标准输出和标准错误重定向到 /dev/null，继续后台运行。<br/>[root@iZ25dcp92ckZ testdemo]# sh -x ./test.sh 16935&nbsp;&nbsp; <br/>+ pid=16935<br/>+ ps -p 16935<br/>+ &#039;[&#039; &#039;!&#039; 0 -eq 0 &#039;]&#039;<br/>+ echo pid 16935<br/>pid 16935<br/>+ trap &#039;kill -usr2 16935 &amp;&amp; exit 1&#039; HUP INT QUIT TERM<br/>+ kill -usr1 16935<br/>+ echo it works,please wait..<br/>it works,please wait..<br/>+ sleep 1<br/>+ tail -f -n 0 /tmp/console_temp.log<br/>test <br/>test <br/>test <br/>test <br/>==========================================================<br/>接着，写个脚本测试这个程序， 保存为test.sh：<br/>#!/bin/bash<br/><br/>pid=$1<br/>ps -p $pid&gt;/dev/null<br/>if [ ! $? -eq 0 ] ; then<br/>&nbsp;&nbsp;echo pid does not exist!<br/>&nbsp;&nbsp;exit 1<br/>fi<br/>echo pid $pid<br/>trap &quot;kill -usr2 $pid &amp;&amp; exit 1&quot; HUP INT QUIT TERM<br/>kill -usr1 $pid<br/>echo it works,please wait..<br/>sleep 1<br/>tail -f -n 0 /tmp/console_temp.log<br/>echo done!<br/>执行这个脚本，结果如下：<br/>$ ./test.sh 11328<br/>pid 11328<br/>it works,please wait..<br/>test<br/>test<br/>然后，按ctrl+c 退出脚本，这时脚本会通知进程将标准输出和标准错误重定向到 /dev/null，继续后台运行。<br/>这样，这个脚本就成了后台进程的调试工具了，需要后台数据的时候执行一下，不需要就关闭。当然，这只是一个示例，实际应用中要做改善，比如kill信号改成pipe或socket通讯，缓存文件要限制大小，或自动清除等。<br/><br/>摘自：http://blog.csdn.net/mycwq/article/details/50479735
]]>
</description>
</item><item>
<link>http://jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] linux获取daemon进程的控制台数据]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>