什么时候应该使用system3运行外部进程?

问题描述

C提供了标准功能system,以使用 shell 运行子进程,许多语言也提供了类似的功能,例如AWKPerl(带有单个参数)和PHP。有时,这些功能criticized不适合在security grounds上使用,或者由于外壳不是可移植的或is not the one used interactively而无法使用。

其他一些语言似乎也同意:它们仅提供一种无需外壳即可运行进程的方式,例如Java标记任何单个字符串参数本身)和Tcl。 Python提供了direct wrappersophisticated replacement,它们可以避免使用外壳,并明确推荐(如does the user community)。

当然,对于许多应用程序来说,shell都是不必要的复杂性。运行外部进程会带来deadlockorphan processes退出状态不明确和file descriptor sharing的问题,在运行mkdir或{{1}的情况下是不必要的}。但是,假设存在echo $VAR是有原因的,那么何时使用它是正确的工具?

解决方法

对于C和Python(即使使用了适当的用例,也适合运行一个外部进程,尤其是通过外壳运行一个用例(不能像popen那样过滤输出)。 实际 C system(3)),还有其他警告。 POSIX specifies对于system的其他行为:它忽略 SIGINTSIGQUIT,并在执行期间阻塞SIGCHLD。理由是,用户(可以从终端发送SIGINTSIGQUIT的用户在执行过程中是interacting with the subprocess,而不是父母,并且system必须处理SIGCHLD的子进程,而不受应用程序的干扰。

这直接暗示了问题的答案:仅在以下情况下才使用system

  1. 用户直接要求执行特定的Shell命令(例如!中带有less),并且
  2. 应用程序无需对此这段时间内退出的任何 other 子进程做出反应(例如,它不应是多线程的)。

如果不满足#1的要求,则用户可能会发送一个终端信号,期望它杀死整个过程,并使它仅杀死(如果不是看不见的话,则是意外的)孩子。 Linux手册页特别警告using it in a loop,使用户无法中断。可能会注意到一个孩子已经退出并重新发出信号,但这是不可靠的,因为某些程序(例如,Python)exit收到某些信号而不是重新提出,以指示退出原因以及外壳(由system强制!)将退出状态与信号杀死状态进行合并

在Python中,错误处理问题由于以下事实而更加复杂:os.system遵循C退出状态(读取:错误代码)约定,而不是将失败报告为异常用户忽略孩子的退出状态。

,

答案很简单(从理论上讲),因为它与适用于许多其他编程问题的答案相同:当使程序员的工作更轻松并且用户的生活不再困难时,最好使用system()

但是,要想做到这一点,则需要做出大量判断,而且我们可能不会总是正确无误。但是,同样,编程中的许多判断调用都是如此。

由于大多数shell是用C编写的,因此没有原理 为什么没有system()完成的任何事情就无法完成。但是,有时需要一堆完整的代码才能通过调用shell来完成一行代码。我猜popen()也有同样的问题。

使用system()引起了可移植性,线程安全性和信号管理问题。

不幸的是,我的经验是system()给(程序员)带来最大好处的情况恰恰是它的可移植性最差的情况。

有时这样的担忧会建议使用不同的方法,有时它们并不重要-取决于应用程序。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...