什么原因会导致Perl系统调用开始失败?

12

一个小请求:我每天都读取 Stack Overflow 上的 Perl 问题,并在我能回答/贡献的时候进行回答;今天我需要社区的帮助!

Perl设置:我在Windows上运行Active Perl 5.8.8。安装在我们部门服务器的本地驱动器上,该驱动器也共享给网络。所有部门用户通过指向这个网络安装的Perl在自己的PC上运行Perl。这已经运作多年,没有引起任何问题,但需要了解这个信息才能理解问题。

所涉及的服务器也是我们的“cron”(定时任务)服务器,处理各种自动化任务。突然上周,在Perl脚本(在服务器端)中的系统调用开始失败(详细信息如下)。一开始,我怀疑是损坏的Perl安装,但所有客户机仍然可以运行相同的Perl脚本而没有任何问题,这让我认为这是一个服务器问题。我已经两次重新启动了服务器,问题仍然存在,因此我需要帮助!

下面是一些示例,演示了各种系统调用失败的方式,将其简化为Perl单行命令:

% perl -e "system('dir')"

应该会打印出"dir"的列表,但实际上它会打开一个子shell。如果我输入"exit",我就可以退出子shell,回到原来的shell(通过使用向上箭头键检查shell历史记录进行确认)。

% perl -e "print `dir`"

这段代码实际上会卡住,什么都不会发生。如果按Ctrl-C来结束程序,你会看到"Terminating on signal SIGINT(2)"的信息并且回到了DOS提示符界面。但是,未来在DOS提示符下输入任何命令(即使只是按下回车键),都会出现错误"The process tried to write to a nonexistent pipe."。因此,你必须退出DOS提示符界面,因为它已经没用了。

最后一个例子:

% perl -e "system('Z:/Scripts/rebuild.pl')"

“ebuild.pl”未被识别为内部或外部命令,可执行程序或批处理文件。

在这种情况下,Perl将正斜杠(/)转换为DOS / Windows反斜杠(\),多年来一直做得很好。但是,Perl将“rebuild.pl”文件名开头的“\r”解释为回车符(我想),并寻找剩余的“ebuild.pl”。对其他脚本名称的调用,其字符无法被误解为这样的结果会导致上述挂起(如果使用反引号,则会打开子shell供system()调用使用)。

我不仅感到困惑 - 我也很绝望! 我们部门服务器的“cron”作业现在毫无用处,因为我们使用了很多系统调用。

再次说明,我不认为这是损坏的Perl安装,因为网络用户可以正常运行。那么,可能会发生什么事情导致Perl的系统调用像这样失败(与Perl安装本身无关的单个计算机)?

环境设置,如所要求:

ALLUSERSPROFILE=C:\Documents and Settings\All Users
APPDATA=C:\Documents and Settings\engmodem\Application Data
CDSROOT=Z:\Cadence\SPB_16.5
CDS_CONCEPT_NOSPLASH=TRUE
CDS_LIC_ONLY=1
CDS_SITE=Z:\Cadence\Sites\16.5
CHDL_LIB_INST_DIR=%CDSROOT%
CLIENTNAME=USENTUTTLJL3C
ClusterLog=C:\WINDOWS\Cluster\cluster.log
CommonProgramFiles=C:\Program Files\Common Files
COMPUTERNAME=CORPUSAPP5
ComSpec=C:\WINDOWS\system32\cmd.exe
CONCEPT_INST_DIR=%CDSROOT%
FP_NO_HOST_CHECK=NO
HOMEDRIVE=H:
HOMEPATH=\
HOMESHARE=\\PF1\HOME
ICMHOME=Z:\Software\PTC\INTERC~1
INSTDIR=%CDSROOT%
LOGONSERVER=\\ENGMAHO5
LSF_BINDIR=Z:\Software\LSF\bin
LSF_ENVDIR=\\hwc151\LSF_6.2\etc
MESSAGE=BROADCAST
NUMBER_OF_PROCESSORS=2
OA_PLUGIN_PATH=%CDSROOT%\Share\oaPlugIns
OS=Windows_NT
Path=C:\Program Files\Legato\nsr\bin;Z:\oracle\ora92\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program Files\Windows Resource Kits\Tools\;Z:\Software\Perl\5.8.8\bin;C:\Program Files\Oracle\jre\1.3.1\bin;C:\Program Files\Oracle\jre\1.1.8\bin;C:\Program Files\Support Tools\;Z:\Software\LSF\bin;C:\Program Files\PHP\;C:\Program Files\Microsoft SQL Server\90\Tools\binn\;C:\Program Files\EMC RepliStor;C:\GitStack\python;C:\GitStack\python\Scripts;C:\GitStack\git\cmd;Z:\Scripts;Z:\bin;Z:\Cadence\SPB_16.5\tools\bin;Z:\Cadence\SPB_16.5\tools\fet\bin;Z:\Cadence\SPB_16.5\tools\pcb\bin;Z:\Cadence\SPB_16.5\OpenAccess\bin\win32\opt
PATHEXT=.COM;.EXE;.BAT;.PL;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.VBS
PCB_LIBRARY=16
PERL5SHELL=cmd
PHPRC=C:\Program Files\PHP\
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_IDENTIFIER=x86 Family 6 Model 29 Stepping 1, GenuineIntel
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=1d01
ProgramFiles=C:\Program Files
PROMPT=$P$G
PULLUP_DIFF_PAIRS=TRUE
SESSIONNAME=RDP-Tcp#1
SystemDrive=C:
SystemRoot=C:\WINDOWS
TZ=EST5EDT
VISUALSVN_SERVER=C:\Program Files\VisualSVN Server\
WF_RESOURCES=Z:\oracle\ora92\WF\RES\WFus.RES
windir=C:\WINDOWS

2
也许这个问题更适合在ServerFault或SuperUser上提问? - TLP
2
有人在服务器上安装了Cygwin吗?请发布环境的副本(您可以清除敏感变量值,但请确保所有变量的名称都在那里)。COMSPEC中有什么? - Sinan Ünür
5
当您删除PERL5SHELL环境变量时会发生什么?它不应该像PERL5SHELL = cmd / x / c或类似的内容吗? - raina77ow
3
“在这种情况下,Perl会将正斜杠(/)转换为DOS/Windows反斜杠(\),多年来一直做得很好。”这句话是错误的,Perl从未将任何“/”转换为“\”。 - ikegami
3
Windows内部可以很好地处理正斜杠;Perl实际上并未转换任何内容。 - Jim Davis
显示剩余9条评论
1个回答

10

原来这种奇怪的行为是由于错误定义了PERL5SHELL变量所致:cmd.exe(Windows中的shell解释器)应该使用一些参数进行正确处理,但在某些更新后这些参数消失了。

顺便提一下,在文档中指出,如果根本没有定义PERL5SHELL环境变量,Perl通常会将'cmd.exe /x /c'作为一个shell可执行文件。

P.S. 我真的很喜欢这个线程:它清楚地展示了注释的目的。)


再次感谢您的帮助!我只定义了那个变量,因为一个新的Perl脚本(foswiki)抱怨它没有被定义。我希望我知道它会引起这么多麻烦... - jimtut
1
+1 很高兴最终发现问题与定义了一个shell的环境变量有关。 - Sinan Ünür
谢谢,顺便说一下,你也应该受到赞扬:你首先提到了环境可能是问题的根源。 - raina77ow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接