Когда я копирую свой 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
с помощью file
cmd.
$ 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.
Последовательность показывает мне повторное открытие файла, winfile.txt
как отформатированного файла Unix ( :e ++ff=unix
). Это говорит vim
не определять автоматически, что файл отформатирован для Windows, и поэтому он будет отображать ^M
символы завершения строки.