Problema con l’uso della libreria curl con PHP

Spread the love
curl-logo
curl-logo

Da tempo sono perseguitato da un errore che si ripete (per quanto sospetto) ad ogni aggiornamento di php e che riguarda la libreria curl.

Sia l’invocazione da Apache che da client mi presentano un errore con questo tono:

$ php -r "curl_init();"
PHP Warning:  PHP Startup: Unable to load dynamic library 'curl.so' (tried: 
    /usr/lib/php/20210902/curl.so    (/usr/lib/php/20210902/curl.so: undefined symbol: curl_mime_addpart, version CURL_OPENSSL_4), 
    /usr/lib/php/20210902/curl.so.so (/usr/lib/php/20210902/curl.so.so: undefined symbol: curl_mime_addpart, version CURL_OPENSSL_4)
) in Unknown on line 0
PHP Fatal error:  Uncaught Error: Call to undefined function curl_init() in Command line code:1
Stack trace:
\#0 {main}
  thrown in Command line code on line 1

Un paio di volte ho pensato di aver risolvto il problema (vedi link in fondo al post) ma il problema è risaltato fuori al primo aggiornamento proposto da Canonical.

È stato stressante non trovare una soluzione in tutti questi anni perché non ne avevo il tempo. Solo che bisogna ad un certo punto venire ad un compromesso tra le cose da fare e lo stress che ci procura il nostro lavoro. Passato un certo segno, lo stress non è più tollerabile per cui le cose da fare passano assolutamente in seconda categoria di importanza.

Fondamentalmente l’articolo che mi trovavo sempre a leggere quando googlavo su questo argomento è quello riportato con Risorsa web [1] con la risposta illuminante dello sviluppatore finlandese:

And there’s your problem.

Toni Viemerö

Il riferimento che fa todeveni è al fatto che un aggiornamento manuale della libreria curl ha rotto quella di sistema.

Intanto mi assicuro che il file oggetto esista

$ stat /usr/lib/php/20210902/curl.so
  File: /usr/lib/php/20210902/curl.so
  Dim.: 117000      Blocchi: 232        Blocco di IO: 4096   file regolare
Device: 801h/2049d  Inode: 12327696    Coll.: 1
Accesso: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Accesso  : 2022-09-09 10:21:33.681311330 +0200
Modifica : 2022-08-15 11:40:11.000000000 +0200
Cambio   : 2022-09-02 15:54:45.221958306 +0200
Creazione: 2022-09-02 15:54:45.181957917 +0200

Il file c’è. Poi cerco se è stato agganciato per PHP. Per vedere questo devo vedere la directory dei mods-available del PHP (non quella di Apache!):

$ cd /etc/php/8.1/mods-available/
$ ll | grep curl
-rw-r--r-- 1 root root   68 dic 31  2021 curl.ini
$ $ cat curl.ini 
; configuration for php curl module
; priority=20
extension=curl.so

Sempre nell’articolo in cui todeveni spiega cos’è successo trovo questo comando che mi conferma che c’è un problema nella libreria:

$ ldd /usr/lib/php/20210902/curl.so 
/usr/lib/php/20210902/curl.so: 
   /usr/local/lib/libcurl.so.4: 
      no version information available (required by /usr/lib/php/20210902/curl.so)
   linux-vdso.so.1 (0x00007fffe63f1000)
...

Il comando ldd (List Dynamic Dependencies) stampa gli oggetti condivisi (librerie condivise) richiesti da ciascun programma o oggetto condiviso specificato nella riga di comando. Un esempio del suo utilizzo e output è il seguente:

marcob@jsbach:/usr/local/lib$ ldd /bin/ls
	linux-vdso.so.1 (0x00007ffe77541000)
	libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007fda76ff6000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fda76dce000)
	libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007fda76d32000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fda77069000)

Tornando al file /usr/lib/php/20210902/curl.so, se cerco le sue dipendenze trovo

marcob@jsbach:/etc/php$ ldd /usr/lib/php/20210902/curl.so 
/usr/lib/php/20210902/curl.so: /usr/local/lib/libcurl.so.4: no version information available (required by /usr/lib/php/20210902/curl.so)
	linux-vdso.so.1 (0x00007fffe63f1000)
	libcurl.so.4 => /usr/local/lib/libcurl.so.4 (0x00007f9a73200000)
...

Attenzione: trovo che il file nella libreria di PHP (/usr/lib/php/20210902/) dipende da un file posizionato nalla cartella /usr/local/lib/ e però è quest’ultimo ad avere qualche problema.

