程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP綜合 >> linux獲取daemon進程的控制台數據

linux獲取daemon進程的控制台數據

編輯:PHP綜合

linux獲取daemon進程的控制台數據?

linux提供了一個daemon函數,使得進程可以脫離控制台運行,實現了後台運行的效果。但是進程後台運行後,原本在終端控制台輸出的數據就看不到了。那麼,怎樣才能找回這些數據?
這裡,文章主題就圍繞著 如何獲得後台進程的控制台數據,其中的原理要從daemon說起。
daemon主要做兩件事:
1、創建子進程,退出當前進程,並且以子進程創建新會話。這樣,就算父進程退出,子進程也不會被關閉

2、將標准輸入,標准輸出,標准錯誤都重定向/dev/null

daemon 實現大致如下:

int daemonize(int nochdir, int noclose) 
{ 
	int fd;

	switch (fork()) {
	case -1:
		return (-1);
	case 0:
		break;
	default:
		_exit(EXIT_SUCCESS);
	}

	if (setsid() == -1)
		return (-1);

	if (nochdir == 0) {
		if(chdir("/") != 0) {
			perror("chdir");
			return (-1);
		}
	}

	if (noclose == 0 && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
		if(dup2(fd, STDIN_FILENO) < 0) {
			perror("dup2 stdin");
			return (-1);
		}
		if(dup2(fd, STDOUT_FILENO) < 0) {
			perror("dup2 stdout");
			return (-1);
		}
		if(dup2(fd, STDERR_FILENO) < 0) {
			perror("dup2 stderr");
			return (-1);
		}

		if (fd > STDERR_FILENO) {
			if(close(fd) < 0) {
				perror("close");
				return (-1);
			}
		}
	}
	return (0);
}

所以,想取回進程的控制台數據,只要將標准輸出,標准錯誤重定向到指定文件,然後讀取這個文件就好了。
文章這裡寫了個例子,簡單演示下(這裡通過kill信號完成進程通信,有點粗暴) 代碼如下,保存為 daemon_example.c

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>

static int fd = -1;

void sigroutine(int dunno) {
	switch (dunno) {
	case SIGUSR1:
		fprintf(stderr, "Get a signal -- SIGUSR1 \n");
		if (fd != -1) close(fd);
		fd = open("/tmp/console_temp.log", O_RDWR|O_APPEND|O_CREAT, 0600);
		if (fd == -1) break;
		dup2(fd, STDIN_FILENO);
		dup2(fd, STDOUT_FILENO);
		dup2(fd, STDERR_FILENO);
		break;
		
	case SIGUSR2:
		fprintf(stderr, "Get a signal -- SIGUSR2 \n");
		if (fd != -1) close(fd);
		fd = open("/dev/null", O_RDWR, 0);
		if (fd == -1) break;
		dup2(fd, STDIN_FILENO);
		dup2(fd, STDOUT_FILENO);
		dup2(fd, STDERR_FILENO);
		break;
	}
	return;

}

int main() {
	signal(SIGUSR1, sigroutine);
	signal(SIGUSR2, sigroutine);

	daemon(1,0);
	for (;;){
			fprintf(stderr,"test \n") ; // 不斷打印test
			sleep(1);
	}
	return 0;
}

然後,編譯和執行這個程序:$ gcc -o daemon_example daemon_example.c $ chmod +x daemon_example $ ./daemon_example
$ ps -ef| grep daemon_example
root     11328     1  0 19:15 ?        00:00:00 ./daemon_example
如上,進程後台運行了,拿到pid 11328
接著,寫個腳本測試這個程序, 保存為test.sh:

#!/bin/bash

pid=$1
ps -p $pid>/dev/null
if [ ! $? -eq 0 ] ; then
	echo pid does not exist!
	exit 1
fi
echo pid $pid
trap "kill -usr2 $pid && exit 1" HUP INT QUIT TERM
kill -usr1 $pid
echo it works,please wait..
sleep 1
tail -f -n 0 /tmp/console_temp.log
echo done!

執行這個腳本,結果如下:$ ./test.sh 11328
pid 11328
it works,please wait..
test 
test 然後,按ctrl+c 退出腳本,這時腳本會通知進程將標准輸出和標准錯誤重定向到 /dev/null,繼續後台運行。 這樣,這個腳本就成了後台進程的調試工具了,需要後台數據的時候執行一下,不需要就關閉。當然,這只是一個示例,實際應用中要做改善,比如kill信號改 成pipe或socket通訊,緩存文件要限制大小,或自動清除等。

*
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved