Várias bibliotecas glibc em um único host

171

Várias bibliotecas glibc em um único host

Meu servidor linux (SLES-8) atualmente possui glibc-2.2.5-235, mas eu tenho um programa que não funciona nesta versão e requer glibc-2.3.3.

É possível ter vários glibcs ​​instalados no mesmo host?

Este é o erro que recebo quando executo meu programa na glibc antiga:

./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./myapp)
./myapp: /lib/i686/libpthread.so.0: version `GLIBC_2.3.2' not found (required by ./myapp)
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./libxerces-c.so.27)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by ./libstdc++.so.6)
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./libstdc++.so.6)

Então, criei um novo diretório chamado newglibc e copiei os seguintes arquivos em:

libpthread.so.0
libm.so.6
libc.so.6
ld-2.3.3.so
ld-linux.so.2 -> ld-2.3.3.so

e

export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH

Mas eu recebo um erro:

./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libpthread.so.0)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by libstdc++.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libm.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by ./newglibc/libc.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libc.so.6)

Então parece que eles ainda estão vinculando a / lib e não pegando de onde eu os coloquei?

obrigado

dogbane
fonte
1
mesmo problema com o servidor SLES-11. Não é possível atualizar e precisa de coisas recentes. oh meu ...
UmNyobe 14/09/12
FWIW, export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH fez resolver o problema para mim! Certamente não funcionará para todos, mas é uma solução fácil se funcionar! Obrigado! :)
rinogo

Respostas:

229

É muito possível ter várias versões do glibc no mesmo sistema (fazemos isso todos os dias).

No entanto, você precisa saber que o glibc consiste em várias partes (mais de 200 bibliotecas compartilhadas) às quais todas devem corresponder. Uma das partes é ld-linux.so.2, e deve corresponder à libc.so.6, ou você verá os erros que está vendo.

O caminho absoluto para ld-linux.so.2 é codificado no executável no momento do link e não pode ser facilmente alterado depois que o link for concluído.

Para criar um executável que funcione com a nova glibc, faça o seguinte:

g++ main.o -o myapp ... \
   -Wl,--rpath=/path/to/newglibc \
   -Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2

A -rpathopção vinculador fará com que o carregador de tempo de execução procure bibliotecas /path/to/newglibc(para que você não precise configurá- LD_LIBRARY_PATHlo antes de executá-lo), e a -dynamic-linkeropção irá "assar" o caminho para corrigir ld-linux.so.2o aplicativo.

Se você não pode vincular novamente o myappaplicativo (por exemplo, porque é um binário de terceiros), nem tudo está perdido, mas fica mais complicado. Uma solução é definir um chrootambiente adequado para isso. Outra possibilidade é usar o rtldi e um editor binário .

Russo empregado
fonte
3
Observe que -Wl,--dynamic-linker=file(leva dois '-') só funciona ao compilar para executáveis ​​do ELF. Verifique/sbin/ldconfig -p | grep ld
Tom
49
Agora você pode usar um utilitário conveniente patchelf( nixos.org/patchelf.html ), que permite modificar o rpath e o intérprete do ELF já compilado.
Michael Pankov
10
Vale ressaltar que especificar o caminho para a nova glibc usando em -Wl,--rpathvez de LD_LIBRARY_PATHpode ser importante por outros motivos que não sejam convenientes: se o programa iniciar processos filhos, o valor de LD_LIBRARY_PATHgeralmente será herdado por eles, mas se eles também não forem compilados para uso o glibc mais recente (por exemplo, se eles são binários de ações bash), eles não serão lançados.
precisa saber é o seguinte
13
Outra opção é executar o novo ld.so diretamente, passando seu programa binário como parâmetro; isso substituirá efetivamente o ld.so usado sem a necessidade de recompilar o programa:/path/to/newglibc/ld-linux.so.2 --library-path /path/tonewglibc/lib64:/path/to/newglibc/usr/lib64 /path/to/myapp
maximk
Eu também precisava -Ie -L: stackoverflow.com/a/52454603/895245
Ciro Santilli郝海东冠状病六四事件法轮功
67

Esta pergunta é antiga, as outras respostas são antigas. A resposta do "russo empregado" é muito boa e informativa, mas só funciona se você tiver o código-fonte. Caso contrário, as alternativas naquela época eram muito complicadas. Felizmente hoje em dia temos uma solução simples para esse problema (como comentado em uma de suas respostas), usando o patchelf . Tudo o que tem a fazer é:

$ ./patchelf --set-interpreter /path/to/newglibc/ld-linux.so.2 --set-rpath /path/to/newglibc/ myapp

E depois disso, você pode simplesmente executar seu arquivo:

$ ./myapp

Não é necessário chrooteditar manualmente os binários, felizmente. Mas lembre-se de fazer backup do seu binário antes de corrigi-lo, se você não tiver certeza do que está fazendo, porque ele modifica seu arquivo binário. Depois de corrigi-lo, você não pode restaurar o caminho antigo para o interpretador / rpath. Se não funcionar, você precisará corrigi-lo até encontrar o caminho que realmente funcionará ... Bem, não precisa ser um processo de tentativa e erro. Por exemplo, no exemplo do OP, ele precisava GLIBC_2.3, para que você possa encontrar facilmente qual lib fornece essa versão usando strings:

$ strings /lib/i686/libc.so.6 | grep GLIBC_2.3
$ strings /path/to/newglib/libc.so.6 | grep GLIBC_2.3

Em teoria, o primeiro grep ficaria vazio porque o libc do sistema não possui a versão que ele deseja, e o segundo deve gerar GLIBC_2.3 porque possui a versão em myappuso, portanto sabemos que podemos patchelfusar nosso binário nesse caminho.

Quando você tenta rodar um binário no linux, o binário tenta carregar o vinculador, depois as bibliotecas, e todas elas devem estar no caminho e / ou no lugar certo. Se o seu problema está no vinculador e você deseja descobrir qual o caminho que seu binário está procurando, você pode descobrir com este comando:

$ readelf -l myapp | grep interpreter
  [Requesting program interpreter: /lib/ld-linux.so.2]                                                                                                                                                                                   

Se o seu problema for com as bibliotecas, os comandos que fornecerão as bibliotecas que estão sendo usadas são:

$ readelf -d myapp | grep Shared
$ ldd myapp 

Isso listará as bibliotecas que seu binário precisa, mas você provavelmente já conhece as problemáticas, pois elas já estão gerando erros, como no caso do OP.

"patchelf" funciona para muitos problemas diferentes que você pode encontrar ao tentar executar um programa, relacionado a esses 2 problemas. Por exemplo, se você obtiver ELF file OS ABI invalid:, pode ser corrigido configurando um novo carregador (a --set-interpreterparte do comando), como explico aqui . Outro exemplo é o problema de obter No such file or directoryquando você executa um arquivo que está lá e é executável, como exemplificado aqui . Nesse caso específico, o OP estava sem um link para o carregador, mas talvez no seu caso você não tenha acesso root e não possa criar o link. Definir um novo intérprete resolveria seu problema.

Obrigado Empregado russo e Michael Pankov pela visão e solução!

msb
fonte
1
Este foi o mais útil! Eu corrigi python binário para usar nova glibc para tensorflow
faizan
Esta é uma solução interessante (eu não sabia anteriormente patchelf), mas a frase "Não há necessidade de ... editar binários" pode ser um pouco enganadora (já que você está realmente editando seus binários).
Larsks4 /
Lá, consertado. ;)
msb
Utilidade realmente útil! Obrigado! Embora eu só conseguiu obter uma falha de segmentação depois de horas de resolver manualmente dependências então remendar tudo para localmente instalar o Chrome sem privilégios de administrador ...
G. Bergeron
@fgiraldeau obrigado pelo elogio. :) mas a pergunta foi feita, respondida e aceita em 2009, eu não esperaria que alguém esperasse 8 anos antes de aceitar uma resposta. heheh; D
msb 22/09
20

Use LD_PRELOAD: coloque sua biblioteca em algum lugar fora dos diretórios man lib e execute:

LD_PRELOAD='mylibc.so anotherlib.so' program

Veja: o artigo da Wikipedia

PiedPiper
fonte
1
pensei que esta seria uma boa solução para um Makefile complexo, mas não funcionou para mim
Galactica
que é útil particularmente aqueles não binary.thanks fonte
codificador
2
Um ... Eu estava errado ,, parecer que eu preciso rPath o ld-linux.so a caminho / / a / new / lib / Frist, enquanto fonte de compilação e vinculando
codificador
1
Isso não funciona se ld - # ## por isso (a partir de seu sistema glibc lib) não é a mesma versão glibc como libc.so. # (do seu lib glibc alternativo)..
Andy
12

Primeiro de tudo, a dependência mais importante de cada programa vinculado dinamicamente é o vinculador. Todas as bibliotecas devem corresponder à versão do vinculador.

Vamos dar um exemplo simples: eu tenho o sistema ubuntu newset onde eu corro algum programa (no meu caso é o compilador D - ldc2). Gostaria de executá-lo no antigo CentOS, mas por causa da biblioteca glibc mais antiga, é impossível. Eu tenho

ldc2-1.5.0-linux-x86_64/bin/ldc2: /lib64/libc.so.6: version `GLIBC_2.15' not found (required by ldc2-1.5.0-linux-x86_64/bin/ldc2)
ldc2-1.5.0-linux-x86_64/bin/ldc2: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ldc2-1.5.0-linux-x86_64/bin/ldc2)

Eu tenho que copiar todas as dependências do ubuntu para centos. O método adequado é o seguinte:

Primeiro, vamos verificar todas as dependências:

ldd ldc2-1.5.0-linux-x86_64/bin/ldc2 
    linux-vdso.so.1 =>  (0x00007ffebad3f000)
    librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f965f597000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f965f378000)
    libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f965f15b000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f965ef57000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f965ec01000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f965e9ea000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f965e60a000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f965f79f000)

O linux-vdso.so.1 não é uma biblioteca real e não precisamos nos preocupar com isso.

/lib64/ld-linux-x86-64.so.2 é o vinculador, que é usado pelo linux vincula o executável a todas as bibliotecas dinâmicas.

O restante dos arquivos são bibliotecas reais e todos eles, juntamente com o vinculador, devem ser copiados em algum lugar dos centos.

Vamos supor que todas as bibliotecas e vinculadores estejam no diretório "/ mylibs".

ld-linux-x86-64.so.2 - como eu já disse - é o vinculador. Não é uma biblioteca dinâmica, mas executável estática. Você pode executá-lo e ver que ele ainda possui alguns parâmetros, por exemplo - --library-path (retornarei a ele).

No Linux, o programa vinculado dinamicamente pode ser almoçado apenas por seu nome, por exemplo

/bin/ldc2

O Linux carrega esse programa na RAM e verifica qual vinculador está configurado para ele. Normalmente, no sistema de 64 bits, é /lib64/ld-linux-x86-64.so.2 (no seu sistema de arquivos é um link simbólico para o executável real). Em seguida, o linux executa o vinculador e carrega bibliotecas dinâmicas.

Você também pode mudar isso um pouco e fazer esse truque:

/mylibs/ld-linux-x86-64.so.2 /bin/ldc2

É o método para forçar o linux a usar o vinculador específico.

E agora podemos retornar ao parâmetro mencionado anteriormente --library-path

/mylibs/ld-linux-x86-64.so.2 --library-path /mylibs /bin/ldc2

Ele executará o ldc2 e carregará bibliotecas dinâmicas em / mylibs.

Este é o método para chamar o executável com bibliotecas escolhidas (não padrão do sistema).

Arkadiusz Rychliński
fonte
Compilei um programa no RH7 e preciso que ele seja executado no RH6. Eu não queria criar um novo executável ou usar o patchelf, então essa é uma ótima alternativa.
precisa saber é o seguinte
9

Configuração 1: compile seu próprio glibc sem o GCC dedicado e use-o

Essa configuração pode funcionar e é rápida, pois não recompila toda a cadeia de ferramentas do GCC, apenas glibc.

Mas não é confiável, pois usa anfitrião C runtime objetos como crt1.o, crti.oe crtn.ofornecido pela glibc. Isso é mencionado em: https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location Esses objetos fazem a configuração antecipada em que a glibc depende, portanto, não ficaria surpreso se algo acontecesse de maneira maravilhosa. e maneiras incrivelmente sutis.

Para uma configuração mais confiável, consulte a Instalação 2 abaixo.

Crie o glibc e instale localmente:

export glibc_install="$(pwd)/glibc/build/install"

