【问题标题】:Perl CGI backticks output assigned to array not present in generated HTML. Possible evaluation order issuePerl CGI 反引号输出分配给生成的 HTML 中不存在的数组。可能的评估订单问题
【发布时间】:2026-01-26 02:40:02
【问题描述】:

我创建了这个 CGI perl 脚本,它调用一个 shell 脚本 (lookup.sh) 来查询 Oracle 数据库,它使用传递给 shell 脚本的第一个参数作为用户名来交叉引用组成员身份。

shell 脚本返回由新行分隔的所有组。我将这个 Perl 脚本作为 CGI 操作传递给一个非常简单的 html 表单,该表单将 USER 参数传递给 perl 脚本,然后 perl 脚本运行 shell 脚本并将原始 html 表单中的用户名作为第一个 arg 传递,然后应该存储在名为@outp 的数组中返回值。

我的测试显示一切正常,但是当我从浏览器运行它时,@outp 数组每次都显示为空白。所有其他测试的数组都包含正确的数据,我唯一能做的假设是 HTML 是在数组填充反引号命令的数据之前生成的。有人可以插话吗?

HTML:

<FORM action="/cgi-bin/test.cgi" method="POST">
USER: <input type="text" name="USER">  <br>
<input type="submit" value="Submit">
</FORM>

壳牌:

      #!/bin/bash

sqlplus -s DB_USER/DB_PASS@//DB_HOST:1521/JIRA_RW <<< "SELECT GROUP_NAME from    jira_db.membershipbase where USER_NAME='$1';"

Perl:

#!/usr/bin/perl
use CGI qw(:standard);


$data = param('USER') || '<i>(No input)</i>';

@outp = `/bin/lookup.sh $data`;
print <<END;
Content-Type: text/html; charset=iso-8859-1

 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<title>Jira User Query</title>
<h1>Group Membership for $data @outp</h1>
<p>print @outp</p>
END

是的,我知道这是一项彻头彻尾的黑客工作。

【问题讨论】:

  • 尝试通过调试定位问题,即。 @outp = '/bin/lookup.sh hardcoded_user'; 并检查网络服务器日志。

标签: perl cgi


【解决方案1】:

首先从 Perl 查询数据库会更好。

好读物:How can I troubleshoot my Perl CGI script?, http://www.cs.cf.ac.uk/Dave/PERL/node1.html

直到你可以做这样的事情:

#!/usr/bin/perl
use CGI qw(:standard);

print "Content-Type: text/html; charset=iso-8859-1\n\n";

use strict;
use warnings;
use CGI::Carp 'fatalsToBrowser';

my $data = param('USER') || '<i>(No input)</i>';

my $outp = `/bin/lookup.sh '$data' 2>&1`;chomp($outp);
if ($?){
  $outp = "Execution error! error coode: $?";
}

print <<END;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html><header></header><body>
<title>Jira User Query</title>
<h1>Group Membership for $data $outp</h1>
END

print "\n<p>print $outp</p>\n</body></html>\n";

使用 DBI 会是(它仍然是 XX.世纪风格,对于新的开发,您可以尝试 Dancer、Mojo 或其他新事物):

#!/usr/bin/perl
use CGI qw(:standard);

print "Content-Type: text/html; charset=iso-8859-1\n\n";

use strict;
use warnings;
use CGI::Carp 'fatalsToBrowser';
use DBI;

my $q = new CGI;
print $q->header;
print $q->start_html;
print $q->h1("Hello, it is working!!!");


my $sql = "SELECT GROUP_NAME from jira_db.membershipbase where USER_NAME=?";
if (defined param('USER')){
  print $q->p("param user: ".param('USER'));
  my $dbh = DBI->connect('dbi:mysql:perltest','root','password') or die "Connection Error: $DBI::errstr\n";
  my $sth = $dbh->prepare($sql);
  $sth->execute(param('USER'));
  while ( my @row = $sth->fetchrow_array() ){
    print $q->p($row[0]);
  }
}

print $q->end_html;

【讨论】:

  • "首先从 Perl 查询数据库会更好。"使用Jira's API 会更好:-)
  • 我知道,但是由于缺少 *.mk 文件,我在编译 DBD::Oracle 时遇到了问题,这是一个快速的解决方法。
  • 我希望它是一个 mysql 数据库,我会完成的。它是甲骨文。
  • 谢谢,我遇到的问题是 shell 脚本中的 sqlplus 二进制文件没有为 apache 用户提供正确的 LD_LIBRARY_PATH 环境设置,所以当脚本由 root 运行时它很好,但我需要将 ORACLE_HOME 和 PATH 添加到 Oracle 库中,然后将它们导出到 shell 脚本中。我将脚本 setuid 设置为 root,但我猜它不使用 root 环境,或者我没有为 root 环境设置这些变量。