bash 是否承诺在简单情况下将 -c 优化为普通 exec?

问题描述 投票:0回答:2

考虑以下 bash 调用

bash -c 'sleep 99'

假设我运行它,在等待它完成睡眠时,我在另一个终端中运行

ps
。 在这种情况下,我确实发现
sleep 99
正在运行。 但它的父进程不是正在运行的进程
bash -c
。 相反,它的父进程是 INVOKED
bash -c
的进程。 我只能想到一个解释:bash 注意到,由于它被要求运行一个简单的命令,它执行了“优化”的
exec sleep 99
序列,而不是“明显”的
fork; exec sleep 99; wait; exit
序列。

我问这个问题的原因是我今天注意到在工作中我们有一些 Python 脚本非常依赖于这种行为。 (一开始并不明显;我们将

subprocess
shell=True
一起使用...直到现在我才意识到其中的含义。)我试图将它们移植到 Windows,当然
cmd.exe
没有这样做是因为
exec
传统上不是 Windows 上的东西。

然后我想知道......它实际上记录在 bash 执行此操作的任何地方吗? 如果事实证明 POSIX 强制这样做,我会感到非常惊讶。 我在 bash 用户手册中没有看到任何提及。 (虽然这是一本很大的手册。)知道在多大程度上可以保证这一点吗?

bash shell process sh pid
2个回答
4
投票

(我个人讨厌这个智能功能。)

如果您确实想要这种行为:

bash -c 'exec sleep 99'
  sh -c 'exec sleep 99'

如果您想避免这种行为:

bash -c 'sleep 99; exit'
  sh -c 'sleep 99; exit'

2
投票

我们有一些 Python 脚本 [...] 使用

subprocess
shell=True

请注意,在 UNIX-y 系统(例如 Linux 或 Mac)上,它本身不会启动 Bash。 相反,它将启动/bin/sh。 这可能是也可能不是 Bash(即使在 Linux 上),如果它

Bash,那么 Bash 在以该名称启动时以 POSIX 模式运行。

实际上是否有 bash 执行此操作的任何地方记录? [...] 我在 bash 用户手册中没有看到任何提及。

我相信我对
手册

的研究足以支持我的断言:不,此类行为没有记录在案。 手册页中也没有它。 我非常希望在源代码中提及,但这将是面向开发人员的,而不是面向用户的。

知道这能保证到什么程度吗?

没有关于此行为的用户文档,最好的答案可能是“根本没有”。 当然,Bash 是软件,所以如果您在一种情况下观察到这种行为,您应该能够在足够相似的情况下依赖相同的行为,但很难非常精确地描述“足够相似”。

对于 Python 脚本,如果您实际上依赖 Bash 直接

exec

指定的命令,那么您应该强烈考虑不指定

shell=True
。但请记住,确保没有插入 shell 并不是这样做的唯一效果。
shell=True
的常见原因实际上是您想在命令中使用 shell 功能,例如 I/O 重定向。
    

© www.soinside.com 2019 - 2024. All rights reserved.