git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28
mkdir build
cd build
../configure --prefix "$glibc_install"
make -j `nproc`
make install -j `nproc`

Instalação 1: verifique a compilação

test_glibc.c

#define _GNU_SOURCE
#include <assert.h>
#include <gnu/libc-version.h>
#include <stdatomic.h>
#include <stdio.h>
#include <threads.h>

atomic_int acnt;
int cnt;

int f(void* thr_data) {
    for(int n = 0; n < 1000; ++n) {
        ++cnt;
        ++acnt;
    }
    return 0;
}

int main(int argc, char **argv) {
    /* Basic library version check. */
    printf("gnu_get_libc_version() = %s\n", gnu_get_libc_version());

    /* Exercise thrd_create from -pthread,
     * which is not present in glibc 2.27 in Ubuntu 18.04.
     * /programming/56810/how-do-i-start-threads-in-plain-c/52453291#52453291 */
    thrd_t thr[10];
    for(int n = 0; n < 10; ++n)
        thrd_create(&thr[n], f, NULL);
    for(int n = 0; n < 10; ++n)
        thrd_join(thr[n], NULL);
    printf("The atomic counter is %u\n", acnt);
    printf("The non-atomic counter is %u\n", cnt);
}

Compile e execute com test_glibc.sh:

#!/usr/bin/env bash
set -eux
gcc \
  -L "${glibc_install}/lib" \
  -I "${glibc_install}/include" \
  -Wl,--rpath="${glibc_install}/lib" \
  -Wl,--dynamic-linker="${glibc_install}/lib/ld-linux-x86-64.so.2" \
  -std=c11 \
  -o test_glibc.out \
  -v \
  test_glibc.c \
  -pthread \
;
ldd ./test_glibc.out
./test_glibc.out

O programa gera o esperado:

gnu_get_libc_version() = 2.28
The atomic counter is 10000
The non-atomic counter is 8674

Comando adaptado de https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location, mas --sysrootfalhou com:

cannot find /home/ciro/glibc/build/install/lib/libc.so.6 inside /home/ciro/glibc/build/install

então eu o removi.

lddoutput confirma que as lddbibliotecas e que acabamos de criar estão realmente sendo usadas conforme o esperado:

+ ldd test_glibc.out
        linux-vdso.so.1 (0x00007ffe4bfd3000)
        libpthread.so.0 => /home/ciro/glibc/build/install/lib/libpthread.so.0 (0x00007fc12ed92000)
        libc.so.6 => /home/ciro/glibc/build/install/lib/libc.so.6 (0x00007fc12e9dc000)
        /home/ciro/glibc/build/install/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fc12f1b3000)

A gccsaída de depuração da compilação mostra que meus objetos de tempo de execução do host foram usados, o que é ruim como mencionado anteriormente, mas não sei como contornar isso, por exemplo, ele contém:

COLLECT_GCC_OPTIONS=/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o

Configuração 1: modificar glibc

Agora vamos modificar o glibc com:

diff --git a/nptl/thrd_create.c b/nptl/thrd_create.c
index 113ba0d93e..b00f088abb 100644
--- a/nptl/thrd_create.c
+++ b/nptl/thrd_create.c
@@ -16,11 +16,14 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */

