首页 > 解决方案 > 迁移到新服务器后,Perl CGI 每日图片脚本未按预期运行

问题描述

我有一个 perl cgi 脚本,多年来一直在 FreeBSD 5.4 Apache 1.3 网络服务器上完美运行,没有遇到任何问题。这是一天脚本的图片,它从给定目录中随机选择一张图片以包含在服务器端包含的 shtml 页面上

<!--#exec cgi="/cgi-bin/pod/pod.cgi"-->

我最近迁移到 Google Cloud Platform 上的新服务器 - Debian 9 (Stretch)、Apache 2.4。剧本坏了。在设置服务器配置以正确执行 cgi perl 脚本并以 ASCII 格式重新上传脚本后,该脚本再次开始工作,但现在出现异常行为。不是整天显示一个图像(相同的图像),然后在午夜更改图像(所需的行为),现在每次在 Web 浏览器中重新加载页面时都会更改图像。

该脚本使用一个平面文件日志来跟踪源目录中的哪些图像已被使用,并且在目标目录中的所有图像都已使用(登录到 pod.log)之前不会重复显示任何图像。正常工作时,它将每天显示一个新图像(在午夜更改),无论页面是否重新加载,所有用户都将保持不变,直到下一个午夜。

已在脚本注释中指定的必要文件上设置了所有权限。该脚本已以 ASCII 格式上传到服务器(如果以二进制格式上传,则根本不起作用)。该脚本正在显示来自正确目录的图像。但是.....每次刷新页面时,都会加载新图像并将其记录到 pod.log 文件中。

我认为可能会影响脚本的一件事是它在哪里获取脚本的日期/时间函数的时间。当我从 debian 命令提示符输入“日期”命令时,服务器返回了我已将服务器配置为的正确时间 - America/Los_Angeles。但我注意到,当我的网络服务器上的文件被触摸或更改时,它会用 UTC 时间对它们进行时间戳记,即 8 小时后。考虑到 Apache 可能导致不同的时间戳,我尝试在 php.ini 中为 apache2 更改时区。这似乎没有改变任何东西(在 apache2ctl 重新启动之后),所以我想,也许我会将服务器时区更改为 UTC。如果你不能打败他们,就加入他们。对?好吧,所以 debian 命令行中的“日期”命令返回了 UTC 时间。另请注意:网络服务器上的文件仍带有 UTC 时区时间戳。一切看起来都很好!但后来我用这个小宝石检查了 perl/cgi 使用的时间,它以人类可读的格式返回日期和时间......

#!/usr/bin/perl
print "Content-type: text/html\n\n";
@months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
@weekDays = qw(Sun Mon Tue Wed Thu Fri Sat Sun);
($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime();
$year = 1900 + $yearOffset;
$theTime = "$hour:$minute:$second, $weekDays[$dayOfWeek] $months[$month] $dayOfMonth, $year";
print $theTime; 

...并且此脚本返回时区 America/Los_Angeles 的时间,而不是 UTC。现在我不知道这种差异是否是导致我的每日脚本中出现错误的原因。但我的猜测,以我非常有限的经验告诉我,这至少是可能的。但就我的技术能力而言,我已经对脚本进行了调试/故障排除。

我需要知道:

  1. 是什么导致脚本在每次重新加载时返回一张新图片并更新日志文件,而不是在 1 天内保持静态?
  2. 它是由脚本中的无意(胖手指)错误引起的吗?
  3. 它是由我的新服务器和/或其配置处理脚本的某种不同方式引起的吗?
  4. 它是由我在上一段中提到的时间戳/时区问题引起的吗?
  5. 或者这是我完全错过的东西的结果?

接下来,我将提供脚本的源代码和我的 apache 配置文件。EXAMPLE.COM 应替换为您的域名,无论它出现在哪里,并且文件的路径应根据您的位置进行调整。

#!/usr/bin/perl

##############################################################
#  POD (Picture of the Day) Version 1.30
##############################################################

package VAR;
use strict;

##############################################################
#  Installation
##############################################################

#  1. Edit path to Perl at top of script (pod.cgi) if it
#  differs on your server. Usual and default path it
#  [/usr/bin/perl]. However, on some servers it may be
#  /usr/local/bin/perl. If in doubt, then refer to a script on
#  your server that does work, or ask your web host. Edit
#  variables below. Ensure you edit (and save) the script using
#  an ASCII editor like Notepad.
#
#  2. Via FTP, create directory on server in CGI-BIN called
#  pod. No need to CHMOD - you can leave set to server
#  default directory permissions.
#
#  3. Via FTP, create subdirectory in 'pod' directory
#  called data and CHMOD 777 (drwxrwxrwx).
#
#  4. FTP upload the pod.cgi script to the 'pod'
#  directory in ASCII (text) and CHMOD 755 (rwxr-xr-x). You may
#  need to rename the scripts with the .pl extension if your
#  server uses the .pl extension for CGI-Perl scripts.
#
#  images/      755 (drwxr-xr-x)
#  cgi-bin/pod/
#   pod.cgi     755 (rwxr-xr-x)
#   data/       777 (drwxrwxrwx)
#

##############################################################
#  Operation
##############################################################
#
#  METHOD 1: SSI Method
#  ====================
#  Call the script via SSI (Server-Side Includes). The image
#  is embedded in the page. Insert the following SSI tag in
#  the desired page:
#
#  <!--#exec cgi="/cgi-bin/pod/pod.cgi"-->
#
#  In either case, ensure to replace the cgi-bin/pod/ portion
#  of the SSI tag with your path to the script.
#
#  If you get the [an error occurred while processing this
#  directive] error message or no image / message displays,
#  make sure (a) the path to Perl is correct, (b) the script
#  was uploaded in ASCII, (c) the script is chmod 755
#  (rwxr-xr-x) and (d) the path to the script in the SSI tag
#  is correct - if in doubt, then ask your web host. If still
#  problematic then try the following:
#
#  1. On most servers, the page with a SSI tag must be named
#  with the SHTML extension in order for the server to parse
#  and execute the SSI tag. Check the page source. If you
#  still see the SSI tag, then it was not parsed. Try
#  renaming the page with the SHTML extension. If the SSI tag
#  is still not parsed (and still visible), then SSI may not
#  be enabled on your server - ask your web host.
#
#  2. Try calling the script directly from the browser. If
#  you get a server 500 error, then check your server error
#  logs.
#
#  3. You can also try the following SSI tag:
#
#  <!--#include virtual="/cgi-bin/pod/pod.cgi"-->
#
#  METHOD 1: Non-SSI Method
#  ====================
#  You can also call the script directly from the browser:
#
#  http://www.yourdomain.com/cgi-bin/pod/pod.cgi
#
#  The image is NOT embedded, but is instead displayed in a
#  script generated HTML page.

##############################################################
#  Configuration
##############################################################

#  Full (absolute) server directory path of directory holding
#  image files for the POD script to draw from. Create this
#  directory in advance and upload images (in Binary) to this
#  directory. No need to chmod. NO trailing slash at end of
#  path.
$VAR::image_dir = "/var/www/EXAMPLE.COM/httpdocs/pod";

#  URL of directory holding image files for the POD script to
#  draw from. NO trailing slash at end of URL.
$VAR::image_url = "http://www.EXAMPLE.COM/pod";

#  Full (absolute) server directory path for script data files
#  (pod.log, pod.err). Create this directory in advance and
#  chmod (777 or drwxrwxrwx). NO trailing slash at end of path.
$VAR::data_dir  = "/var/www/EXAMPLE.COM/httpdocs/pod/data";

#  Output template - how POD image (or error message) is
#  displayed. Feel free to change the HTML but (1) the MS link
#  back MUST be retained and (2) the <%image%> tag MUST be
#  retained as the tag is replaced with the image (or error
#  message) HTML code.
$VAR::template  = qq~
<center>
<table border="1">
        <th>
        <%image%>
        </th>
</table>
</center>
~;

##########################################################################
#  Do NOT change or alter the code below!
##########################################################################

eval {
    ($0 =~ m,(.*)/[^/]+,) && unshift (@INC, "$1");
    require 5.004;
};
if ($@) {
    print "Content-type: text/html\n\n";
    print "Server Error Message: $@\n";
    exit;
}

eval { &main; };
if ($@) { &error ("[Error 01]: $@"); }
exit;

###############################################
# Main
###############################################
sub main {

my ($time, $date) = &get_time_stamp();
my $num;

if (-e "$VAR::data_dir/pod.log") {
    open (LOG, "$VAR::data_dir/pod.log") ||
    &error ("Error [02]: Cannot open pod.log file - $!");
    my @entries = <LOG>;
    close (LOG);
    chomp (@entries);

    my @match = grep (/^$date/, @entries);
    if (@match) {
        foreach (@match) {
            split (/\|/);
            if ($_[0] eq $date) {
                $num = $_[1];
                last;
            }
        }
    }
}

opendir (DIR, "$VAR::image_dir") || &error ("Error [03]: Cannot open $VAR::image - $!");
my @files = sort (grep { m/.*\.gif|.jpg/ } readdir (DIR));
closedir (DIR);

if ($num eq "") { $num = int (rand @files); }
my $image = @files[$num];
if (! -e "$VAR::image_dir/$image") { &error ("Error [04]: Cannot find image file [$image]"); }

my $tag = "<img src=\"$VAR::image_url/$image\">";
$VAR::template =~ s/<%image%>/$tag/gis;
print $VAR::template;

my ($found, $newfile);
if (-e "$VAR::data_dir/pod.log") {
    open (LOG, "$VAR::data_dir/pod.log") ||
    &error ("Error [05]: Cannot open pod.log file - $!");
    my @entries = <LOG>;
    close (LOG);
    chomp (@entries);

    foreach (@entries) {
        split (/\|/);
        if ($_[0] eq $date) {
            $_[2]++;
            $newfile .= "$date|$_[1]|$_[2]|$_[3]\n";
            $found++;
        }       
        else { $newfile .= "$_\n"; }
    }
    if (! $found) { $newfile .= "$date|$num|1|$image\n"; }

    open (LOG, ">$VAR::data_dir/pod.log") ||
    &error ("Error [06]: Cannot open pod.log file - $!");
    flock (LOG, 2) || &error ("Error [07]: Cannot lock pod.log file - $!");
    print LOG $newfile;
    close (LOG);
}
else {
    open (LOG, ">$VAR::data_dir/pod.log") ||
    &error ("Error [08]: Cannot open pod.log file - $!");
    print LOG "$date|$num|1|$image\n";
    close (LOG);
    chmod (0666, "$VAR::data_dir/pod.log") ||
    &error ("Error [09]: Cannot chmod pod.log file - $!");
}
}

###############################################
# Get Time Stamp
###############################################
sub get_time_stamp {

my (@tb)    = localtime (time);
my ($ap)    = "am";

$tb[4]++;
for (0..4) { $tb[$_] = sprintf ("%02d", $tb[$_]); }
$tb[5] += 1900;
$ap = "pm" if ($tb[2] >= 12);
$tb[2] -= 12 if ($tb[2] > 12);

my $date = "$tb[4]/$tb[3]/$tb[5]";
return ("$tb[2]:$tb[1]:$tb[0]$ap $date", $date);
}

###############################################
# Error Handler
###############################################
sub error {

my $error       = shift;
my ($time, $date)   = &get_time_stamp();

my $tag         = "Cannot display image";
$VAR::template      =~ s/<%image%>/$tag/gis;

print $VAR::template;

open (ERR, ">>$VAR::data_dir/pod.err");
print ERR "$time | $ENV{'REMOTE_ADDR'} | $error\n";
close (ERR);
chmod (0666, "$VAR::data_dir/pod.err");
exit;
}
########################################
#end of Picture of the Day script
########################################

这是我的 apache2.conf (同样,无论我的域名出现在哪里,我都将我的域名更改为EXAMPLE.COM......

# configuration directives that give the server its instructions.
# See http://httpd.apache.org/docs/2.4/ for detailed information about
# the directives and /usr/share/doc/apache2/README.Debian about Debian specific
# hints.
#
#
# Summary of how the Apache 2 configuration works in Debian:
# The Apache 2 web server configuration in Debian is quite different to
# upstream's suggested way to configure the web server. This is because Debian's
# default Apache2 installation attempts to make adding and removing modules,
# virtual hosts, and extra configuration directives as flexible as possible, in
# order to make automating the changes and administering the server as easy as
# possible.

# It is split into several files forming the configuration hierarchy outlined
# below, all located in the /etc/apache2/ directory:
#
#       /etc/apache2/
#       |-- apache2.conf
#       |       `--  ports.conf
#       |-- mods-enabled
#       |       |-- *.load
#       |       `-- *.conf
#       |-- conf-enabled
#       |       `-- *.conf
#       `-- sites-enabled
#               `-- *.conf
#
#
# * apache2.conf is the main configuration file (this file). It puts the pieces
#   together by including all remaining configuration files when starting up the
#   web server.
#
# * ports.conf is always included from the main configuration file. It is
#   supposed to determine listening ports for incoming connections which can be
#   customized anytime.
#
# * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/
#   directories contain particular configuration snippets which manage modules,
#   global configuration fragments, or virtual host configurations,
#   respectively.
#
#   They are activated by symlinking available configuration files from their
#   respective *-available/ counterparts. These should be managed by using our
#   helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See
#   their respective man pages for detailed information.
#
# * The binary is called apache2. Due to the use of environment variables, in
#   the default configuration, apache2 needs to be started/stopped with
#   /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not
#   work with the default configuration.


# Global configuration
#

#
# ServerRoot: The top of the directory tree under which the server's
# configuration, error, and log files are kept.
#
# NOTE!  If you intend to place this on an NFS (or otherwise network)
# mounted filesystem then please read the Mutex documentation (available
# at <URL:http://httpd.apache.org/docs/2.4/mod/core.html#mutex>);
# you will save yourself a lot of trouble.
#
# Do NOT add a slash at the end of the directory path.
#
#ServerRoot "/etc/apache2"

# Set timezone for apache
  SetEnv TZ America/Los_Angeles

#
# The accept serialization lock file MUST BE STORED ON A LOCAL DISK.
#
Mutex file:${APACHE_LOCK_DIR} default

#
# The directory where shm and other runtime files will be stored.
#

DefaultRuntimeDir ${APACHE_RUN_DIR}

#
# PidFile: The file in which the server should record its process
# identification number when it starts.
# This needs to be set in /etc/apache2/envvars
#
PidFile ${APACHE_PID_FILE}

#
# Timeout: The number of seconds before receives and sends time out.
#
Timeout 300

#
# KeepAlive: Whether or not to allow persistent connections (more than
# one request per connection). Set to "Off" to deactivate.
#
KeepAlive On

#
# MaxKeepAliveRequests: The maximum number of requests to allow
# during a persistent connection. Set to 0 to allow an unlimited amount.
# We recommend you leave this number high, for maximum performance.
#
MaxKeepAliveRequests 500

#
# KeepAliveTimeout: Number of seconds to wait for the next request from the
# same client on the same connection.
#
KeepAliveTimeout 5


# These need to be set in /etc/apache2/envvars
User ${APACHE_RUN_USER}
Group ${APACHE_RUN_GROUP}

#
# HostnameLookups: Log the names of clients or just their IP addresses
# e.g., www.apache.org (on) or 204.62.129.132 (off).
# The default is off because it'd be overall better for the net if people
# had to knowingly turn this feature on, since enabling it means that
# each client request will result in AT LEAST one lookup request to the
# nameserver.
#
HostnameLookups Off

# ErrorLog: The location of the error log file.
# If you do not specify an ErrorLog directive within a <VirtualHost>
# container, error messages relating to that virtual host will be
# logged here.  If you *do* define an error logfile for a <VirtualHost>
# container, that host's errors will be logged there and not here.
#
ErrorLog ${APACHE_LOG_DIR}/error.log

#
# LogLevel: Control the severity of messages logged to the error_log.
# Available values: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the log level for particular modules, e.g.
# "LogLevel info ssl:warn"
#
LogLevel warn

# Include module configuration:
IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf

# Include list of ports to listen on
Include ports.conf


# Sets the default security model of the Apache2 HTTPD server. It does
# not allow access to the root filesystem outside of /usr/share and /var/www.
# The former is used by web applications packaged in Debian,
# the latter may be used for local directories served by the web server. If
# your system is serving content from a sub-directory in /srv you must allow
# access here, or in any related virtual host.
<Directory />
        Options FollowSymLinks
        AllowOverride None
        Require all denied
</Directory>

<Directory /usr/share>
        AllowOverride None
        Require all granted
</Directory>

<Directory /var/www/>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
</Directory>

#<Directory /srv/>
#       Options Indexes FollowSymLinks
#       AllowOverride None
#       Require all granted
#</Directory>
# AccessFileName: The name of the file to look for in each directory
# for additional configuration directives.  See also the AllowOverride
# directive.
#
AccessFileName .htaccess
#
# The following lines prevent .htaccess and .htpasswd files from being
# viewed by Web clients.
#
<FilesMatch "^\.ht">
        Require all denied
</FilesMatch>
#
# The following directives define some format nicknames for use with
# a CustomLog directive.
#
# These deviate from the Common Log Format definitions in that they use %O
# (the actual bytes sent including headers) instead of %b (the size of the
# requested file), because the latter makes it impossible to detect partial
# requests.
#
# Note that the use of %{X-Forwarded-For}i instead of %h is not recommended.
# Use mod_remoteip instead.
#
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %O" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
# Include of directories ignores editors' and dpkg's backup files,
# see README.Debian for details.
# Include generic snippets of statements
IncludeOptional conf-enabled/*.conf
# Include the virtual host configurations:
IncludeOptional sites-enabled/*.conf
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

这是我的虚拟主机的conf...

<VirtualHost *:80>
    ServerName EXAMPLE.com
    ServerAlias www.EXAMPLE.com
    UseCanonicalName Off
    ServerAlias  EXAMPLE1.com
    ServerAlias  www.EXAMPLE1.com
    ServerAlias  EXAMPLE2.com
    ServerAlias  www.EXAMPLE2.com
    ServerAlias  EXAMPLE.co.uk
    ServerAlias  www.EXAMPLE.co.uk
    ServerAlias  EXAMPLE.net
    ServerAlias  www.EXAMPLE.net
    ServerAlias  EXAMPLE3.com
    ServerAlias  www.EXAMPLE3.com
    ServerAdmin EXAMPLEd@gmail.com
    DocumentRoot /var/www/EXAMPLE.com/httpdocs
    <Directory /var/www/EXAMPLE.com/httpdocs>
        Options -Indexes +FollowSymLinks
        AllowOverride All
    </Directory>
    ScriptAlias "/cgi-bin/" "/var/www/EXAMPLE.com/cgi-bin/"
    #<Directory "/var/www/EXAMPLE.com/cgi-bin/">
    #    Options +ExecCGI
    #    AddHandler cgi-script .cgi
    #    AllowOverride All    
    #</Directory>
    #<Directory "/var/www/EXAMPLE.com/httpdocs/members/cgi-bin">
    #    Options +ExecCGI
    #    AddHandler cgi-script .cgi
    #    AllowOverride All
    #</Directory>
    #<Directory "/var/www/EXAMPLE.com/httpdocs/pod">
    #    Options +ExecCGI
    #    AddHandler cgi-script .cgi
    #    AllowOverride All
    #</Directory>

    Alias "/passwd/" "/var/www/EXAMPLE.com/passwd/"

    <IfModule mod_ssl.c>
        SSLEngine off
    </IfModule>

    <Directory /var/www/EXAMPLE.com>
        Options +ExecCGI +FollowSymLinks +Includes
        AddHandler cgi-script .cgi
        AllowOverride All
    </Directory>

    <Directory /var/www/EXAMPLE.com>
        <IfModule sapi_apache2.c>
                php_admin_flag engine on
                php_admin_flag safe_mode on
                php_admin_value open_basedir "/var/www/EXAMPLE.com/httpdocs:/tmp"
        </IfModule>
        <IfModule mod_php5.c>
                php_admin_flag engine on
                php_admin_flag safe_mode on
                php_admin_value open_basedir "/var/www/EXAMPLE.com/httpdocs:/tmp"
        </IfModule>
    </Directory>

    <Directory /var/www/EXAMPLE.com>
        RewriteEngine on

        # the following section prevents outside sites from hot-linking photos
        # leave this next line in allow empty referrers, remove to disallow empty referrers
        RewriteCond %{HTTP_REFERER} !^$ [NC]
        RewriteCond %{HTTP_REFERER} !^http://(.*@)?([a-z0-9-]+\.)*XX\.XXX\.XXX\.XXX(:[0-9]+)?(/.*)?$ [NC]
        RewriteCond %{HTTP_REFERER} !^http://(.*@)?([a-z0-9-]+\.)*EXAMPLE\.com(:[0-9]+)?(/.*)?$ [NC]
        RewriteCond %{HTTP_REFERER} !^http://(.*@)?([a-z0-9-]+\.)*EXAMPLE\.org(:[0-9]+)?(/.*)?$ [NC]
        RewriteCond %{HTTP_REFERER} !^http://(.*@)?([a-z0-9-]+\.)*EXAMPLE\.net(:[0-9]+)?(/.*)?$ [NC]
        RewriteCond %{HTTP_REFERER} !^http://(.*@)?([a-z0-9-]+\.)*EXAMPLE\.co.uk(:[0-9]+)?(/.*)?$ [NC]
        RewriteCond %{HTTP_REFERER} !^http://(.*@)?([a-z0-9-]+\.)*EXAMPLE\.de(:[0-9]+)?(/.*)?$ [NC]
        RewriteCond %{HTTP_REFERER} !^http://(.*@)?1\.2\.3\.4(:[0-9]+)?(/.*)?$
        RewriteRule .*\.(gif|jpeg|jpg)$ - [NC,F,L]
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/EXAMPLE.com-error.log
    CustomLog ${APACHE_LOG_DIR}/EXAMPLE.com-access.log combined
    # sends 404-not-found errors to error page
    ErrorDocument 404 /404-error-page.html

    # makes server side includes work on all html pages
    AddType text/html .shtml .html .htm
    AddHandler server-parsed .shtml .html .htm

    RewriteEngine On

    # If the hostname is NOT www.domain.com
    # RewriteCond %{HTTP_HOST} !^www\.EXAMPLE\.com$
    # 301 redirect to the same resource on www.EXAMPLE.com
    # RewriteRule (.*) http://www.EXAMPLE.com$1 [L,R=301]

    # sets the web surfer's browser to cache images, style sheets, and JavaScript for a week
    <IfModule mod_headers.c>
    # WEEK
    <FilesMatch "\.(jpg|jpeg|png|gif|swf|js|css)$">
        Header set Cache-Control "max-age=604800, public"
    </FilesMatch>
    </IfModule>

</VirtualHost>

任何人都可以给我的任何帮助将不胜感激!你们为帮助像我这样的其他初出茅庐的程序员所做的一切令人惊叹。谢谢你,谢谢你,谢谢你。

标签: apacheperltimestampdebiancgi

解决方案


在 Perl 5.12 之前,在 void 上下文中调用时split将其结果存储在其中。@_这是一种可怕的做法,因此在 5.12 中删除了“功能”,并添加了警告 ( Useless use of split in void context)。

我怀疑您使用的 Perl 版本比您以前使用的要新,它split在 void 上下文中没有特别的行为。如果是这种情况,您应该收到警告。一直用use strict; use warnings qw( all );

要解决问题,请更换

split (/\|/);

@_ = split (/\|/);

(您应该使用与 不同的数组@_,但以上是最小的变化。)


您似乎在这方面花了很多时间,但实际上并没有花任何时间尝试调试问题!您所做的第一件事是添加 missing use warnings qw( all );,这会立即发现问题。即使没有这个,最少的工作也应该将问题缩小到split.

  1. 你应该发现这$num eq ""总是正确的。
  2. 这会让你发现那$_[0] eq $date总是错误的。
  3. 这会导致您发现$_[0]永远不会设置。

推荐阅读