我可以在启动程序时从命令行重定向其他文件描述符吗?
Can I redirect additional file descriptors from the command line while launching a program?
在c++中可以输出到cout
和cerr
,分别由文件描述符1
和2
处理。在c++程序之外,我可以将输出重定向到我想要的任何地方(在本例中,将其写入两个单独的文件):
$ my-program 1>output 2>errors;
我是否只能使用文件描述符1
和2
,或者我可以"创建我自己的"?比方说,我想要第三个输出保存调试信息,或者第四个输出给管理员发邮件?
$ my-program 1>output 2>errors 3>>/logs/my-program.log 4>&1 | scripts/email-admin.sh;
我可以在我的程序中写入文件描述符的3和4吗?
在包装器脚本中打开所有文件通常不是一个好的设计。当你想让你的程序更智能,能够关闭一个大的日志文件并启动一个新的,你需要在你的程序中的逻辑。
但是要回答实际的问题:
是,您可以让shell打开您喜欢的任何编号的文件描述符,用于输入、输出或两者。让父进程在execve(2)
之前打开它们与在子进程中使用代码打开它们所得到的结果相同(至少在POSIX系统上,stdin/out/err就像其他文件描述符一样,并不特殊)。文件描述符可以标记为close-on-exec或不标记为close-on-exec。使用open(2)
和O_CLOEXEC
,或者打开后使用fcntl(2)
设置FD_CLOEXEC
它们也不需要引用常规文件。它们中的任何一个都可以是tty、管道、块或字符设备文件、套接字甚至目录。(打开目录没有shell重定向语法,因为您只能在它们上使用readdir(3)
,而不能使用read(2)
或write(2)
。)
请参阅bash重定向教程。再举一个我自己的例子:
peter@tesla:~$ yes | sleep 60 4> >(cat) 5</etc/passwd 9>/dev/tcp/localhost/22 42<>/tmp/insecure_temp &
[1] 25644
peter@tesla:~$ ll /proc/$!/fd
total 0
lr-x------ 1 peter peter 64 Sep 9 21:31 0 -> pipe:[46370587]
lrwx------ 1 peter peter 64 Sep 9 21:31 1 -> /dev/pts/19
lrwx------ 1 peter peter 64 Sep 9 21:31 2 -> /dev/pts/19
l-wx------ 1 peter peter 64 Sep 9 21:31 4 -> pipe:[46372222]
lrwx------ 1 peter peter 64 Sep 9 21:31 42 -> /tmp/insecure_temp
lr-x------ 1 peter peter 64 Sep 9 21:31 5 -> /etc/passwd
l-wx------ 1 peter peter 64 Sep 9 21:31 63 -> pipe:[46372222]
lrwx------ 1 peter peter 64 Sep 9 21:31 9 -> socket:[46372228]
# note the rwx permissions: some are read-write, some are one-way
>(cmd)
进程替换语法扩展为像/dev/fd/63
这样的文件名。使用4> >(cmd)
将fd打开为fd 4。
将stderr重定向到管道需要对文件描述符进行一些调整,因为没有2| cmd
语法。2> >(cmd)
工作,但cmd
在后台运行:
peter@tesla:~$ (echo foo >&2 ) 2> >(wc) # next prompt printed before wc output
peter@tesla:~$ 1 1 4
peter@tesla:~$ ( echo foo >&2; ) 2>&1 | wc
1 1 4
处理将调试信息发送到其他地方的通常方法是选择一个直接写入文件的日志系统(而不是将其发送到另一个虚拟文件描述符,然后在bash中将该文件描述符重定向到file)。
一种选择是使用mkfifo,并让您的程序作为文件写入fifo,然后使用其他方法将fifo定向到其他位置。
邮件脚本的另一种选择是将邮件脚本作为c++程序中的子进程运行,并使用内部管道写入其标准输入。在Unix系统上,管道进入sendmail
是程序发送邮件的传统方式。
最好的办法是找到处理你想做的事情的库。
例子mkfifo
http://linux.die.net/man/3/mkfifo您使用mkfifo命令创建一个特殊的文件,然后您可以像往常一样将fopen
和fprint*
添加到它。您可以像传递其他文件名一样将文件名传递给程序。
bash部分看起来像这样:
mkfifo mailfifo
yourprogram mailfifo &
cat mailfifo | scripts/email-admin.s
管道到子进程
http://www.gnu.org/software/libc/manual/html_node/Pipe-to-a-Subprocess.html- 在其他文件中创建类时在 c++ 项目中不起作用
- 我应该将除 .cpp 以外的其他文件添加到 git 中吗?
- 如何在其他文件中使用函数
- C++ - 忽略并从其他文件获取数据
- CMake:在其他目录中找不到我的头文件
- 无法使用 CMake 从其他文件夹添加源文件
- 如何使用 C/C++ 和 system() 系统调用以外的其他方法在 Linux 中获取文件功能?
- 从文件中查找单词并替换到其他文件中
- 在命名空间中声明变量,在 main 中定义它,使其对所有其他文件可见
- 没有头文件如何使用c ++调用其他模块中的函数?
- 访问从 CPP 文件到其他头文件的静态变量
- 不能在其他文件中包含结构
- 无法打开包含文件'Graphics.hpp'没有这样的文件或目录,Visual Studio的其他包含不起作用
- 如何在 Linux 下使用 c++ 知道文件是否被其他进程使用?
- 使用函数打开文件,然后让其他函数利用该文件?
- 如何使用Winforms C#或C++.Net在不更改文件中其他内容的情况下修改jpg文件中的Orientation e
- 如何调试visual studio 2017生成的C++代码.android中的SO文件和其他第三方库
- 如何使用QXmlStreamReader解析包含对其他XML文件的引用的XML文件
- 如何在不受其他文件影响的情况下"by itself" Visual Studio 项目中运行C++文件?
- 如何将 cpp 文件中的静态函数公开给其他文件