如果我不知道哪个shell ( stderr,csh,dash)正在解释我的命令,我如何将stdout(或stdout+stderr)重定向到一个文件?
我在Linux/FreeBSD/OSX上运行的C代码需要通过system()函数调用一个外部程序,它将使用/bin/sh来解释所提供的命令行。我想捕获由该外部程序打印到stderr的消息,并将它们保存到文件中。问题是,在不同的系统上,/bin/sh指向不同的shell,这些shell具有不同的语法将stderr流重定向到文件。
我发现的最接近的一点是bash实际上理解将csh+stdout重定向到文件的stderr-style语法:
some_program >& output.txt但是dash并不理解这个语法,它是Ubuntu上的默认shell (即非常常见)。
是否有一种stderr重定向语法可以被所有常见的shell正确解释?或者,是否有方法告诉system() (或其他类似的C函数?)使用/usr/bin/env bash而不是/bin/sh来解释所提供的命令行?
发布于 2019-07-09 19:52:11
发布于 2019-07-09 20:04:53
您有一个错误的假设,即/bin/sh可以是一个与标准shell语法不兼容的“备用”shell,比如csh。如果您有这样的系统设置,它就会被破坏,没有shell脚本能够工作。几乎所有现代系统都试图(至少在表面上)符合POSIX标准,其中sh命令处理POSIX中指定的shell命令语言,这大致相当于历史上的Bourne,以及bash、dash、ash等(通常作为/bin/sh安装的Shell )都与其兼容99.9%。
您可以完全忽略csh和类似的。它们从未作为sh安装,只有真正想要使用它们的人,或者那些被困在使用它们作为交互shell的人,因为一些邪恶的sysadmin设置了登录外壳的默认方式,因此必须关心它们。
发布于 2019-07-09 19:53:12
如果我不知道哪个shell (bash、csh、dash)正在解释我的命令,如何将stderr (或stdout+stderr)重定向到一个文件?
伯恩家族shell和csh家族shell有不同的、不兼容的语法来重定向stderr。事实上,csh和tcsh根本没有语法来重定向stderr --它们只能与stdout一起重定向。
如果你真的可以在任何一个外壳,那么你几乎是水龙头在做任何事情。人们可以想象一个晦涩的、深奥的、语法完全不兼容的shell。因此,即使标准shell的不寻常配置也会让您感到意外--例如,如果IFS变量被设置为Bourne家族shell中的异常值,那么执行任何没有考虑到这一点的命令都会遇到困难。
如果您可以指望至少执行简单的命令,那么您可以在未知的shell中执行一个已知的shell来处理您的命令,但是对于您感兴趣的情况来说,这不应该是必需的。
或者,是否有方法告诉system() (或其他类似的C函数?)使用/usr/bin/env而不是/bin/sh解释所提供的命令行?
不适用于符合POSIX标准的系统。POSIX显式指定system()函数使用/bin/sh -c [the_command]执行命令。但是这不应该让人担心,因为/bin/sh应该是一个符合POSIX的外壳,或者至少非常接近一个shell。当然,它应该是伯恩家族的外壳,bash和dash都是,但tcsh绝对不是。
在POSIX中重定向标准错误流的方法是使用2>重定向操作符(这是适用于任何文件描述符的更为通用的重定向特性的特例)。无论shell /bin/sh实际上是什么,都应该认识到这个语法,特别是bash和dash都是这样做的:
some_program 2> output.txthttps://stackoverflow.com/questions/56959503
复制相似问题