了解更多Greenplum技术干货,欢迎访问Greenplum中文社区网站
作为Greenplum Release Engineering团队的工程师,最近有机会深入探讨Postgres的构建系统。Greenplum Server基于Postgres,并从上游继承了构建系统。gp-releng团队正在创建可重定位版本的Greenplum Server,这使我们开始研究如何进行可重定位的Postgres版本。本文提到的可重定位(Relocated)指在不重新编译安装Postgres的情况下,改变原有安装路径后,程序依然可以正常运行,并且不需要设置LD_LIBRARY_PATH就能使程序找到正确的共享库。 考虑以下假设情景,以突出关键思想和发现过程,而不是被我们团队的用例的细节所困扰。
构建Postgres 11.8
Cardenia是一家美国大学实验室的研究生。她想使用Postgres进行数据分析,但是她对实验室的共享服务器没有root访问权限。她不想打扰该服务器的银发管理员,于是决定在自己的主目录中构建,安装和运行Postgres。由于数据分析使用了Perl模块,因此需要配置Postgres使用PL / Perl。
mkdir -p ~/.local/src
cd ~/.local/src
curl https://ftp.postgresql.org/pub/source/v11.8/postgresql-11.8.tar.bz2 | \
tar -xj
cd ./postgresql-11.8
./configure \
--prefix=/home/cardenia/.local/postgres \
--with-perl
make -j
make install
至此已成功构建并安装了Postgres。她决定进行一次快速验证
$ cd ~
$ export PATH="${HOME}/.local/postgres/bin:${PATH}"
$ initdb ~/test
...
$ pg_ctl -D ~/test -l logfile start
waiting for server to start.... done
server started
$ createdb
$ psql -c 'SELECT version();'
version
---------------------------------------------------------------------------------------------------------
PostgreSQL 11.8 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-bit
(1 row)
看起来Postgres服务器已启动并运行,但她还想确保PL / Perl也能正常工作。于是启动psql并创建PL / Perl函数
-- taken from https://www.postgresql.org/docs/11/plperl-funcs.html
CREATE EXTENSION plperl;
CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS $$
if ($_[0] > $_[1]) { return $_[0]; }
return $_[1];
$$ LANGUAGE plperl;
她通过调用以下函数来测试PL / Perl是否正常工作:
$ psql -c 'SELECT perl_max(1, 2);'
perl_max
----------
2
(1 row)
构建Postgres 12
距离Cardenia构建并安装Postgres 11.8,过去一段时间了,这时,Postgres 12发布了。新版本看起来有一些很好的新功能,但是Cardenia不确定她是否要从Postgres 11原地升级。于是她决定与现有Postgres 11.8并行安装Postgres 12。
现有的Postgres 11.8安装在~/.local/postgres中。那么在哪里安装新版本呢?Cardenia 决定将在安装位置包含版本信息,这样可以方便区分两个Postgres版本。
$ pg_ctl -D ~/test -l logfile stop
$ mv ~/.local/postgres ~/.local/postgres-11
$ export PATH="${HOME}/.local/postgres-11/bin:${PATH}"
$ pg_ctl -D ~/test -l logfile start
$ psql -c 'SELECT version();'
psql: error while loading shared libraries: libpq.so.5: cannot open shared object file: No such file or directory
Cardenia知道应用程序在运行时,需要ld-linux帮助二进制文件找到依赖的共享库,而通过ldd,可以帮助Cardenia打印二进制文件所依赖的共享库。
$ ldd ~/.local/postgres-11/bin/psql
linux-vdso.so.1 => (0x00007ffe5b9d2000)
libpq.so.5 => not found
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f6981cae000)
libreadline.so.6 => /lib64/libreadline.so.6 (0x00007f6981a68000)
librt.so.1 => /lib64/librt.so.1 (0x00007f6981860000)
libm.so.6 => /lib64/libm.so.6 (0x00007f698155e000)
libc.so.6 => /lib64/libc.so.6 (0x00007f6981190000)
/lib64/ld-linux-x86-64.so.2 (0x00007f6981eca000)
libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00007f6980f66000)
注意:在不受信任的二进制文件上执行ldd是危险的,因为它会执行所探测的程序–相关概念参考ldd arbitrary code execution(https://catonmat.net/ldd-arbitrary-code-execution)。当使用未知来源的二进制文件时,最好来自binutils的readelf。
ldd的输出显示动态链接器无法找到libpq.so.5。但是她通过以下检查,得知libpq.so.5确实存在:
$ ls -l ~/.local/postgres-11/lib/libpq.so*
lrwxrwxrwx 1 cardenia cardenia 13 Jul 23 21:14 /home/cardenia/.local