Скрипт оболочки работает при сохранении с помощью nano, но не работает при сохранении с помощью Notepad++

Скрипт оболочки работает при сохранении с помощью nano, но не работает при сохранении с помощью Notepad++

Когда я копирую свой bash-скрипт из Notepad++ в новый файл с помощью nano-редактора внутри SSH и сохраняю. Он отлично работает. (sh ./install).

Но если я сохраняю файл (точно такое же содержимое), загружаю на свой веб-сервер, скачиваю его с помощью Wget на той же машине. Я получаю синтаксические ошибки. Я проверил кодировку, и она, кажется, одинаковая. С тех пор я использовал множество кодировок символов, чтобы посмотреть, решит ли это проблему. Я также делаю файл исполняемым, как только загружаю его с помощью wget!

Файл работает нормально, и у меня нет ошибок при копировании и вставке с помощью nano. Есть идеи, что это может быть?

решение1

Я готов поспорить, что проблема связана с окончаниями строк. Вероятно, вы где-то в процессе работаете с не-*nix-машиной. Я также однажды столкнулся с проблемой, когда apache(работая на Linux) добавлял окончания строк в стиле Windows к загруженным текстовым файлам, так что вы можете видеть что-то похожее.

Для проверки возьмите загруженный файл и пропустите его через od. Если файл длинный, просто возьмите первые несколько строк:

head script.sh | od -c

Просмотрите вывод и проверьте, есть ли у вас что-то вроде этого:

f   o   o  \r  \n

Это \rвозврат каретки, и в Windows строки заканчиваются на , \r\nв отличие от \n*nix. Если выяснится, что проблема действительно была в этом, вы можете исправить файл, удалив возврат каретки:

sed -i 's/\r//g' script.sh

решение2

Как проницательно заметил @graeme, поскольку на сервере есть скрипт в обеих формах, вы можете выполнить простую операцию, diffчтобы определить, чем отличается рабочая версия от проблемной.

$ diff working.sh broken.sh

Вы также можете сделать сравнение бок о бок, например так:

$ diff -y working.sh broken.sh

Если скрипт не работает из-за какой-то опечатки, вы зачастую можете обнаружить ее, добавив переключатель -xв bash, что сделает его более подробным.

$ bash -x broken.sh

Вы также можете включить этот переключатель в шебанг ( #!/bin/bash) в верхней части ваших скриптов следующим образом:

#!/bin/bash -x

Окончания строк

Это часто является проблемой при перемещении файлов из Windows в системы Unix/Linux. Проблема связана с тем, как обозначаются концы строк на двух платформах. Вы можете прочитать об этом больше здесь, в Википедии, под названием:Новые строки.

сделать файл образца

$ echo -e "This is a file.\nThat I made on Unix.\n" > unixfile.txt

Как @terdon описал в своем ответе, вы можете использовать, sedчтобы убрать их, вы также можете часто использовать инструмент, который называется, dos2unixчтобы сделать то же самое. Вы можете использовать его одним из двух способов:

$ dos2unix unixfile.txt

или если вы не хотите перезаписывать существующий файл:

$ dos2unix -n oldfile.txt newfile.txt

При использовании того, что diffя упомянул ранее, вы получите примерно такой вывод при сравнении этих двух файлов:

$ diff -y unixfile.txt winfile.txt 
This is a couple                            |   This is a couple
of lines of sample                          |   of lines of sample
text.                                       |   text.

Вы не сможете различить различия, просто то, что они есть. Опять же, ответ @terdon показывает один из методов решения проблемы с помощью od. Конечно, вы можете использовать множество способов, чтобы выяснить, в чем дело.

Использование vim

с помощью filecmd.

$ file unixfile.txt
winfile.txt: ASCII text 

$ file winfile.txt 
unixfile.txt: ASCII text, with CRLF line terminators

Вышеизложенное подчеркивает проблему, что файл из Windows имеет CRLF (т.е. символы возврата каретки + перевода строки в конце строк). Эти символы 0x0D и 0x0A в шестнадцатеричном формате, снова см.Статья в Википедии о Newlinesесли вы хотите узнать об этом больше.

Вы также можете использовать vimдля просмотра проблемы:

$ vim winfile.txt

Вот небольшая последовательность, которая показывает, что нужно сделать, vimчтобы увидеть проблему. Символы CRLF обычно отображаются в Unix как ^M, это Ctrl+ M.

                                       сс из vim

Последовательность показывает мне повторное открытие файла, winfile.txtкак отформатированного файла Unix ( :e ++ff=unix). Это говорит vimне определять автоматически, что файл отформатирован для Windows, и поэтому он будет отображать ^Mсимволы завершения строки.

Связанный контент