OVH Cloud OVH Cloud

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

35 réponses
Avatar
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 \n
#---------------------------------------------

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

10 réponses

1 2 3 4
Avatar
Francois Lafont
Le 30/05/2012 20:57, Luc Habert a écrit :

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.



Merci pour les explications.

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.



Ok, effectivement, avoir un code de retour différent aurait été plus
logique. J'aurais gagné un peu de temps. :-)


--
François Lafont
Avatar
Arnaud Gomes-do-Vale
Francois Lafont writes:

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.



Oups, j'avais pas lu ça. En tout cas la solution, comme l'indique
Nicolas, est de différentier ton PATH en fonction de l'architecture de
la machine (genre PATH=/mon/repertoire/$(arch)/bin:$PATH). Avec un bémol
quand même, constaté à l'instant sur une machine à base d'AMD Geode :

:~% uname -a
Linux pousse 2.6.32-5-486 #1 Mon Oct 3 03:34:28 UTC 2011 i586 GNU/Linux
:~% arch
i586
:~% uname -i
unknown
:~% uname -p
unknown
:~% uname -m
i586

Rien qui indique i386. Grmpf.

--
Arnaud
http://blogs.glou.org/arnaud/
Avatar
Francois Lafont
Le 30/05/2012 21:09, Nicolas George a écrit :
Francois Lafont , dans le message
<4fc65b71$0$16491$, a écrit :
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.



Désolé. Des fois, comme j'ai tendance à être un peu bavard, j'ai peur de
faire un premier message très long que personne ne lit.


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.



Je n'y connais rien en C mais effectivement j'ai conscience que ma
demande (avoir un seul et unique binaire pour 32 bits et 64 bits) est
sans doute un infâme bricolage. Mais c'est pour un tout petit programme
et pour un objectif très modeste : faire en sorte qu'après le démarrage
des machines Debian (32 ou 64 bits donc) d'un réseau local, au moment où
la fenêtre de connexion s'affiche, le pavé numérique soit activé. Alors,
ça m'arrangerait d'avoir un seul binaire.

Mais, en admettant qu'il soit définitivement plus sage d'avoir un
binaire compilé sur un 32 bits et un autre compilé sur un 64 bits, je
pourrais faire ceci dans un script bash :

#------------------------------------------
function est_64_bits ()
{
...
}

if est_64_bits; then
# On lance le binaire version 64 bits.
/mnt/partage/numlock_active_64_bits
else
# Sinon, on est a priori sur un hôte 32 bits,
# alors on lance le binaire version 32 bits.
/mnt/partage/numlock_active_32_bits
fi
#------------------------------------------

Mais dans ce cas, que faudrait-il que je mette exactement dans le corps
de la fonction est_64_bits ?

Je pars du principe que sur le réseau local, il y a des machines
installées :

- soit avec un CD debian-6.0.5-amd64-netinst.iso
- soit avec un CD debian-6.0.5-i386-netinst.iso

A priori, pas d'autre architecture dans le réseau local.


--
François Lafont
Avatar
Luc.Habert.00__arjf
Francois Lafont :

$ 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
---------------------------------------------------------



C'est -lploum en un mot et pas -l ploum. Cela dit, il y a des chances que
gcc aie compris quand même et que le problème soit différent. Il y a une
blague avec l'ordre dans lequel mettre les libs, je ne me souviens jamais du
bon sens. Essaye le .c en premier et -lX11 en dernier.
Avatar
Alex F.
Bonjour,

Francois Lafont a écrit:

#------------------------------------------
function est_64_bits ()
{
...
}

if est_64_bits; then
# On lance le binaire version 64 bits.
/mnt/partage/numlock_active_64_bits
else
# Sinon, on est a priori sur un hôte 32 bits,
# alors on lance le binaire version 32 bits.
/mnt/partage/numlock_active_32_bits
fi
#------------------------------------------

Mais dans ce cas, que faudrait-il que je mette exactement dans le corps
de la fonction est_64_bits ?




Sans la fonction, un test de ce genre devrait suffire:

#!/bin/sh

if [ "$(uname -m)" = "x86_64" ]; then
/mnt/partage/numlock_active_64_bits
else
/mnt/partage/numlock_active_32_bits

fi

--
Alex
Avatar
Nicolas George
Luc Habert, dans le message <jq5tmv$v2c$, a écrit :
C'est -lploum en un mot et pas -l ploum.



Non, pas du tout.
Avatar
Nicolas George
Francois Lafont , dans le message
<4fc67367$0$6138$, a écrit :
$ gcc -static -l X11 -l xcb -l Xau -l Xdmcp numlock_active_i386.c
-o numlock_active_i386



Les bibliothèques doivent se mettre après les fichiers objets (ou les autres
bibliothèques) qui en dépendent.

En dynamique, on s'en fiche, on note le SONAME et on vérifie à la fin
qu'entre toutes les bibals tous les symboles sont résolus. Mais en statique,
il faut bien choper les bons fichier objets.

Mais je répète, lier statiquement n'est pas la bonne solution.
Avatar
Luc.Habert.00__arjf
Nicolas George :

C'est -lploum en un mot et pas -l ploum.



Non, pas du tout.



Gni? gcc a l'air de comprendre les deux, mais dans l'univers parallèle d'où
je viens, c'est -lploum la syntaxe historique.
Avatar
Nicolas George
Luc Habert, dans le message <jq5ued$v6q$, a écrit :
je viens, c'est -lploum la syntaxe historique.



Mais c'est -l truc la syntaxe standard, au moins depuis SUSv2.
Avatar
Francois Lafont
Le 30/05/2012 21:50, Luc Habert a écrit :

C'est -lploum en un mot et pas -l ploum. Cela dit, il y a des chances que
gcc aie compris quand même



Ok (et oui en effet gcc avait quand même compris qu'il fallait importer
les lib).

Il y a une
blague avec l'ordre dans lequel mettre les libs, je ne me souviens jamais du
bon sens. Essaye le .c en premier et -lX11 en dernier.



J'ai fait ça :

$ gcc -static numlock_active_i386.c -lX11 -lxcb -lXau -lXdmcp
-o numlock_active_i386

Du coup, j'ai eu une ribambelle d'erreur (beaucoup plus qu'avant), mais
plus une seule concernant XOpenDisplay. Du coup, ça m'a semblé être en
progrès et le message semblait indiquer qu'il manquait la lib "pthread".
Du coup, avec ça :

$ gcc -static numlock_active_i386.c -lX11 -lxcb -lXau -lXdmcp
-lpthread -o numlock_active_i386

Je n'obtiens plus qu'un warning dont j'ignore la signification :

/usr/lib/gcc/i486-linux-gnu/4.4.5/../../../../lib/libX11.a(xim_trans.o):
In function `_XimXTransSocketUNIXConnect':
(.text+0xcda): warning: Using 'getaddrinfo' in statically linked
applications requires at runtime the shared libraries from the glibc
version used for linking

Que dois-je faire ? Me manque-t-il encore une option de compilation ?
Une lib ?


--
François Lafont
1 2 3 4