考虑以下 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 -c 'exec sleep 99'
sh -c 'exec sleep 99'
如果您想避免这种行为:
bash -c 'sleep 99; exit'
sh -c 'sleep 99; exit'
我们有一些 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 重定向。