Bash : « Aucun fichier ou dossier de ce type » alors que le fichier existe.. .

Le
Francois Lafont
Bonjour à tous,

Je suis confronté à un problème bien mystérieux que je vous soumets et
qui pourrait se résumer à ceci :

#
# cd /etc/se3/bin/
# ls -l n*
-rwx 1 root root 999994 30 mai 13:19 numlock_active_i386
# ./numlock_active_i386
-bash: ./numlock_active_i386: Aucun fichier ou dossier de ce type
# ./n*
-bash: ./numlock_active_i386: Aucun fichier ou dossier de ce type
# test -e ./numlock_active_i386 && echo Existe
Existe
#

Comme vous pouvez voir, je suis root et le fichier numlock_active_i386
existe bel et bien (la complétion automatique du nom avec la touche TAB
fonctionne très bien) et les droits sont corrects. Au départ, je me
disais que, peut-être, le nom du fichier contenait je ne sais quel
caractère non imprimable ou un truc dans le genre, mais ça ne semble pas
être le cas :

#
# ls n* | od -c
0000000 n u m l o c k _ a c t i v e _ i
0000020 3 8 6
#

La partition qui contient le répertoire /etc/se3/bin/ est montée tout
simplement monté sur / et j'ai :

#
# mount | grep 'on / '
/dev/sda5 on / type ext4 (rw,errors=remount-ro)
#

Bref, au niveau de la partition je n'ai pas l'impression que ça soit
particulièrement exotique.

Autre information : la machine est une Debian Squeeze 64 bits.

#
# uname -a
Linux smm1-03 2.6.32-5-amd64 #1 SMP Sun May 6 04:00:17 UTC 2012 x86_64
GNU/Linux
#

Enfin, pour être parfaitement complet, il faut que je vous parle du
fichier en question (numlock_active_i386) car c'est un peu particulier.
Peut-être que ça n'a rien à voir avec le problème mais dans le doute je
vous livre ce qui suit. C'est peut-être important.

Le fichier numlock_active_i386 est en fait le résultat d'une compilation
d'un tout petit programme en langage C. En l'occurrence, ce programme là :

//
#include <X11/XKBlib.h>
#include <X11/extensions/XKB.h>
#include <X11/keysym.h>

int main () {
Display *disp = XOpenDisplay(NULL);
if(disp == NULL) return 1;
unsigned int nl_mask = XkbKeysymToModifiers(disp, XK_Num_Lock);
XkbLockModifiers(disp, XkbUseCoreKbd, nl_mask, nl_mask);
XCloseDisplay(disp);
return 0;
}
//

Ce programme (trouvé sur le Web car je suis nul en C) permet de simuler
l'appui sur la touche "VerrNum" afin d'activer le pavé numérique. Sur
Debian, il y a le paquet « numlockx » qui fournit la commande du même
nom qui fait exactement cela. Mais lorsque la commande numlockx est
lancée *avant* qu'un utilisateur ouvre une session, c'est-à-dire
typiquement au moment où la fenêtre de connexion du display manager
s'affiche, celle-ci ne fonctionne pas (il semble que ça soit un bug
connu et signalé à plusieurs reprises). C'est pourquoi, après des
recherches sur le Web, j'étais tombé sur le programme ci-dessus qui lui
fonctionne aussi au moment de l'affichage de la fenêtre de connexion.

Sur une Squeeze 32 bits, je l'avais compilé comme ceci, sans erreur
(auparavant il a fallu que j'installe le paquet « libx11-dev »)

$ gcc -l X11 numlock_active_i386.c -o numlock_active_i386

Mais le souci, c'est que j'obtenais un fichier qui ne marchait que sur
des 32 bits et au niveau des bibliothèques partagées (attention je suis
nul en C alors mes explications sont sans doute un peu foireuses) ça
coinçait quand je cherchait à lancer le binaire sur une 64 bits. Du
coup, j'ai *essayé* de faire une compilation qui encapsule toutes les
bibliothèques partagées nécessaires dans le binaire afin que celui-ci
soit « standalone » et qu'il marche aussi bien sur un 32 bits qu'un 64
bits.n Du coup, sur ma Squeeze 32 bits, j'ai fait ça :

$ gcc -l X11 -c numlock_active_i386.c -o numlock_active_i386.o

Ensuite, j'ai tenté ça :

gcc numlock_active_i386.o -o numlock_active_i386

Et en fonction des messages d'erreur un peu évocateur, j'ai ajouté des
bibliothèques jusqu'à que ceci me donne une compilation sans erreur :

gcc numlock_active_i386.o /usr/lib/libX11.a /usr/lib/libxcb.a
/usr/lib/libXau.a /usr/lib/libXdmcp.a -o numlock_active_i386

Voilà, j'espère avoir donné toutes les informations nécessaires. Si ce
n'est pas le cas, n'hésitez pas à me demander.

Bref, pourquoi diable le shell me dit que le fichier n'existe pas alors
que celui-ci existe ?

Merci d'avance pour votre aide.



--
François Lafont
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 4
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Nicolas George
Le #24522041
Francois Lafont , dans le message
-rwx------ 1 root root 999994 30 mai 13:19 numlock_active_i386
# ./numlock_active_i386
-bash: ./numlock_active_i386: Aucun fichier ou dossier de ce type



Ultra-classique : chargeur dynamique ELF non trouvé.
Francois Lafont
Le #24522021
Le 30/05/2012 19:23, Nicolas George a écrit :
Francois Lafont , dans le message
-rwx------ 1 root root 999994 30 mai 13:19 numlock_active_i386
# ./numlock_active_i386
-bash: ./numlock_active_i386: Aucun fichier ou dossier de ce type



Ultra-classique : chargeur dynamique ELF non trouvé.



Ok. Attention, pour moi ce n'est pas classique, c'est très nouveau. Je
n'y connais pas grand chose en C. :-)

Si je comprends bien, là où le bât blesse sans dans la façon dont j'ai
compilé mon source. Il n'est pas « standalone » à 100%, c'est ça ? Du
coup, il cherche à consulté une bibliothèque partagée sur le système
hôte et ne la trouve pas, c'est ça ?

Mais dans ce cas, comment dois-je faire au niveau de la compilation pour
rendre mon binaire 100% autonome afin qu'il marche sans erreur sur une
architecture 32 bits comme sur une architecture 64 bits ?

--
François Lafont
Philippe Naudin
Le #24522011
Le mer. 30 mai 2012 18:55:15 CEST, Francois Lafont a écrit:

Bonjour à tous,

...
Mais le souci, c'est que j'obtenais un fichier qui ne marchait que sur
des 32 bits et au niveau des bibliothèques partagées (attention je su is
nul en C alors mes explications sont sans doute un peu foireuses) ça
coinçait quand je cherchait à lancer le binaire sur une 64 bits. Du
coup, j'ai *essayé* de faire une compilation qui encapsule toutes les
bibliothèques partagées nécessaires dans le binaire afin que celui- ci
soit « standalone » et qu'il marche aussi bien sur un 32 bits qu'un 64
bits.n Du coup, sur ma Squeeze 32 bits, j'ai fait ça :

$ gcc -l X11 -c numlock_active_i386.c -o numlock_active_i386.o
...



Tu te compliques singulièrement la vie :
$ gcc -l X11 numlock_active_i386.c -o numlock_active_i386
$ file numlock_active_i386
numlock_active_i386: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV ), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), not stripped
$ ./numlock_active_i386
... aucun problème. Compile directement sur ta machine 64 bits.

--
Philippe Naudin
Francois Lafont
Le #24522091
Le 30/05/2012 19:33, Philippe Naudin a écrit :

$ gcc -l X11 -c numlock_active_i386.c -o numlock_active_i386.o
...



Tu te compliques singulièrement la vie :
$ gcc -l X11 numlock_active_i386.c -o numlock_active_i386
$ file numlock_active_i386
numlock_active_i386: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), not stripped
$ ./numlock_active_i386
... aucun problème. Compile directement sur ta machine 64 bits.



Oui, mais si je fais cela, j'aurai un binaire qui marche bien sur du 64
bits mais pas sur 32 bits, non ? Or, ce que je voudrais, c'est un unique
binaire qui marche sur les deux architectures, car en fait ce binaire se
trouve sur un partage réseau et il peut être exécuté par des machines 32
ou 64 bits. C'est pourquoi j'aimerais bien pouvoir créer un binaire 32
bits 100% « standalone » qui du coup fonctionnera sur du 64 bits,
indépendamment de ce qui pourra être installé ou non sur le système hôte.

Est-ce que cela est possible au moins (sachant que mon programme est
assez « petit ») ?

--
François Lafont
Luc.Habert.00__arjf
Le #24522351
Francois Lafont :

Mais dans ce cas, comment dois-je faire au niveau de la compilation pour
rendre mon binaire 100% autonome afin qu'il marche sans erreur sur une
architecture 32 bits comme sur une architecture 64 bits ?



Il faut compiler avec l'option -static. Tu peux alors spécifier les libs
avec -lploum au lieu de /.../libploum.a. Il faut les spécifier toutes
explicitement, parce qu'un .a ne contient pas de liste de dépendances. Il en
faudra probablement quelques unes de plus.
Luc.Habert.00__arjf
Le #24522451
Nicolas George :

Ultra-classique : chargeur dynamique ELF non trouvé.



Pour détailler: un exe au format ELF (standard sur tous les unix de nos
jours), si il dépend de libs dynamiques contient dans un header un chemin
d'accès style /lib/ld.so qui pointe vers un exécutable. Lorsque le noyau
exécute un exe ELF, il regarde le header, et si il y trouve un tel chemin
d'accès, il exécute en fait le ld.so pointé, en lui transmettant d'une
manière ou d'une autre l'exe elf de départ.

