[英]Start a process in the background in Linux with C
I am trying to do something a little weird here. 我想在这里做一些有点奇怪的事情。 I need to start a process, logcat, from a deamon that will run in the background and print to the terminal without taking control of stdin. 我需要从一个将在后台运行的deamon启动一个进程logcat,并在不控制stdin的情况下打印到终端。 It is for logging so ideally logcat will print log messages while still allowing the user to input standard commands and initialize programs from the shell. 它用于日志记录,因此理想情况下logcat将打印日志消息,同时仍允许用户输入标准命令并从shell初始化程序。 Here is the code for the daemon I have so far. 这是我到目前为止守护进程的代码。 The program, logcat, starts and shows log messages but I cannot enter any commands into stdin as it appears that the program has taken control of stdin. 程序logcat启动并显示日志消息但我无法输入任何命令到stdin,因为程序似乎控制了stdin。
int main ( int argc, char** argv, char** env )
{
int fd;
if ((fd = open("/dev/console", O_RDWR)) < 0) {
fd = open("/dev/null", O_RDWR);
}
printf("THIS IS A TEST\n");
dup2(1, fd);
dup2(2, fd);
pid_t childpid = fork();
if(childpid == -1) {
perror("Failed to fork, logcat not starting");
return 1;
}
if(childpid == 0) {
//this is the child, exec logcat
setsid();
int execReturn = execl("/system/bin/logcat", "logcat", (char *) 0);
} else {
//this is the parent do nothing
close(fd);
return 0;
}
close(fd);
return 0;
}
Thanks 谢谢
How to Daemonize in Linux [dead link] 如何在Linux中进行Daemonize [死链接]
How to Daemonize in Linux [wayback machine archive of the above] 如何在Linux中进行Daemonize [以上的回程机器存档]
gist on github -- code taken from link above 关于github的要点 - 从上面的链接中获取的代码
Executive summary: 执行摘要:
One of the things I keep running across is Linux daemons that don't properly daemonize themselves. 我一直在运行的一件事是Linux守护进程,它们没有正确地守护自己。 To properly daemonize, the following steps must be followed. 要正确守护,必须遵循以下步骤。
- The fork() call is used to create a separate process. fork()调用用于创建单独的进程。
- The setsid() call is used to detach the process from the parent (normally a shell). setsid()调用用于将进程与父进程(通常是shell)分离。
- The file mask should be reset. 应重置文件掩码。
- The current directory should be changed to something benign. 应将当前目录更改为良性。
- The standard files (stdin,stdout and stderr) need to be reopened. 需要重新打开标准文件(stdin,stdout和stderr)。
Failure to do any of these steps will lead to a daemon process that can misbehave. 如果不执行任何这些步骤,将导致守护程序进程无法正常运行。 The typical symptoms are as follows. 典型症状如下。
- Starting the daemon and then logging out will cause the terminal to hang. 启动守护程序然后注销将导致终端挂起。 This is particularly nasty with ssh. 这对ssh特别讨厌。
- The directory from which the daemon was launched remains locked. 启动守护程序的目录保持锁定状态。
- Spurious output appears in the shell from which the daemon was started. 虚假输出出现在启动守护程序的shell中。
The 'logcat' command seems to be for Android development - that might explain the odd location of the command. 'logcat'命令似乎适用于Android开发 - 这可能解释了命令的奇怪位置。
The key operation that you must fix is to ensure that you close your current standard input (the terminal) and open /dev/null/
for the input device: 您必须修复的关键操作是确保关闭当前标准输入(终端)并为输入设备打开/dev/null/
:
close(0);
if ((fd = open("/dev/null", O_RDONLY)) != 0)
...error - failed to open /dev/null!
This means that your daemonized child process will not read anything from the terminal. 这意味着您的守护进程子进程将不会从终端读取任何内容。
What I think you want to do is: 我认为你想做的是:
/dev/null
. 在程序内部,您想要替换标准输入,因此它来自/dev/null
。 logcat
to write to the current standard output. 您希望单独保留标准输出 - 您希望logcat
写入当前标准输出。 At some point in the proceedings, you do your daemonization properly (borrowing the link from @bstpierre's answer), making sure that the terminal you are connected to is not your controlling terminal, so that interrupts and hangups sent to the terminal don't affect your daemon. 在程序中的某个时刻,你正确地进行守护 (从@bstpierre的答案借用链接),确保你所连接的终端不是你的控制终端,这样发送到终端的中断和挂断不会影响你的守护进程。 The plumbing is simpler than what you have set up - you should deal with standard input and leave standard output and standard error unchanged (instead of changing the outputs and leaving the input unchanged). 管道比您设置的更简单 - 您应该处理标准输入并保持标准输出和标准错误不变(而不是更改输出并保持输入不变)。
Now, you might want the output to go to /dev/console
; 现在,您可能希望输出转到/dev/console
; if so, then it is reasonable to revise the code to open /dev/console
. 如果是这样,那么修改代码以打开/dev/console
是合理的。 However, it is not reasonable to fall back on /dev/null
if you can't open /dev/console
; 但是,如果无法打开/dev/console
,则退回/dev/null
是不合理的; your program should report an error and fail (because there is no point in having logcat writing to /dev/null
!). 你的程序应该报告错误并失败(因为将logcat写入/dev/null
没有意义!)。 Make sure you open the console with the O_NOCTTY
flag so it does not become the controlling terminal for the daemon. 确保使用O_NOCTTY
标志打开控制台,这样它就不会成为守护程序的控制终端。
The final comment I'd make is: 我最后的评论是:
I don't much like it when that happens. 当发生这种情况时,我不太喜欢它。
There is special purposed function for this in glibc: 在glibc中有这个特殊功能:
#include <unistd.h>
...
/* We are in the parent, yet */
daemon(0,0);
/* Now we are in the child */
...
More details here http://linux.die.net/man/3/daemon 更多详情请访问http://linux.die.net/man/3/daemon
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.