如何将stdin、stdout、stderr重定向到/dev/null

Q: 我使用了如下代码将stdin、stdout、stderr重定向到/dev/null

freopen( "/dev/null", "w", stdout );
   freopen( "/dev/null", "w", stderr );
   freopen( "/dev/null", "r", stdin );

这样做正确吗,是否使用"w+"或者"a"更正确一些。在很多代码中是这样完成重定
   向的:

close( 0 );
   close( 1 );
   close( 2 );
   open( "/dev/null", O_RDWR );
   dup( 0 );
   dup( 0 );

这两种方式中哪一种更好、更具可移植性。

A: Andrew Gierth <andrew@erlenstar.demon.co.uk>

第一种方式不是总能达到目的。freopen()并不确保新的文件流描述符一定重用底层
原有文件句柄。假如未能重用,向stderr流输出的标准I/O函数最终输出到/dev/null,
但那些向STDERR_FILENO句柄输出的标准I/O函数就没这么幸运了,可能输出到一些不
可预期的文件中去。换句话说,2号句柄此时不再是标准错误输出了。比如:

write( 2, ... )

这样的调用存在安全问题。第二种方式可以避免上述问题,然而存在竞争环境问题。

现在看下述代码:

--------------------------------------------------------------------------
    int fd = open( "/dev/null", O_RDWR );
    /*
     * handle failure of open() somehow
     */
    dup2( fd, 0 );
    dup2( fd, 1 );
    dup2( fd, 2 );
    if ( fd > 2 )
    {
        close( fd );
    }
--------------------------------------------------------------------------

与第二种方式相比,这种代码是线程安全的。

有人认为对于后台守护进程做此类重定向操作浪费资源,建议直接关闭0、1、2号句
柄拉倒,这是非常不正确的。假设它们确实被关闭了,则一些普通数据文件句柄将等
于0、1、2。以2号句柄为例,某些库函数失败后会向2号句柄输出错误信息,这将破
坏原有数据。

D: 小四 <scz@nsfocus.com> 2002-04-25 16:47

2号句柄的此类安全问题在2002年4月23日得到了实际印证,可参看<<x86/FreeBSD 
4.5-RELEASE IO Smash及S/Key机制分析>>。

1987年,Henry Spencer在setuid(7)手册页中做了如下建议,一切标准I/O句柄都可
能因关闭过而不再是真实的标准I/O句柄,在使用printf()一类的函数前,务必确认
这些句柄是期待中的标准I/O句柄。1991年,在comp news上有人重贴了这份文档。

内核补丁应该确保对于SUID、SGID进程而言,0、1、2号句柄不会被打开后指向一个
普通文件。这有很多实现方式,比如使它们全部指向/dev/null。这种限制不应该在
库函数一级实现,可能有些SUID、SGID程序直接使用系统调用。

stdin、stdout、stderr中某一个被关闭,都可能潜在存在问题。

1992年W. Richard Stevens在<<Advanced Programming in the UNIX Environment>>
中建议Daemon进程应该关闭所有不必要的文件句柄,并将stdin、stdout、stderr指
向/dev/null。

自1998年以来,OpenBSD内核中execve()里有一个检查,如果句柄0、1、2是关闭的,
就打开/dev/null,使之对应0、1、2号句柄。这样就可以安全地执行setuid程序了。
FreeBSD/NetBSD直至最近才再次暴露出类似问题,而Linux在glibc中做了一些检查。

但是,OpenBSD这个检查存在一个问题,当falloc()失败时,应该转向错误处理,而
不是简单地跳出循环。art在注释中指出了这点,却无人去修正它。

--------------------------------------------------------------------------
sys/kern/kern_exec.c

在一个循环中,内核试图打开/dev/null,使之对应0-2号句柄

(...)
    if ( ( error = falloc( p, &fp, &indx ) ) != 0 )
    {
        break;
    }
(...)
--------------------------------------------------------------------------

于是本地用户获得一个内核文件表项相关的竞争环境,可以获取root权限。

