Perl, работающий от имени пользователя "apache", не может загрузить DBD :: mysql, в то время как другие пользователи могут - PullRequest
1 голос
/ 23 апреля 2020

На сайте, которым я управляю, есть несколько CGI-скриптов, которые запускают скрипты вида:

#!/usr/bin/env bash

perl my-script.pl

my-script.pl использует DBD :: mysql.

use DBD::mysql;

My сценарии используют много модулей CPAN, и я не хочу загрязнять «систему» ​​Perl (5.16), установленную дистрибутивом Linux. Наша политика безопасности требует, чтобы httpd запускался как пользователь "apache" и чтобы apache не имел домашнего каталога на нашем сервере, поэтому я решил установить Perl с perlbrew под другим домашним каталогом, к которому у меня есть доступ. Затем файл конфигурации Apache для виртуального хоста устанавливает некоторые env-переменные для доступа к нему.

SetEnv PATH /export/home/user1/perl5/perlbrew/perls/perl-5.30.2/bin:${PATH}
SetEnv PERL5LIB /export/home/user1/perl5/perlbrew/perls/perl-5.30.2/lib  # this may not be needed

Это работает достаточно хорошо для загрузки большинства модулей. Например, apache может работать:

perl -mDateTime -e 'print $DateTime::VERSION' # prints "1.52"

, но если apache пытается:

perl -mDBD::mysql -e 'print $DBD::mysql::VERSION'

it barfs:

Can't locate loadable object for module DBD::mysql in @INC (@INC contains: /export/home/user1/perl5/perlbrew/perls/perl-5.30.2/lib/site_perl/5.30.2/x86_64-linux /export/home/user1/perl5/perlbrew/perls/perl-5.30.2/lib/site_perl/5.30.2 /export/home/user1/perl5/perlbrew/perls/perl-5.30.2/lib/5.30.2/x86_64-linux /export/home/user1/perl5/perlbrew/perls/perl-5.30.2/lib/5.30.2) at -e line 0.
Compilation failed in require.
BEGIN failed--compilation aborted.

Сообщение об ошибке " Не могу найти ... "вводит в заблуждение. Я подтвердил, что DBD :: mysql доступен по 3-му пути в @ IN C:

$ find ~user1/perl5/perlbrew/perls/perl-5.30.2/lib/site_perl/5.30.2  -name mysql -ls
16540213    4 drwxr-x---   2 user1   user1       4096 Apr 21 12:51 /export/home/user1/perl5/perlbrew/perls/perl-5.30.2/lib/site_perl/5.30.2/x86_64-linux/auto/DBD/mysql
16540211    4 drwxr-xr-x   2 user1   user1       4096 Apr 21 11:26 /export/home/user1/perl5/perlbrew/perls/perl-5.30.2/lib/site_perl/5.30.2/x86_64-linux/DBD/mysql

Кроме того, user1 может загрузить DBD :: mysql без проблем:

 perl -mDBD::mysql -e 'print $DBD::mysql::VERSION'  # prints 4.050

Поэтому я подозреваю, что вышеприведенное сообщение об ошибке должно было гласить: «Не удается загрузить libmysqlclient.so ...»

libmysqlclient.so находится в / usr / lib64 / mysql /

 ls -l /usr/lib64/mysql/
total 3076
lrwxrwxrwx  1 root root      17 Apr 16 11:59 libmysqlclient_r.so -> libmysqlclient.so
lrwxrwxrwx  1 root root      20 Apr 16 11:59 libmysqlclient.so -> libmysqlclient.so.18
lrwxrwxrwx  1 root root      24 Apr 16 11:57 libmysqlclient.so.18 -> libmysqlclient.so.18.0.0
-rwxr-xr-x  1 root root 3135664 Aug 18  2019 libmysqlclient.so.18.0.0
-rwxr-xr-x  1 root root    6758 Aug 18  2019 mysql_config
drwxr-xr-x. 2 root root    4096 Apr 16 11:57 plugin

Если user1 запускает perl -V, разделы Linker и Dynami c Linking показывают следующее:

  Linker and Libraries:
    ld='cc'
    ldflags =' -fstack-protector-strong -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib /lib/../lib64 /usr/lib/../lib64 /lib /lib64 /usr/lib64 /usr/local/lib64
    libs=-lpthread -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat
    perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    libc=libc-2.17.so
    so=so
    useshrplib=false
    libperl=libperl.a
    gnulibc_version='2.17'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs
    dlext=so
    d_dlsymun=undef
    ccdlflags='-Wl,-E'
    cccdlflags='-fPIC'
    lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector-strong'

Если я запускаю этот же perl как apache , он даст тот же результат:

sudo -u apache bash
PATH=~user1/perl5/perlbrew/perls/perl-5.30.2/bin:/usr/local/bin:/usr/bin:/usr/X11R6/bin
perl -V
...
  Linker and Libraries:
    ld='cc'
    ldflags =' -fstack-protector-strong -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib /lib/../lib64 /usr/lib/../lib64 /lib /lib64 /usr/lib64 /usr/local/lib64
    libs=-lpthread -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat
    perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    libc=libc-2.17.so
    so=so
    useshrplib=false
    libperl=libperl.a
    gnulibc_version='2.17'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs
    dlext=so
    d_dlsymun=undef
    ccdlflags='-Wl,-E'
    cccdlflags='-fPIC'
    lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector-strong'

Почему пользователь1 perl может загрузить DBD :: mysql, но apache не может, хотя оба работают с одинаковым Perl с одинаковые пути @ IN C и их динамические c пути загрузки библиотек выглядят одинаково? Кто-нибудь знает, что еще я могу сделать, чтобы добраться до сути этого?

1 Ответ

2 голосов
/ 23 апреля 2020

Для начала, вы никогда не должны делать

SetEnv PERL5LIB /export/home/user1/perl5/perlbrew/perls/perl-5.30.2/lib 

Если вы используете .../perl-5.30.2/bin/perl, он будет знать, что искать в .../perl-5.30.2/lib, и это единственный perl, который должен смотреть в этом каталоге.


В идеале, вы бы тоже не делали следующее:

SetEnv PATH /export/home/user1/perl5/perlbrew/perls/perl-5.30.2/bin:${PATH}

Шебанг скрипта должен указывать на perl, который он должен использовать (тот, с которым это было проверено и известно, что оно работает).

Другими словами, используйте в скрипте bash следующее:

./my-script.pl

И используйте следующий шебанг в my-script.pl:

#!/export/home/user1/perl5/perlbrew/perls/perl-5.30.2/bin/perl

То, что вы в настоящее время делаете, не страшно, но может укусить вас, если вы попытаетесь что-то обновить.


Наконец, perl не может найти модуль из-за вопросы разрешения. Предполагая, что пользователь apache не является членом группы user1, вы показали, что пользователь apache не может получить доступ к lib/site_perl/5.30.2/x86_64-linux/auto/DBD/mysql (и, возможно, он также не сможет получить доступ к другим соответствующим файлам).

Исправлено:

chmod go+X \
   /export \
   /export/home \
   /export/home/user1\
   /export/home/user1/perl5 \
   /export/home/user1/perl5/perlbrew \
   /export/home/user1/perl5/perlbrew/perls
chmod -R go+rX /export/home/user1/perl5/perlbrew/perls/perl-5.30.2
...