【问题标题】:Perl how to detect if running from the command line or called from browserPerl如何检测是从命令行运行还是从浏览器调用
【发布时间】:2025-12-17 21:30:01
【问题描述】:

有没有一种好方法可以检测 Perl 脚本是从终端/DOS 调用还是从 Web 服务器调用。

我目前有这个代码:

sub cli {
    # return 1 if called from browser, 0 if called from command line
    if  (defined $ENV{GATEWAY_INTERFACE} ||  exists $ENV{HTTP_HOST}){
        return 0;
    }
    return 1;
}

但请注意,并非所有服务器都设置了这些 ENV 变量。

如果脚本从终端运行,我将打印文本/纯格式的消息,如果从浏览器运行,我将打印 HTML 格式的消息。

【问题讨论】:

  • this question 中所示,也许检查$ENV{REQUEST_METHOD},因为CGI 就是这样确定Web 请求和命令行调用之间的区别的。
  • 您的终端是否在网络服务器上?
  • @vol7ron 我看到接受的答案正在检查$ENV{GATEWAY_INTERFACE},所以仍然没有一种方法得到所有人的确认,但是你指出这个答案很好,它有很多新想法
  • 就我个人而言,我的技术是将大部分脚本移动到提供to_textto_html 函数/方法的模块中。然后有两个脚本 - 一个调用to_text,一个调用to_html。通过 Web 浏览器访问 HTML 输出脚本,并在命令行运行文本输出脚本。简单。

标签: perl


【解决方案1】:

我通常这样做:

if (-t STDIN) {
    //This is running from a terminal
}

阅读 cmets 后编辑:我发现了另一个详细说明不同解决方案的问题:How do I check if a Perl script is running in a terminal?

【讨论】:

  • 这将告诉您 STDIN 是否连接到终端。但是,比如说,echo "foo" | perl myscript.pl。 STDIN 不再附加到终端,但我们仍在从命令行运行脚本;不是通过网络服务器。
【解决方案2】:

以下是一个简单的示例,可能不是最准确的,但用于证明您可以检查进程的父命令。

my $parent_process  = `ps -o ppid= -p $$ | xargs ps -o command= -p`;
if ($parent_process =~ /httpd/) {
   say q{CGI};
} else {
   say q{Terminal};
}

基本上,我们检索当前进程的搜索,并将该父进程通过管道传输到另一个查找中,以便我们可以获得父进程运行的命令。从终端它应该是 shell 名称(例如,-bash),但如果它是由服务器运行的,它应该是服务器守护进程 httpd(取决于 Web 服务器)。

让服务器设置环境变量并检查该变量是否存在会容易得多。这一切都取决于您在哪里运行命令以及以谁身份运行命令。

这可以进一步浓缩为:

my $is_server = `ps -o ppid= -p $$ | xargs ps -o command= -p | grep httpd -q && echo "1" || echo "0"`; chomp $is_server;
if ($is_server) { ... } else { ... }

【讨论】: