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 SetEnv
和 PassEnv
指令来控制 ENV 变量。
因此,为了将 /somedir
传递给 @INC
,我们需要添加
echo "SetEnv PERL5LIB /somedir" >> /usr/local/apache2/conf/httpd.conf
我有以下 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 SetEnv
和 PassEnv
指令来控制 ENV 变量。
因此,为了将 /somedir
传递给 @INC
,我们需要添加
echo "SetEnv PERL5LIB /somedir" >> /usr/local/apache2/conf/httpd.conf