Unter Windows bearbeitetes Bash / Korn-Shell-Skript löst den Fehler '… ^ M: nicht gefunden' aus

8

Ich habe ein Bash-Skript in Windows mit Notepad ++ geschrieben.

cxStopAllServicesOnSERVER.sh

#!/usr/bin/bash
cd "/some/path"
echo "Hi. Logs can be found at "`pwd`"/cxStartStopLogger.log"
echo "["`date`"]*** STOPPING ALL SERVICES ON SERVER ***" >> "cxStartStopLogger.log"
exit

Nachdem ich es hochgeladen und die erforderlichen Dateiberechtigungen festgelegt hatte, habe ich versucht, es wie folgt auszuführen:

bash-3.00$ cat cxStopAllServicesOnSERVER.sh #Let's have a look at the code.
#!/usr/bin/bash
cd "/some/path/"
echo "Hi. Logs can be found at "`pwd`"/cxStartStopLogger.log"
echo "["`date`"]*** STOPPING ALL SERVICES ON SERVER ***" >> "cxStartStopLogger.log"

bash-3.00$ # Code and hashbang 'looks' correct, 
bash-3.00$ # if there is any issue with the format (EOL characters and such) 
bash-3.00$ # we cannot see it using cat.
bash-3.00$ 
bash-3.00$ sh cxStopAllServicesOnSERVER.sh
cxStopAllServicesOnSERVER.sh[2]: /some/path^M:  not found
Hi. Logs can be found at /some/path/cxStartStopLogger.log
bash-3.00$ # Note that ^M appears at the end of the line.

bash-3.00$ bash -x cxStopAllServicesOnSERVER.sh
+ cd $'/some/path\r'
: No such file or directory1.sh: line 2: cd: /some/path
++ pwd
' echo 'Hi. Logs can be found at /some/path/cxStartStopLogger.log
Hi. Logs can be found at /some/path/cxStartStopLogger.log
++ date
+ echo '[Sun' Nov 18 00:28:17 EST '2012]*** STOPPING ALL SERVICES ON SERVER ***'
bash-3.00$ # Note that '\r' return character appears at the end of the line.

Problem: Wenn ich den Code in Korn Shell ändere, habe ich das gleiche Problem. Es scheint, dass am Ende der Zeile ein falsches Zeichen hinzugefügt wird.

HINWEIS: Ich habe die Lösung gefunden und dieselbe als Antwort veröffentlicht. Fühlen Sie sich frei, es zu aktualisieren oder zu verbessern, um anderen Anfängern zu helfen, die möglicherweise mit dem gleichen Problem konfrontiert sind. Vielen Dank!

Kent Pawar
quelle

Antworten:

15

Nachdem ich mich in verschiedenen Foren und einigen Stack-Overflow-Posts umgesehen hatte, fand ich das Problem.

Hier ist eine Erklärung, um die Grundursache der Fehler besser zu verstehen und zu „sehen“.

Wenn Sie Code unter Windows schreiben, sollten Sie sich zunächst mit Notepad ++ ausrüsten. Meiner Meinung nach ist es im Grunde das Schweizer Taschenmesser der Texteditoren.

Um einen Blick auf die EOL-Zeichen (Zeilenende) und andere Steuerungssymbole zu werfen, gehen Sie wie folgt vor:

1.Öffnen Sie die Datei in Notepad ++.

Wählen Sie in der Menüleiste Ansicht> Symbol anzeigen> Alle Zeichen anzeigen

Sie sollten die Symbole nun wie folgt sehen: Screenshot von Notepad ++: Bearbeiten eines UNIX-Skripts unter Windows

Aha! Windows / MS-DOS verwendet CR + LF, um das Zeilenende anzuzeigen. Jetzt verwendet UNIX das LF-Zeichen, um den Zeilenabschluss (EOL-Zeichen) anzuzeigen.

2.1.Konvertieren Sie die Windows-EOL in UNIX-EOLs:

Wählen Sie BEARBEITEN> EOL-Konvertierung> UNIX-Format

Sie sollten so etwas sehen:

Screenshot von Notepad ++: EOL-Konvertierung in das UNIX-Format Dies erklärt, warum das Zeichen '\ r' am Ende der Zeile angehängt wurde. Dies liegt daran, dass UNIX das Zeichen '\ n' oder LF (Zeilenvorschub) als Zeilenabschluss- / EOL-Zeichen erkannt hat, das Zeichen '\ r' oder ^ M (Wagenrücklauf) jedoch ignoriert.

Wir können auch auf das EOL-Problem testen

bash-3.00$ head myScript.sh | cat -vet | head -1
#usr/bin/bash^M$
bash-3.00$ #We see that ^M, that is \r is found at the end of each line. 

2.2.Wenn Sie die Datei unter Windows von Windows in das UNIX EOL-Format konvertieren möchten, gibt es zwei Möglichkeiten, dies zu beheben:

$ dos2unix myScript.sh

oder

Verwenden Sie die von @Chris Down bereitgestellte Lösung wie folgt :

$ sed -i 's/\r$//' myScript.sh

Verweise:

  1. Weitere Informationen zur Leitungsbeendigung und zum Unterschied zwischen r und n finden Sie unter diesen Links.
Kent Pawar
quelle
1
Hervorragende Antwort! Ich denke, für kleine Dinge, die dabei bleiben pico, wird der Befehlszeileneditor die Lösung sein.
João Pimentel Ferreira
4

Ihr Skript enthält CRLF-Zeilenenden, während Unix LF-Zeilenenden verwendet. Das Folgende entfernt sie, wenn Sie GNU haben sed:

sed -i 's/\r$//' cxStopAllServicesOnSERVER.sh

Wenn Sie kein GNU haben sed, schreiben Sie in eine temporäre Datei und verschieben Sie sie über die alte Datei.

Nebenbei bemerkt, wenn Sie ein Skript mit aufrufen sh, überschreiben Sie den Shebang. Das ist wahrscheinlich nicht was du willst.

Chris Down
quelle
1
Das dos2unixTool ist auch einen Vorschlag wert.
Jordanm
@ Jordanm Yup. Ich habe es in meinem Beitrag unten behandelt.
Kent Pawar
Es ist kein Shebang definiert. !/muss in die erste Zeile eingefügt werden, um eine zu haben.
Wunder173
@ miracle173 Ich nahm an, dass dies eher ein Tippfehler als eine Absicht war.
Chris Down