CGI 脚本和 shell 中的不同 @INC

Different @INC at CGI script and shell

我有以下 docker-撰写文件:

version: '2'

services:
    test:
        image: httpd
        container_name: inc_test
        ports:
            - "3000:80"
        environment:
            - PERL5LIB=/somedir
            - PERLLIB=/somedir
        command:
            - bash
            - -c
            - |
                cat /usr/local/apache2/conf/httpd.conf | grep modules/mod_cgid.so
                sed -i 's,#\(LoadModule cgid_module modules/mod_cgid.so\),,g' /usr/local/apache2/conf/httpd.conf
                cat /usr/local/apache2/conf/httpd.conf | grep modules/mod_cgid.so
                echo '#!/usr/bin/env perl' >> /usr/local/apache2/cgi-bin/test.pl
                echo 'print "Content-type: text/html\n\n";' >> /usr/local/apache2/cgi-bin/test.pl
                echo 'print join("\n", @INC);' >> /usr/local/apache2/cgi-bin/test.pl
                ls -lah /usr/local/apache2/cgi-bin/test.pl
                cat /usr/local/apache2/cgi-bin/test.pl
                httpd -M | grep -e cgid -e alias
                chmod a+x /usr/local/apache2/cgi-bin/test.pl
                perl -le 'print for @INC'
                echo "Which perl : "
                which perl
                httpd-foreground

当我去 http://localhost:3000/cgi-bin/test.pl 时,我看到 /somedir 不在 @INC 中。然而 perl -le 'print for @INC' 包含 /somedir。 什么鬼?

在调查问题后,我通过检查 httpd.conf 发现 daemon 用户下的 httpd 运行 httpd-foreground,而不是 root。

用户 daemon 默认没有 shebang:

$ docker run -it httpd cat /etc/passwd | grep daemon
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin

但即使我们加上

runuser - daemon -c "export PERL5LIB=/somedir" -s /bin/bash

command: 它不会将变量传递给 perl,因为 httpd 运行 CGI 脚本在单独的、隔离的进程中,所以 shell 也是隔离的。我们只能通过使用 mod_env SetEnvPassEnv 指令来控制 ENV 变量。

因此,为了将 /somedir 传递给 @INC,我们需要添加

echo "SetEnv PERL5LIB /somedir" >> /usr/local/apache2/conf/httpd.conf