如何将stdin、stdout、stderr重定向到/dev/null相关推荐

  1. Linux Shell 文件描述符 及 stdin stdout stderr 重定向

    Abstract: 1) Linux Shell 命令的标准输入.标准输出.标准错误,及其重定位: 2)Linux Shell 操作自定义文件描述符: 文件描述符是与文件相关联的一些整数,他们保持与已 ...

  2. linux 输出重定向_Linux--文件描述符和stdin,stdout,stderr

    基本概念 1. 文件描述符 总览: 当一个程序成功向操作系统请求访问一个打开的文件, 内核会返回一个指向内核中全局文件表(global file table)中的入口点(entry)的文件描述符. 文 ...

  3. WorkerMan源码分析(resetStd方法,PHP中STDIN, STDOUT, STDERR的重定向)

    WorkerMan中work.php中 resetStd 方法中代码如下 public static function resetStd(){if (!static::$daemonize || st ...

  4. 利用stdin stdout stderr及POSIX-linux机制重定向写日志

    利用stdin stdout stderr及POSIX-linux机制重定向写日志 由open返回的文件描述符一定是该进程尚未使用的最小描述符.由于程序启动时自动打开文件描述符0.1.2,因此第一次调 ...

  5. C语言调试技巧:stdin,stdout,stderr

    stdin,stdout,stderr流 介绍 stdin,stdout,stderr是标准的输入输出流.其中,stdin是访问键盘输入,stdout和stderr分别是向终端输出数据. 关键函数 f ...

  6. stdout stderr 重定向到文件

    1. stdout/stderr 重定向 1. stdout/stderr 重定向 1.1. dup/dup2 重定向到已打开文件 或 新文件 1.2. freopen 重定向到新文件 1.3. 命令 ...

  7. STDOUT/STDERR重定向到ALOG中

    说下背景:现在众多Android开发者新添加的Google暂时并不会支持的功能,比如拨号上网,USB打印机等等,一般的实现方法就是静态编译Linux的相对开源库和程序(一般是C/C++语言),然后由A ...

  8. stdin, stdout, stderr

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.pandas是什么? 二.使用步骤 1.引入库 2.读入数据 总结 前言 在通常情况下,Linux/UNIX每个程 ...

  9. linux 读取终端stdout,【Linux基础】linux下的stdin,stdout和stderr理解

    在Linux下,当一个用户进程被创建的时候,系统会自动为该进程创建三个数据流,也就是题目中所提到的这三个. 1.三个数据流默认是表现在用户终端上的 执行一个shell命令行时通常会自动打开三个标准文件 ...

最新文章

  1. Bzoj3509 [CodeChef] COUNTARI
  2. 左神算法:未排序正数数组中累加和为给定值的最长子数组长度(Java版)
  3. wide Deep tensorflow实现
  4. Python环境下,提高pip安装库速度的方法!
  5. dwc_otg驱动 BUG: sleeping function called from invalid context at mm/page_alloc.c
  6. php垃圾回收算法分代,PHP的垃圾回收机制代码实例讲解
  7. 数据挖掘是如何解决问题的
  8. Excel数据转化为sql脚本
  9. 信号处理之freqz函数
  10. 第12课:JSP动作 Jsp include动作(JSP教程 JSP入门实战教程 黄菊华Java网站开发系列教程)
  11. 移动彩信MM7 API JAVA 样例
  12. Incorrect string value: '\xF0\x9F\x98\x82' for column '' at row 1
  13. 王逸凡的十万个为什么
  14. 最新php开发学习资料网盘下载
  15. 记录四川移动盒子打开adb命令的方法 型号:UNT402H
  16. 电子稳定程序系统--ESP
  17. 2023年如何实习QQ强制拉人入群,QQ批量拉群,QQ强制拉群软件开发定制的思路解析
  18. appinventor mysql_利用AppInventor实现登录功能(完整版).docx
  19. sqlserver 日期比较
  20. php与go按位异或的差异

热门文章

  1. 速修复!严重的F5 BIG-IP 漏洞 PoC 已发布
  2. 微软紧急修复 Windows codecs 库中的两个 RCE 漏洞
  3. 编程在线--- 网站(IT技术学习、面试、交流)上线了
  4. python操作日期和时间的方法
  5. 黑苹果 装SVN工具 cornerstone无法打开解决办法——网卡内建
  6. PHP文件操作【其一】文件路径
  7. Recreate failovered primary database using Flashback Database
  8. 单实例数据库迁移到rac环境(四)上
  9. Python中多线程thread与threading的实现方法
  10. Python实现代码行数统计工具