linux获取后台进程的控制台输出,linux获取后台进程的控制台数据

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

#include

#include

#include

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通讯,缓存文件要大小限制。或自己主动清除等。

文章最后。是不是有点取巧。你有什么更好的办法,欢迎评论交流!

參考:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值