Le ld.so fonctionne alors au départ comme un interpréteur: il charge à la
main en mémoire le contenu de l'exe, va chercher les libs dont il dépend,
les charge, et récursivement. Quand il a fini, il laisse la main au code
contenu dans l'exe.

Ce no such file or directory ultraconfusant (on s'est tous arraché les
cheveux une fois à cause de lui; c'est un rite de passage) est envoyé par le
noyau lorsqu'il échoue à trouver le ld.so et non l'exe lui-même. Mais il
renvoie la même erreur que si il n'avait pas trouvé l'exe (ça n'aurait pas
été stupide de créer un code d'erreur supplémentaire, mais ça n'a pas été
fait), donc le shell pond le même message d'erreur.
Nicolas George
Le #24522521
Francois Lafont , dans le message
Si je comprends bien, là où le bât blesse sans dans la façon dont j'ai
compilé mon source. Il n'est pas « standalone » à 100%, c'est ça ? Du



Oui, mais ce n'est pas fondamentalement un problème, la liaison dynamique,
c'est très bien

Mais dans ce cas, comment dois-je faire au niveau de la compilation pour
rendre mon binaire 100% autonome afin qu'il marche sans erreur sur une
architecture 32 bits comme sur une architecture 64 bits ?



Rien, ce n'est pas une bonne idée. La bonne solution, c'est d'installer sur
ta machine 64 bits les bibliothèques de base permettant d'exécuter les
programmes 32 bits communs.
Nicolas George
Le #24522511
Francois Lafont , dans le message
Oui, mais si je fais cela, j'aurai un binaire qui marche bien sur du 64
bits mais pas sur 32 bits, non ?



Oui.

Or, ce que je voudrais, c'est un unique
binaire qui marche sur les deux architectures,



Tu aurais dû préciser cet élément dès le début.

car en fait ce binaire se
trouve sur un partage réseau et il peut être exécuté par des machines 32
ou 64 bits.



Tu y arriveras pour les cas très simples, mais au delà ça ne passera plus,
donc tu devrais songer à préparer une architecture qui te permettra d'avoir
des binaires des deux sortes disponibles.
Francois Lafont
Le #24522631
Le 30/05/2012 20:45, Luc Habert a écrit :

Mais dans ce cas, comment dois-je faire au niveau de la compilation pour
rendre mon binaire 100% autonome afin qu'il marche sans erreur sur une
architecture 32 bits comme sur une architecture 64 bits ?



Il faut compiler avec l'option -static. Tu peux alors spécifier les libs
avec -lploum au lieu de /.../libploum.a. Il faut les spécifier toutes
explicitement, parce qu'un .a ne contient pas de liste de dépendances. Il en
faudra probablement quelques unes de plus.



C'est sans doute le cas, car si je fais :

$ gcc -static -l X11 -l xcb -l Xau -l Xdmcp numlock_active_i386.c
-o numlock_active_i386

J'obtiens en retour ceci :

---------------------------------------------------------
/tmp/ccy5eb1F.o: In function `main':
numlock_active_i386.c:(.text+0x11): undefined reference to `XOpenDisplay'
numlock_active_i386.c:(.text+0x37): undefined reference to
`XkbKeysymToModifiers'
numlock_active_i386.c:(.text+0x5f): undefined reference to
`XkbLockModifiers'
numlock_active_i386.c:(.text+0x6b): undefined reference to `XCloseDisplay'
collect2: ld returned 1 exit status
---------------------------------------------------------

Quand j'utilisais le coup des « /.../libploum.a », avec ce genre de
message, j'arrivais toujours à trouver la lib à ajouter dans /usr/lib/
(car les noms étaient dérivés du nom de la lib). Mais, là je coince. Je
pensais que XOpenDisplay faisait partie de la lib X11 que j'ai incluse
dans la compilation avec l'option « -l X11 ». Mais apparemment, ça ne
suffit pas car pour lui XOpenDisplay est indéfini.

Mais alors comment savoir ce qu'il faut que j'ajoute comme option « -l
truc » pour que ce XOpenDisplay soit défini ?


--
François Lafont
Arnaud Gomes-do-Vale
Le #24522621
Nicolas George
Mais dans ce cas, comment dois-je faire au niveau de la compilation pour
rendre mon binaire 100% autonome afin qu'il marche sans erreur sur une
architecture 32 bits comme sur une architecture 64 bits ?



Rien, ce n'est pas une bonne idée. La bonne solution, c'est d'installer sur
ta machine 64 bits les bibliothèques de base permettant d'exécuter les
programmes 32 bits communs.



Non, la bonne solution, c'est de compiler en 64 bits. Les couches de
compatibilité binaires, ça marche ou pas, et ça expose à tout un tas de
problèmes un peu bizarres (la preuve). Et en plus c'est pénible à gérer
en termes d'admin système.

--
Arnaud
http://blogs.glou.org/arnaud/
Publicité
Poster une réponse
Anonyme