Почему правильная оболочка script дает обернутое/усеченное/поврежденное сообщение об ошибке?

У меня есть оболочка script с командой, которая кажется, что она должна работать, но вместо этого она терпит неудачу с нечетным завершенным/усеченным/поврежденным сообщением об ошибке. Пример:

$ ls -l myfile
-rw-r----- 1 me me 0 Aug  7 12:36 myfile
$ cat myscript 
ls -l myfile
$ bash myscript
: No such file or directory

Файл явно существует, но даже если я этого не сделал, это сообщение об ошибке, которое я обычно получаю:

$ ls -l idontexist
ls: cannot access idontexist: No such file or directory

Обратите внимание на то, как он включает имя инструмента ls, строку сообщения и имя файла, в то время как мой не работает.

Вот что я получу, если попытаюсь использовать mysql вместо этого. Сообщение об ошибке выглядит как завернутое, и теперь начинается с цитаты:

Command:  mysql -h myhost.example.com
Expected: ERROR 2005 (HY000): Unknown MySQL server host 'myhost.example.com' (0)
Actual:   ' (0) 2005 (HY000): Unknown MySQL server host 'myhost.example.com

И вот моя тривиальная команда ssh, которая должна работать или, по крайней мере, дать нормальное сообщение об ошибке, но которая вместо этого завернута, чтобы начать с двоеточия и заканчивается странным сбиванием:

Command:  ssh myhost
Expected: ssh: Could not resolve hostname myhost: Name or service not known
Actual:   : Name or service not knownname myhost

Почему это происходит и как его исправить?

Ответ 1

TL; DR: ваш script или данные имеют окончание строк CRLF в стиле Windows.

Преобразовать в стиль Unix, удалив возврат каретки.


Как проверить, вернёт ли мой script или данные каретки?

Они обнаруживаются как ^M в выводе cat -v yourscript:

$ cat -v myscript
ls -l myfile^M

Если ваш script не имеет их, ваши данные могут - особенно, если вы читаете файлы ini/csv или curl:

hostname=$(curl https://example.com/loginhost.txt)
ssh "$hostname"            # Shows strange error
echo "$hostname" | cat -v  # Shows myhost^M

Как удалить их?

Установите редактор, чтобы сохранить файл с окончанием строки Unix, ака "терминаторы строк" ​​или "концевые символы", и сохраните его.

Вы также можете удалить их из командной строки с помощью dos2unix yourscript или cat yourscript | tr -d '\r' > fixedscript.

Если вы нашли в своих данных, вы можете передать свой источник через tr -d '\r':

hostname=$(curl https://example.com/loginhost.txt | tr -d '\r')

Почему возврат каретки вызывает странные сообщения об ошибках?

Символ "возврат каретки", иначе CR или \r, заставляет курсор перемещаться к началу строки и продолжать печать оттуда. Другими словами, он начинает переписывать строку с самого начала. Вот почему они обманывают странно:

Intended:     ssh: Could not resolve hostname myhost\r: Name or service not known

Written:      ssh: Could not resolve hostname myhost\r
Overwritten:  : Name or service not known
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                  
Result:       : Name or service not knownname myhost