Как я могу отследить скрипт, который дает мне «команда не найдена» сразу после входа в систему?

8

Когда я вхожу, у меня есть эти сообщения:

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

Совершенно очевидно, что это вызвано окончаниями строк в стиле Windows в некоторых сценариях запуска, поэтому мой вопрос: могу ли я отследить сценарий, который вызывает это и как?

Денис Саблуков
источник
2
Попробуйте посмотреть файлы .bashrc, .bash_profile и профиля в вашем домашнем каталоге, а также / etc / profile
Raman Sailopal,

Ответы:

14

Bash при запуске читает несколько различных файлов, даже в зависимости от того, как он запускается ( описание см. В руководстве ). Тогда есть такие вещи /etc/profile.d/, которые непосредственно не читаются оболочкой, но на них можно ссылаться из других файлов запуска во многих дистрибутивах.

Тебе придется пройти через все это, но, к счастью, ты можешь просто grepвернуться в карету. Попробуйте, например, что-то вроде:

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

См. Также Можно ли узнать, какие файлы устанавливаются / добавляются в переменные среды, и каков их приоритет? по аналогичной проблеме.

ilkkachu
источник
6
Еще одно место для поиска:~/.bash_aliases
Вейцзюнь Чжоу
1
Другой вариант заключается в использовании strace -e open your-shell, от ответа Stephane над здесь
Джефф Schaller
5

file (1) может быть полезен и здесь.

$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

Я вижу, что signupнужно удалить эти надоедливые окончания строк Windows CRLF.

Для прямой рекурсии, такой как /home/usernameвы, возможно, можно комбинировать с findи xargs(и, может быть, с grep):

$ 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
источник
3

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

$ head .bashrc
echo "Running bashrc"

Затем при входе в систему вы увидите что-то вроде этого:

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

На этом этапе вы можете сделать вывод, что (в приведенном выше примере) .bash_aliasesсодержит обидные окончания строки.

После того, как вы определили файл, но проблемные строки не выпрыгивают на вас, вы можете использовать тот же метод, чтобы отследить линию. Выведите сообщение наполовину через файл, затем через 3/4 или 1/4 в зависимости от вывода. Таким образом, вы можете отследить линию, в зависимости от того, отражается ли она до или после вашего эха.

user394
источник
Да, этот метод хорош, если можно быстро его автоматизировать, в противном случае он почти такой же, как просмотр всех этих файлов.
Денис Саблуков
1
Обратите внимание, что вы можете также сказать «завершено выполнение <файл>» в конце каждого. В этом случае это на самом деле не имеет значения, если только некоторые строки не имеют окончаний строки CR, но если вы ищете другую ошибку, она может быть в вашем .bashrc после вашего исходного кода .bash_aliases.
Бен Милвуд
1
Для тех, кто только учится отлаживать проблемы оболочки, или когда это не так просто, как поиск '\ r', ЭТОТ ответ стоит иметь в вашем наборе инструментов знаний. Я унаследовал сложную систему сборки, которая была крысиным гнездом переплетенных скриптов для создания удаленных сборок по SSH. Это был единственный способ размотать его и перенести в контейнеры Docker.
Скотт Прайв
1
Еще один общий совет - при работе со взаимосвязанными сценариями Bash следует помнить, где вы добавляете операторы echo и (что бы вы ни делали) часто тестировать. Если сценарий bash используется для вывода строк в STDOUT, и вы добавили операторы отладки в STDOUT, то вы, вероятно, сломали то, что отлаживали. Иногда ответом является использование команды «logger» для добавления информации / отладки в скрипт. В других случаях используйте STDERR, если это условие предупреждения.
Скотт Прайв
@DenisSablukov, если ваши файлы длинные и их просмотр занимает много времени, этот метод поможет вам быстрее сузить источник. Это не займет много времени в строке вверху и внизу 6 файлов.
user394
3

Я принимаю сложную часть этого вопроса так: «Как я могу найти возврат каретки в файле?» но "как я могу узнать, какие файлы использует мой bashrc?"

По второму вопросу вы можете попробовать что-то вроде этого:

bash -x .bashrc

Это покажет вам все, что делает ваш bashrc, включая все файлы, на которые он ссылается. Это шумно, но должно помочь вам отследить, какие файлы используются.

За исключением того, что мои (и многие другие) .bashrcфайлы выходят раньше, если не работают в интерактивном режиме, так что вы должны обманом пройти эту проверку:

bash -ix .bashrc

Здесь действует -iинтерактивный режим.

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

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

Я думаю, вы также можете захотеть сообщения об ошибках, так что-то вроде:

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

Если по какой-либо причине ничего из этого не сработало, я бы прибегнул к strace -e open bashчему-то подобному, чтобы найти каждый раз, когда какой-либо файл открывается вашим сеансом bash. Но это еще более тяжелое / шумное решение.

Бен Милвуд
источник