Provo a localizzare il file libcurl.so.4; ce n’è una marea:

$ locate libcurl.so.4
/home/marcob/.snap/auxdata/netcdf_natives/8.0.0/amd64/libcurl.so.4
/home/marcob/.snap/auxdata/netcdf_natives/8.0.5/amd64/libcurl.so.4
/home/marcob/.snap/auxdata/netcdf_natives/8.0.8/amd64/libcurl.so.4
/home/marcob/.snap/auxdata/netcdf_natives/8.0.9/amd64/libcurl.so.4
....
/usr/local/lib/libcurl.so.4 <-- questo è il file che vedo con ldd /usr/lib/php/20210902/curl.so 
/usr/local/lib/libcurl.so.4.4.0
/var/lib/flatpak/runtime/org.freedesktop.Platform/x86_64/18.08/1f7a5575c84c1df838ff07540cbc155e1eb78fee764860cbcbfab6d766328588/files/lib/x86_64-linux-gnu/libcurl.so.4
...

Però effettivamente il php punta a quello nella cartella /usr/local/lib/.

Attenzione: se cerco quali sono le librerie da da cui dipende il file in questa cartella non vedo nessun errore:

$ ldd /usr/local/lib/libcurl.so.4 | grep curl
$

ma non trovo neanche una dipendenza.

Ora però vediamo chi è davvero questo file so:

$ ls -l /usr/local/lib/libcurl.so.4
lrwxrwxrwx 1 root root 16 set  7 11:23 /usr/local/lib/libcurl.so.4 -> libcurl.so.4.4.0

Questo file non fa riferimento ad una libreria di sistema ma al file libcurl.so.4.4.0 che è stato buildato il 23/05/2017 e che ormai non è più allineato con quello ufficiale rilasciato da Canonical.

La soluzione arriva dalla Risorsa Web [4].

Dunque siamo alla soluzione, che comprende due operazioni

Rimuovo il file .so dalla /usr/lib/local

marcob@jsbach:/etc/php$ cd /usr/local/lib
marcob@jsbach:/usr/local/lib$ ll
totale 14368
drwxr-xr-x 10 root root     4096 set  7 11:23 ./
drwxr-xr-x 19 root root     4096 set 24  2021 ../
-rw-r--r--  1 root root     1957 set  2 17:07 curl.txt
-rw-r--r--  1 root root  1006444 mag 23  2017 libcurl.a
-rwxr-xr-x  1 root root     1042 mag 23  2017 libcurl.la*
lrwxrwxrwx  1 root root       16 set  7 11:23 libcurl.so.4 -> libcurl.so.4.4.0*
-rwxr-xr-x  1 root root   542272 mag 23  2017 libcurl.so.4.4.0*
-rw-r--r--  1 root root  4129514 gen 30  2018 libfilezilla.a
...
$ 
marcob@jsbach:/usr/local/lib$ sudo unlink libcurl.so.4
marcob@jsbach:/usr/local/lib$

E lo faccio puntare ad una libreria di sistema

$ sudo ln -s /usr/lib/x86_64-linux-gnu/libcurl.so.4 
$ ll libcurl.so.4 
lrwxrwxrwx  1 root root       38 set  9 11:35 libcurl.so.4 -> /usr/lib/x86_64-linux-gnu/libcurl.so.4

Praticamente sono passato da

libcurl.so.4 -> libcurl.so.4.4.0

a

libcurl.so.4 -> /usr/lib/x86_64-linux-gnu/libcurl.so.4

Ora, se ripeto un comando che dava l’errore:

marcob@jsbach:/usr/local/lib$ php -r "curl_init();"
marcob@jsbach:/usr/local/lib$

Ma qualsiasi comando con php dovrebbe darlo e non lo da più. In particolare quello che mi conferma che ora il modulo curl è caricato per il client:

marcob@jsbach:/usr/local/lib$ php -m | grep curl
curl

Faccio ripartire anche Apache:

marcob@jsbach:/usr/local/lib$ sudo apache2ctl restart
marcob@jsbach:/usr/local/lib$

E finalmente il comando phpinfo(); mi mostra il modulo caricato anche da Apache:

php curl, problema risolto
php curl, problema risolto

Risorse web

  1. Primo tentativo di fixare il problema
  2. Secondo tentativo
  3. Il file a cui punta il modulo PHP non è corretto (Todeveni)
  4. Una soluzione definitiva (spero, grazie a Chenjian e Scott Skiles)
  5. Pagina Linux man di ldd

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.