Comment puis-je suivre le script qui me donne «commande introuvable» juste après la connexion?

8

Lorsque je me connecte, j'ai ces messages:

-bash: $'\r' : command not found
-bash: $'\r' : command not found
-bash: $'\r' : command not found 

Il est assez clair que cela est causé par des fins de ligne de style Windows dans certains scripts de démarrage, donc ma question est: puis-je suivre le script qui cause cela et comment?

Denis Sablukov
la source
2
Essayez de regarder les fichiers .bashrc, .bash_profile et profile dans votre répertoire personnel ainsi que / etc / profile
Raman Sailopal

Réponses:

14

Bash lit un certain nombre de fichiers différents au démarrage, même en fonction de la façon dont il a démarré ( voir le manuel pour la description ). Ensuite, il y a des choses comme ça /etc/profile.d/qui ne sont pas directement lues par le shell, mais qui peuvent être référencées à partir des autres fichiers de démarrage dans de nombreuses distributions.

Vous devrez passer par tous ces éléments, mais heureusement, vous pouvez juste greppour le retour en calèche. Essayez par exemple quelque chose comme:

grep $'\r' ~/.bashrc ~/.profile ~/.bash_login ~/.bash_profile /etc/bash.bashrc /etc/profile /etc/profile.d/*

Voir aussi Est-il possible de savoir quels fichiers définissent / ajoutent aux variables d'environnement et leur ordre de priorité? pour un problème similaire.

ilkkachu
la source
6
Un autre endroit à rechercher:~/.bash_aliases
Weijun Zhou
1
Une autre option est d'utiliser strace -e open your-shell, d'après la réponse
Jeff Schaller
5

Le fichier (1) peut également être utile ici.

$file *

signin:                                     Python script, ASCII text
signup:                                     Python script, ASCII text, with CRLF line terminators
site_off.htm:                               XML 1.0 document, ASCII text
sitemaps:                                   directory

Je peux voir que signupces fins de ligne Windows CRLF doivent être supprimées.

Pour un récursif directement comme /home/usernamevous pourriez probablement le combiner avec findet xargs(et peut-être aussi un grep):

$ find . | xargs file | grep CR

./foo_data/V: ASCII text, with CR, LF line terminators
./foo_data/Y: ASCII text, with CR, LF line terminators
Kevin_Kinsey
la source
3

Une autre méthode consiste à prendre tous les scripts de démarrage mentionnés et à faire écho à une chaîne identifiant chacun au début de chacun.

$ head .bashrc
echo "Running bashrc"

Ensuite, lors de la connexion, vous verrez quelque chose comme ceci:

running bashrc
running bash_aliases
-bash: $'\r' : command not found
-bash: $'\r' : command not found
-bash: $'\r' : command not found 
running something_else

À ce stade, vous pouvez conclure que, (dans l'exemple ci-dessus) .bash_aliasescontient les fins de ligne incriminées.

Une fois que vous avez identifié le fichier, mais que les lignes problématiques ne vous sautent pas aux yeux, vous pouvez utiliser la même méthode pour retrouver la ligne. Faites écho à un message à mi-chemin dans le fichier, puis aux 3 / 4ème ou 1 / 4s, selon la sortie. De cette façon, vous pouvez suivre la ligne, selon qu'elle résonne avant ou après votre écho.

user394
la source
Oui, cette méthode est bonne si l'on peut rapidement l'automatiser, sinon c'est presque la même chose que de parcourir tous ces fichiers.
Denis Sablukov
1
Notez que vous voudrez peut-être également dire «terminé l'exécution de <fichier>» à la fin de chacun. Dans ce cas, cela n'a pas vraiment d'importance à moins que seules certaines lignes aient des fins de ligne CR, mais si vous recherchez une autre erreur, elle pourrait être dans votre .bashrc après avoir source .bash_aliases.
Ben Millwood
1
Pour quelqu'un qui apprend juste à déboguer des problèmes de shell, ou quand ce n'est pas aussi simple que de rechercher '\ r', CETTE réponse vaut la peine d'être contenue dans votre boîte à outils de connaissances. J'ai hérité d'un système de build complexe qui était un nid de scripts entrelacés pour faire des builds à distance via SSH. C'était le seul moyen de le dérouler et de le déplacer vers des conteneurs Docker.
Scott Prive
1
Une autre astuce générale - lorsque vous traitez avec des scripts Bash interdépendants, faites attention à l'endroit où vous ajoutez des instructions d'écho et (quoi que vous fassiez) testez fréquemment. Si un script bash est utilisé pour générer des chaînes vers STDOUT et que vous avez ajouté des instructions de débogage à STDOUT, vous avez probablement cassé la chose que vous déboguiez. Parfois, la réponse consiste à utiliser la commande "logger" pour ajouter des informations / débogage à un script. D'autres fois, utilisez STDERR, s'il s'agit d'une condition d'avertissement.
Scott Prive
@DenisSablukov si vos fichiers sont longs et que leur lecture prend du temps, cette méthode vous aidera à affiner la source plus rapidement. Il ne faut pas très longtemps pour une ligne vers le haut et le bas de 6 fichiers.
user394
3

Je considère que la partie difficile de cette question n'est pas "comment puis-je trouver les retours chariot dans un fichier?" mais "comment savoir quels fichiers mon bashrc utilise?"

Pour la deuxième question, vous pouvez essayer quelque chose comme ceci:

bash -x .bashrc

Cela vous montrera tout ce que fait votre bashrc, y compris tous les fichiers auxquels il se réfère. C'est bruyant, mais cela devrait vous aider à identifier les fichiers utilisés.

Sauf qu'en fait, mes .bashrcfichiers (et bien d'autres) se terminent tôt s'ils ne sont pas exécutés de manière interactive, vous devez donc le piéger pour réussir cette vérification:

bash -ix .bashrc

Voici le -imode interactif des forces.

Pour repérer uniquement les cas où vous sourcez un fichier, quelque chose comme ça fonctionne pour moi mais je ne peux pas promettre que l'expression régulière capture tout:

bash -ix .bashrc 2> >(grep -E '^\+* (\.|source)')

Je suppose que vous pourriez également vouloir les messages d'erreur, donc quelque chose comme:

bash -ix .bashrc 2> >(grep -E -e '^\+* (\.|source)' -e 'command not found')

Si pour une raison quelconque, cela ne fonctionnait pas, je recourrais à strace -e open bashquelque chose comme ça, pour trouver chaque fois qu'un fichier est ouvert par votre session bash. Mais c'est une solution encore plus lourde / bruyante.

Ben Millwood
la source