Wie kann ich ein Skript verfolgen, das mir direkt nach der Anmeldung den Befehl "Befehl nicht gefunden" gibt?

8

Wenn ich mich anmelde, habe ich folgende Meldungen:

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

Es ist ziemlich klar, dass dies durch Zeilenenden im Windows-Stil in einigen Startskripten verursacht wird. Meine Frage lautet also: Kann ich ein Skript verfolgen, das dies verursacht, und wie?

Denis Sablukov
quelle
2
Schauen Sie sich die .bashrc-, .bash_profile- und Profildateien in Ihrem Home-Verzeichnis sowie / etc / profile an
Raman Sailopal

Antworten:

14

Bash liest beim Start eine Reihe verschiedener Dateien, auch je nachdem, wie sie gestartet wurden (eine Beschreibung finden Sie im Handbuch ). Dann gibt es /etc/profile.d/solche Dinge , die nicht direkt von der Shell gelesen werden, sondern in vielen Distributionen aus den anderen Startdateien referenziert werden können.

Sie müssen all das durchgehen, aber zum Glück können Sie nur grepfür den Wagenrücklauf. Versuchen Sie zB etwas wie:

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

Siehe auch Ist es möglich herauszufinden, welche Dateien Umgebungsvariablen setzen / hinzufügen und in welcher Reihenfolge sie Vorrang haben? für ein ähnliches Problem.

ilkkachu
quelle
6
Ein weiterer Ort zu suchen:~/.bash_aliases
Weijun Zhou
1
Eine andere Möglichkeit ist strace -e open your-shell, aus Stéphanes Antwort hier zu verwenden
Jeff Schaller
5

Datei (1) kann auch hier hilfreich sein.

$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

Ich kann sehen, dass signupdiese lästigen Windows CRLF-Zeilenenden entfernt werden müssen.

Für eine rekursive direkt wie /home/usernameSie wahrscheinlich mit findund xargs(und vielleicht auch mit einem grep) kombinieren könnten :

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

Eine andere Methode besteht darin, alle genannten Startskripte zu verwenden und eine Zeichenfolge zu wiederholen, die jedes am Anfang jedes Skripts identifiziert.

$ head .bashrc
echo "Running bashrc"

Beim Anmelden sehen Sie dann Folgendes:

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

An diesem Punkt können Sie schließen, dass (im obigen Beispiel) .bash_aliasesdie fehlerhaften Zeilenenden enthält.

Sobald Sie die Datei identifiziert haben, aber die Problemzeilen nicht herausspringen, können Sie dieselbe Methode verwenden, um die Zeile aufzuspüren. Echo eine Nachricht zur Hälfte der Datei, dann 3/4 oder 1/4 durch, je nach Ausgabe. Auf diese Weise können Sie die Linie aufspüren, je nachdem, ob sie vor oder nach Ihrem Echo wiedergegeben wird.

user394
quelle
Ja, diese Methode ist gut, wenn man sie schnell automatisieren kann, ansonsten ist sie fast das gleiche wie das Durchsuchen all dieser Dateien.
Denis Sablukov
1
Beachten Sie, dass Sie am Ende jeder Datei auch "Fertig mit der Ausführung von <Datei>" sagen möchten. In diesem Fall spielt es keine Rolle, es sei denn, nur einige der Zeilen haben CR-Zeilenenden. Wenn Sie jedoch nach einem anderen Fehler suchen, kann dieser in Ihrer .bashrc-Datei enthalten sein, nachdem Sie .bash_aliases als Quelle angegeben haben.
Ben Millwood
1
Für jemanden, der gerade das Debuggen von Shell-Problemen lernt oder wenn es nicht so einfach ist, nach '\ r' zu suchen, lohnt es sich, DIESE Antwort in Ihrer Wissens-Toolbox zu haben. Ich habe ein komplexes Build-System geerbt, das ein Rattennest aus verschlungenen Skripten war, um Remote-Builds über SSH durchzuführen. Dies war die einzige Möglichkeit, es abzuwickeln und in Docker-Container zu verschieben.
Scott Prive
Ein weiterer allgemeiner Tipp: Achten Sie beim Umgang mit Bash-Skripten darauf, wo Sie Echoanweisungen hinzufügen und (was auch immer Sie tun) häufig testen. Wenn ein Bash-Skript zum Ausgeben von Zeichenfolgen an STDOUT verwendet wird und Sie STDOUT Debug-Anweisungen hinzugefügt haben, haben Sie wahrscheinlich das, was Sie debuggt haben, beschädigt. Manchmal besteht die Antwort darin, den Befehl "logger" zu verwenden, um einem Skript info / debug hinzuzufügen. In anderen Fällen verwenden Sie STDERR, wenn es sich um eine Warnbedingung handelt.
Scott Prive
@DenisSablukov Wenn Ihre Dateien lang sind und das Durchsuchen eine Weile dauert, können Sie mit dieser Methode die Quelle schneller eingrenzen. Es dauert nicht lange, bis eine Zeile oben und unten in 6 Dateien angezeigt wird.
user394
3

Ich nehme den schwierigen Teil dieser Frage als nicht "Wo finde ich Wagenrückläufe in einer Datei?" aber "wie kann ich herausfinden, welche Dateien mein bashrc verwendet?"

Bei der zweiten Frage können Sie Folgendes ausprobieren:

bash -x .bashrc

Dies zeigt Ihnen alles , was Ihr bashrc tut, einschließlich aller Dateien, auf die es verweist. Es ist laut, soll Ihnen aber dabei helfen, herauszufinden, welche Dateien verwendet werden.

Außer in der Tat werden meine (und viele andere) .bashrcDateien vorzeitig beendet, wenn sie nicht interaktiv ausgeführt werden. Sie müssen sie also dazu verleiten, diese Prüfung zu bestehen:

bash -ix .bashrc

Hier -ierzwingt der interaktive Modus.

Um nur die Fälle herauszufinden, in denen Sie eine Datei als Quelle verwenden, funktioniert so etwas für mich, aber ich kann nicht versprechen, dass der Regex alles abfängt:

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

Ich denke, Sie möchten vielleicht auch die Fehlermeldungen, also so etwas wie:

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

Wenn aus irgendeinem Grund nichts davon funktioniert, würde ich auf strace -e open bashoder so etwas zurückgreifen , um jedes Mal zu finden, wenn eine Datei von Ihrer Bash-Sitzung geöffnet wird. Aber das ist eine noch schwerere / lautere Lösung.

Ben Millwood
quelle