+#include <stdio.h>
+
 #include "thrd_priv.h"

 int
 thrd_create (thrd_t *thr, thrd_start_t func, void *arg)
 {
+  puts("hacked");
   _Static_assert (sizeof (thr) == sizeof (pthread_t),
                   "sizeof (thr) != sizeof (pthread_t)");

Em seguida, recompile e reinstale o glibc, recompile e execute novamente o nosso programa:

cd glibc/build
make -j `nproc`
make -j `nproc` install
./test_glibc.sh

e vemos hackedimpressos algumas vezes conforme o esperado.

Isso confirma ainda mais que usamos o glibc que compilamos e não o host.

Testado no Ubuntu 18.04.

Configuração 2: configuração intacta crosstool-NG

Esta é uma alternativa para a configuração 1, e é a configuração mais correta que consegui agora: tudo está correto, tanto quanto eu posso observar, incluindo o tempo de execução C objetos como crt1.o, crti.oecrtn.o .

Nesta configuração, compilaremos uma cadeia de ferramentas GCC dedicada completa que usa a glibc que queremos.

A única desvantagem desse método é que a compilação levará mais tempo. Mas eu não arriscaria uma instalação de produção com nada menos.

O crosstool-NG é um conjunto de scripts que baixa e compila tudo da fonte para nós, incluindo GCC, glibc e binutils.

Sim, o sistema de criação do GCC é tão ruim que precisamos de um projeto separado para isso.

Essa configuração não é perfeita porque o crosstool-NG não suporta a criação de executáveis ​​sem -Wlsinalizadores extras , o que é estranho desde que criamos o próprio GCC. Mas tudo parece funcionar, então isso é apenas um inconveniente.

Obtenha crosstool-NG, configure e construa:

git clone https://github.com/crosstool-ng/crosstool-ng
cd crosstool-ng
git checkout a6580b8e8b55345a5a342b5bd96e42c83e640ac5
export CT_PREFIX="$(pwd)/.build/install"
export PATH="/usr/lib/ccache:${PATH}"
./bootstrap
./configure --enable-local
make -j `nproc`
./ct-ng x86_64-unknown-linux-gnu
./ct-ng menuconfig
env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`

A construção leva cerca de trinta minutos a duas horas.

A única opção de configuração obrigatória que posso ver é fazer com que ela corresponda à sua versão do kernel do host para usar os cabeçalhos corretos do kernel. Encontre a sua versão do kernel host com:

uname -a

o que me mostra:

4.15.0-34-generic

então menuconfigeu faço:

  • Operating System
    • Version of linux

então eu seleciono:

4.14.71

qual é a primeira versão igual ou mais antiga. Tem que ser mais antigo, pois o kernel é compatível com versões anteriores.

Instalação 2: configurações opcionais

O .configque geramos com ./ct-ng x86_64-unknown-linux-gnu:

CT_GLIBC_V_2_27=y

Para mudar isso, menuconfigfaça:

  • C-library
  • Version of glibc

Salve o .config e continue com a compilação.

Ou, se você quiser usar sua própria fonte glibc, por exemplo, para usar glibc a partir do git mais recente, proceda da seguinte maneira :

  • Paths and misc options
    • Try features marked as EXPERIMENTAL: definido como true
  • C-library
    • Source of glibc
      • Custom location: diga sim
      • Custom location
        • Custom source location: aponte para um diretório que contém sua fonte glibc

onde glibc foi clonado como:

git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28

Instalação 2: teste

Depois de criar a cadeia de ferramentas desejada, teste-a com:

#!/usr/bin/env bash
set -eux
install_dir="${CT_PREFIX}/x86_64-unknown-linux-gnu"
PATH="${PATH}:${install_dir}/bin" \
  x86_64-unknown-linux-gnu-gcc \
  -Wl,--dynamic-linker="${install_dir}/x86_64-unknown-linux-gnu/sysroot/lib/ld-linux-x86-64.so.2" \
  -Wl,--rpath="${install_dir}/x86_64-unknown-linux-gnu/sysroot/lib" \
  -v \
  -o test_glibc.out \
  test_glibc.c \
  -pthread \
;
ldd test_glibc.out
./test_glibc.out

Tudo parece funcionar como na Instalação 1, exceto que agora os objetos de tempo de execução corretos foram usados:

COLLECT_GCC_OPTIONS=/home/ciro/crosstool-ng/.build/install/x86_64-unknown-linux-gnu/bin/../x86_64-unknown-linux-gnu/sysroot/usr/lib/../lib64/crt1.o

Configuração 2: falha na tentativa eficiente de recompilação glibc

Não parece possível com o crosstool-NG, conforme explicado abaixo.

Se você apenas reconstruir;

env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`

suas alterações no local de origem glibc personalizado são levadas em consideração, mas ele cria tudo do zero, tornando-o inutilizável para o desenvolvimento iterativo.

Se nós fizermos:

./ct-ng list-steps

fornece uma boa visão geral das etapas de compilação:

Available build steps, in order:
  - companion_tools_for_build
  - companion_libs_for_build
  - binutils_for_build
  - companion_tools_for_host
  - companion_libs_for_host
  - binutils_for_host
  - cc_core_pass_1
  - kernel_headers
  - libc_start_files
  - cc_core_pass_2
  - libc
  - cc_for_build
  - cc_for_host
  - libc_post_cc
  - companion_libs_for_target
  - binutils_for_target
  - debug
  - test_suite
  - finish
Use "<step>" as action to execute only that step.
Use "+<step>" as action to execute up to that step.
Use "<step>+" as action to execute from that step onward.

portanto, vemos que há etapas glibc entrelaçadas com várias etapas do GCC, mais notavelmente libc_start_filesanteriores cc_core_pass_2, o que provavelmente é a etapa mais caracc_core_pass_1 .

Para criar apenas uma etapa, primeiro defina a opção "Salvar etapas intermediárias" na .configopção para a compilação inicial:

  • Paths and misc options
    • Debug crosstool-NG
      • Save intermediate steps

e então você pode tentar:

env -u LD_LIBRARY_PATH time ./ct-ng libc+ -j`nproc`

mas, infelizmente, o +exigido conforme mencionado em: https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536

Observe, no entanto, que reiniciar em uma etapa intermediária redefine o diretório de instalação para o estado que possuía durante essa etapa. Ou seja, você terá uma libc reconstruída - mas nenhum compilador final construído com essa libc (e, portanto, nenhuma biblioteca de compiladores como a libstdc ++).

e basicamente ainda torna a reconstrução muito lenta para ser viável para o desenvolvimento, e não vejo como superar isso sem aplicar o patch crosstool-NG.

Além disso, a partir da libcetapa parecia não copiar novamente a fonte Custom source location, tornando ainda mais inutilizável esse método.

Bônus: stdlibc ++

Um bônus se você também estiver interessado na biblioteca padrão do C ++: Como editar e recriar a fonte da biblioteca padrão do GCC libstdc ++ C ++?

Ciro Santilli adicionou uma nova foto
fonte
6

Você pode considerar usar o Nix http://nixos.org/nix/ ?

O Nix suporta o gerenciamento de pacotes para vários usuários: vários usuários podem compartilhar um armazenamento comum do Nix com segurança, não precisam ter privilégios de root para instalar o software e podem instalar e usar versões diferentes de um pacote.


fonte
4

O @msb oferece uma solução segura.

Eu conheci esse problema quando o fiz import tensorflow as tfno ambiente conda em CentOS 6.5que apenas o possui glibc-2.12.

ImportError: /lib64/libc.so.6: version `GLIBC_2.16' not found (required by /home/

Quero fornecer alguns detalhes:

Primeiro instale glibcno seu diretório inicial:

mkdir ~/glibc-install; cd ~/glibc-install
wget http://ftp.gnu.org/gnu/glibc/glibc-2.17.tar.gz
tar -zxvf glibc-2.17.tar.gz
cd glibc-2.17
mkdir build
cd build
../configure --prefix=/home/myself/opt/glibc-2.17  # <-- where you install new glibc
make -j<number of CPU Cores>  # You can find your <number of CPU Cores> by using **nproc** command
make install

Segundo, siga o mesmo caminho para instalar o patchelf ;

Terceiro, corrija seu Python:

[myself@nfkd ~]$ patchelf --set-interpreter /home/myself/opt/glibc-2.17/lib/ld-linux-x86-64.so.2 --set-rpath /home/myself/opt/glibc-2.17/lib/ /home/myself/miniconda3/envs/tensorflow/bin/python

como mencionado por @msb

Agora eu posso usar tensorflow-2.0 alphano CentOS 6.5.

ref: https://serverkurma.com/linux/how-to-update-glibc-newer-version-on-centos-6-x/

Belter
fonte
2

Não tenho certeza de que a pergunta ainda seja relevante, mas há outra maneira de corrigir o problema: Docker. Pode-se instalar um contêiner quase vazio da distribuição de origem (a distribuição usada para desenvolvimento) e copiar os arquivos no contêiner. Dessa forma, você não precisa criar o sistema de arquivos necessário para o chroot.

user1396055
fonte
1

Se você olhar atentamente para a segunda saída, poderá ver que o novo local para as bibliotecas é usado. Talvez ainda existam bibliotecas ausentes que fazem parte da glibc.

Eu também acho que todas as bibliotecas usadas pelo seu programa devem ser compiladas contra essa versão do glibc. Se você tiver acesso ao código fonte do programa, uma nova compilação parece ser a melhor solução.

rsarro
fonte
1

"Russo empregado" está entre as melhores respostas e acho que todas as outras respostas sugeridas podem não funcionar. O motivo é simplesmente porque, quando um aplicativo é criado pela primeira vez, todas as APIs necessárias são resolvidas no momento da compilação. Usando "ldd", você pode ver todas as dependências vinculadas estaticamente:

ldd /usr/lib/firefox/firefox
    linux-vdso.so.1 =>  (0x00007ffd5c5f0000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f727e708000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f727e500000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f727e1f8000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f727def0000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f727db28000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f727eb78000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f727d910000)

Mas em tempo de execução, o firefox também carregará muitas outras bibliotecas dinâmicas, por exemplo (para o firefox) existem muitas bibliotecas marcadas com "glib" carregadas (mesmo que vinculadas estaticamente não existam):

 /usr/lib/x86_64-linux-gnu/libdbus-glib-1.so.2.2.2
 /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0
 /usr/lib/x86_64-linux-gnu/libavahi-glib.so.1.0.2

Muitas vezes, você pode ver os nomes de uma versão sendo vinculados a outra versão. Por exemplo:

lrwxrwxrwx 1 root root     23 Dec 21  2014 libdbus-glib-1.so.2 -> libdbus-glib-1.so.2.2.2
-rw-r--r-- 1 root root 160832 Mar  1  2013 libdbus-glib-1.so.2.2.2

Portanto, significa que existe uma versão diferente de "bibliotecas" em um sistema - o que não é um problema, pois é o mesmo arquivo e fornecerá compatibilidade quando os aplicativos tiverem dependências de várias versões.

Portanto, no nível do sistema, todas as bibliotecas são quase interdependentes entre si, e apenas alterar a prioridade de carregamento das bibliotecas através da manipulação de LD_PRELOAD ou LD_LIBRARY_PATH não ajudará - mesmo que seja possível carregar, o tempo de execução ainda pode falhar.

http://lightofdawn.org/wiki/wiki.cgi/-wiki/NewAppsOnOldGlibc

A melhor alternativa é o chroot (mencionado brevemente por ER): mas para isso, você precisará recriar todo o ambiente em que a execução binária original - geralmente iniciando em / lib, / usr / lib /, / usr / lib / x86 etc. Você pode usar "Buildroot", ou YoctoProject, ou apenas tar de um ambiente Distro existente. (como Fedora / Suse etc).

Peter Teoh
fonte
0

Quando eu queria rodar um navegador chromium no Ubuntu preciso (glibc-2.15), recebi a mensagem (típica) "... libc.so.6: versão` GLIBC_2.19 'não encontrada ... ". Eu considerei o fato de que os arquivos não são necessários permanentemente, mas apenas para iniciar. Então, coletei os arquivos necessários para o navegador e o sudo e criei um ambiente mini-glibc-2.19-, iniciei o navegador e depois copiei os arquivos originais novamente. Os arquivos necessários estão na RAM e a glibc original é a mesma.

as root
the files (*-2.15.so) already exist 

mkdir -p /glibc-2.19/i386-linux-gnu

/glibc-2.19/ld-linux.so.2 -> /glibc-2.19/i386-linux-gnu/ld-2.19.so
/glibc-2.19/i386-linux-gnu/libc.so.6 -> libc-2.19.so
/glibc-2.19/i386-linux-gnu/libdl.so.2 -> libdl-2.19.so
/glibc-2.19/i386-linux-gnu/libpthread.so.0 -> libpthread-2.19.so

mkdir -p /glibc-2.15/i386-linux-gnu

/glibc-2.15/ld-linux.so.2 -> (/glibc-2.15/i386-linux-gnu/ld-2.15.so)
/glibc-2.15/i386-linux-gnu/libc.so.6 -> (libc-2.15.so)
/glibc-2.15/i386-linux-gnu/libdl.so.2 -> (libdl-2.15.so)
/glibc-2.15/i386-linux-gnu/libpthread.so.0 -> (libpthread-2.15.so)

o script para executar o navegador:

#!/bin/sh
sudo cp -r /glibc-2.19/* /lib
/path/to/the/browser &
sleep 1
sudo cp -r /glibc-2.15/* /lib
sudo rm -r /lib/i386-linux-gnu/*-2.19.so
dudu
fonte