概要。为什么FastScripts application执行以下操作,是否有目的,我或FastScripts开发人员能否以某种方式修复/更改行为而不执行此操作? (我发现FastScripts是一个很棒的应用程序。我正在运行MacOS 10.9.5。)
详情。
FastScripts 2.6.8似乎将其运行的当前脚本的内容复制到stdin
,用于在所述脚本中运行的任何子进程,如下面的命令行会话所示。这不仅非常奇怪,在开发由FastScripts指令触发的软件时会引起很大的混淆。
我没有用非Python脚本测试过类似的行为,但是我写的多个独立的Python程序都表现得一样。我将通过电子邮件将这个问题的链接发送给FastScripts开发人员/技术支持。
以下演示了正确运行的脚本:
$ cat test_subprocess_stdin.py
#!/usr/bin/env python
import subprocess
cmd1 = '/tmp/reprint_stdin.py >/tmp/cmd1out.txt'
cmd2 = '/tmp/reprint_stdin.py </dev/null >/tmp/cmd2out.txt'
subprocess.Popen(cmd1, shell=True)
subprocess.Popen(cmd2, shell=True)
$ cat /tmp/reprint_stdin.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
# from http://stackoverflow.com/a/17735803/605356
stdin_content_present = not sys.stdin.isatty()
if stdin_content_present:
for line in sys.stdin:
sys.stdout.write('stdin: ' + line)
$ ./test_subprocess_stdin.py
$ cat /tmp/cmd1out.txt
$ cat /tmp/cmd2out.txt
$
然而,从FastScripts运行上述脚本时会发生奇怪的事情:
$ # <now running test_subprocess_stdin.py from FastScripts keyboard shortcut>
$
$ cat /tmp/cmd1out.txt
stdin: #!/usr/bin/env python
stdin: import subprocess
stdin: cmd1 = '/tmp/reprint_stdin.py >/tmp/cmd1out.txt'
stdin: cmd2 = '/tmp/reprint_stdin.py </dev/null >/tmp/cmd2out.txt'
stdin: subprocess.Popen(cmd1, shell=True)
stdin: subprocess.Popen(cmd2, shell=True)
$ cat /tmp/cmd2out.txt
$
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.9.5
BuildVersion: 13F1077
$
请注意,调用os.system()
代替subprocess.Popen()
会导致相同的异常行为。
出于某种原因,FastScripts和FastScripts似乎将正在运行的脚本的内容(在上面的例子中为test_subprocess_stdin.py
)指向任何(子)脚本的stdin。在顶级脚本/程序中调用。 (</dev/null
指示被调用的下标忽略stdin。)这很奇怪,因此,我需要花费大量的开发和调试时间来发现为什么我的FastScript调用程序正在破坏。
答案 0 :(得分:1)
感谢您提出这个有趣的问题。我已经下载并确认了您看到的相同行为,并且我正在尝试理解它。
FastScripts运行shell脚本的方式是从#解释! (shebang)在脚本行中运行工具的名称,然后简单地运行该工具,提供脚本文件的内容作为正在运行的工具的标准输入。例如,在您的示例中,它将运行:
/ usr / bin / env python
以文件内容作为标准输入。
据我所知,这是一种非常传统的方法来调用shell工具来运行任意基于脚本的命令。那么为什么FastScripts的行为与例如从命令行运行该工具?我不知道。
显然有充分证据表明,子进程确实继承了他们的父进程,例如: stdin(https://unix.stackexchange.com/questions/58252/what-sets-a-childs-stderr-stdout-and-stdin),所以当env运行python并且python运行子进程调用时,标准输入应该保持活动状态并不神秘。
我想到的问题是,在直接从命令行运行脚本的情况下会发生什么?我不知道shell脚本执行的标准实现是否做了一些特殊的事情来防止将stdin传播到脚本本身。我不得不考虑这个。