【问题标题】:Why do I get 'Bad file descriptor' when trying sys.stdin.read() in subversion pre-revprop-change py script?为什么在 subversion pre-revprop-change py 脚本中尝试 sys.stdin.read() 时会得到“错误的文件描述符”?
【发布时间】:2012-09-24 09:01:49
【问题描述】:

我正在 Windows 机器上尝试 pre-revprop-change 挂钩脚本,但发现一个棘手的问题。

我将我的问题提炼为以下场景:

我有 C:\csvn\data\repositories\tr1\hooks\pre-revprop-change.bat 内容:

D:\svntest\testhook.py %*
exit %ERRORLEVEL%

testhook.py 是:

import os, sys

if __name__ == '__main__':
    # sys.stderr.write(sys.version+'\n') # this is OK, tried.
    newtext = sys.stdin.read() # try to read new log message

    sys.stderr.write('newtext is: %s\n'%newtext)

    exit(2)

但是,在做客户端 svn propset svn:log --revprop -r 2 "newtext" 时,我得到了 python 错误:

Traceback (most recent call last):
  File "D:\svntest\testhook.py", line 5, in <module>
    newtext = sys.stdin.read() # try to read new log message
IOError: [Errno 9] Bad file descriptor

这个错误的原因是什么?

似乎 pre-revprop-change.bat 没有将 STDIN 句柄传递给 py 脚本。是的,我验证了 pre-revprop-change.bat 可以从 STDIN 获取文本(根据 Read stdin stream in a batch file 中的说明)。

我也试过直接从命令行运行 pre-revprop-change.batsys.stdin.read() 就可以了。

请帮帮我。

截图如下:

环境:

  • Windows Server 2003
  • Collabnet Subversion Edge 2.3(svn 1.7.3 和 Apache 2.2.22)
  • 从 python.org 安装 Python 2.7.1 msi

==============[最新更新]=====================

不好意思说:我应该写在.bat里

exit %ERRORLEVEL%

而不是

exit /b %ERRORLEVEL%

对于和我一起尝试过的人,请修复它并重试。 /b 似乎有 pre-revprop-change.bat 总是以 0 退出。提示:没有/b,直接从 cmd 窗口运行 .bat 会导致 cmd 窗口关闭,所以我们最好尝试一下与cmd /c "pre-revprop-change.bat some param"

在下面重现此问题的快速方法

还有,还有兴趣的小伙伴们,请

然后我的问题将被重现。 (要求:svn.exe 1.7 命令行(collabnet 或 TortoiseSVN),并安装 Python 2.7)

如果您仍然无法重现错误。我已经准备了一个 VMware 虚拟机来准确地展示这个问题。在 http://down.nlscan.com/misc/chj/winxp-svnhook-py-stdin-error.7z 下载 VM(链接预计在 2013 年 9 月之前有效)。 VMware Player 3.0(免费)足以运行该虚拟机。

==============[解决方法]==================

@nmenezes 提供的非常好的解决方法,在 bat 中带有 c:\Python27\python.exe D:\svntest\testhook.py %*

【问题讨论】:

  • 为什么不直接使用.py文件呢?
  • 我相信我可以在 Linux 上做到这一点。但是在 Windows 上,svn 拒绝直接调用 pre-revprop-change.py。

标签: python svn svn-hooks


【解决方案1】:

SVN 在没有关联控制台的情况下执行脚本。 所以你不会在 STDOUT 上看到任何显示。 如果脚本返回不同于 0 的错误代码,则发送到 STDERR 的所有内容都会在 SVN 上显示为消息。

这种脚本应该在无人看管的情况下运行,它独立于用户的输入或输出。

您可以尝试将属性值作为额外的命令行参数传递。 为此,请将您的 .bat 更改为:

@echo off
set /p NEWTEXT=
test.py %* %NEWTEXT%
exit /b %ERRORLEVEL%

而 .py 为:

import os, sys

if __name__ == '__main__':   
    newtext = sys.argv[6]
    sys.stderr.write('newtext is: %s\n'% newtext)
    exit(2)

我将批处理 STDIN 读取到 NEWTEXT 变量,并将其作为额外的命令行参数传递给您的脚本。

此解决方案不适用于多行值。因此,我再次尝试了您的原始解决方案,并且效果很好。

svn propset svn:log --revprop -r 3 -F svn.txt

在这种情况下,属性值是从 svn.txt 文件中读取的,这是一个多行的文本文件。在这种情况下,带有 set /p 的选项不起作用,正如我们在 cmets 中讨论的那样。但原始脚本有效。

有关信息,在命令行中传递了 5 个属性:

1 - 存储库

2 - 修订号

3 - 用户

4 - 属性名称

5 - 操作(在本例中为 M)

属性值在批处理脚本的标准输入上传递。

@Chen,我终于下载了图片。将钩子批处理更改为:

c:\python27\python.exe d:\svntest\testhook.py %*
exit %ERRORLEVEL%

看来你的XP机器直接执行python的方式配置错误。

【讨论】:

  • 是的。 TESTVAR 将包含来自 STDIN 的内容。但问题是:一旦 pre-revprop-change.bat 启动某个进程,该进程就会丢失 STDIN。
  • 您是否在 pre-revprop-change.bat 中运行了这些行?
  • 是的,正好在 pre-revprop-change.bat 中。
  • 很遗憾,set /p 技能效果不佳。正如这篇文章stackoverflow.com/a/6980605/151453 中所述,并确认我自己,set /p 只读取一行(并且可能不能多次调用以读取所有行)。但是你知道,svn log 消息可能包含可能的行。无论如何,感谢您的参与。
  • 嗨陈,我在我的 Windows 机器上进行了测试......我没有遇到使用 Python 脚本读取标准输入的问题,就像你在第一篇文章中所做的那样。我开始认为我们在这里遗漏了一些东西。我明天再做一次测试。
【解决方案2】:

难道不是由你的批处理文件将它接收到的标准输入引导到它调用的脚本中吗?

供参考:http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true

也许你可以在你的脚本调用前加上 > 符号来实现这一点?

> D:\svntest\testhook.py %*
exit /b %ERRORLEVEL%

看起来如果批处理文件可以从标准输入读取,那么 SVN 正在做它应该做的事情,这取决于您的批处理文件是否可以将其提供给您调用的附加脚本。

【讨论】:

  • 我想我明白了你的想法。对于解决方法,我可以告诉 .bat 将 STDIN 内容写入 tmpfile,然后在我的 py 脚本中读取该 tmpfile。但是,令人困惑的是:如果 .bat 直接从 CMD 行运行,为什么 py 脚本可以继承 STDIN,但如果从 svn hook 过程调用它就不能。
  • 对不起,我不知道您所说的“在对脚本的调用前加上 > 符号”是什么意思...
  • 我修复了格式,抱歉之前没有注意到。这能回答我的意思吗?
  • 不,在 pre-revprop-change.bat 中写入 &gt; D:\svntest\testhook.py %* 会清除我的 testhook.py(即 testhook.py 变为 0 字节)。
  • 对此感到抱歉,呵呵!当然,这就是这样做的。我想知道管道( | )是否可行?您也许可以使用 findstr 命令读取标准输入,然后将输出通过管道传输到您的脚本中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-26
  • 2012-03-12
  • 1970-01-01
  • 2010-10-05
  • 2014-09-18
  • 2019-02-26
  • 1970-01-01
相关资源
最近更新 更多