Достаточно давно @andy_shev посоветовал мне уделить внимание переменным окружения, выставляемые при установлении ssh-соединения. Тогда мне это не показалось чем-то важным практически, но сегодня пришло время.
Проблема, с которой я столкнулся, оказалась странной. В Snow Leopard наконец-то Terminal.app стал нормально обрабатывать русские буквы в кодировке UTF-8, раньше же были проблемы с их отображением (они или “бились”, или же преобразовывались в набор восьмеричных чисел). Я вздохнул облегчённо - наконец-то я смог при работе в консоли комфортно писать по-русски.
Если же у вас до сих пор есть эта проблема, то прочитайте статью Папаши ”Отбивные из терминала”, и у вас всё получится. Правильная конфигурация такая:
Но когда я начал переносить свой сайт на второй ноутбук, я работал в основном с ним по ssh, и вот тут-то столкнулся с такой ситуацией - в локальном Terminal.app русские буквы работают идеально, а вот при заходе на такой же Mac OS X 10.6 по ssh вместо текста получаю набор восьмеричных чисел:
И это при том, что при работе через Screen Sharing с удалённым ноутбуком эта проблема не проявляется:
“Хммм…”, - сказал я и многозначительно почесал затылок. В чём же разница? А разница при всех прочих равных условиях (профайлы-то одинаковы) заключается в переменных окружения, которые выставляются при установке соединения по ssh. Идея намечена, проверяю.
Захожу через Screen Sharing, запускаю Terminal.app и сбрасываю переменные окружения в файл:
$ set > set.local
Захожу туда же через ssh:
$ set > set.ssh
Сравниваю и нахожу нужную мне переменную:
$ diff -u set.ssh set.local +LC_CTYPE=UTF-8
Опять захожу через ssh и пробую выставить её вручную
$ export LC_CTYPE=UTF-8
Ничего не меняется, значит настройка кодировки производится при запуске bash. Так, за это отвечает библиотека readline, а параметры bash, связанные с ней, можно посмотреть через “bind -v”. Повторяю процесс сравнения, в чём же разница:
(screen sharing) $ bind -v > bind.local (ssh) $ bind -v > bind.ssh $ diff -u bind.ssh bind.local -set convert-meta on +set convert-meta off -set input-meta off +set input-meta on -set meta-flag off +set meta-flag on -set output-meta off +set output-meta on
Нашёл. Чтобы эти параметры задействовать, их нужно поместить в файл ~/.inputrc и перезпустить bash:
$ cat ~/.inputrc set convert-meta off set input-meta on set meta-flag on set output-meta on
После повторного захода получаю именно то, что мне было нужно - русские буквы набираются без проблем.
Проблема-то решена, но сделаем ещё один шаг. Конфигурации-то одинаковы, почему же переменная LC_TYPE не передаётся через ssh? Смотрю man ssh и в секции ENVIRONMENT нахожу, что при соединении ssh выставляются только такие переменные окружения: DISPLAY, HOME, LOGNAME, MAIL, PATH, SSH_ASKPASS, SSH_AUTH_SOCK, SSH_CONNECTION, SSH_ORIGINAL_COMMAND, SSH_TTY, TZ, USER. И самое ценное:
Additionally, ssh reads ~/.ssh/environment, and adds lines of the format “VARNAME=value” to the envi-ronment environment if the file exists and users are allowed to change their environment.
Удаляю на удалённом хосте (тавтология) файл ~/.inputrc, делаю файл ~/.ssh/environment и правлю /etc/sshd_config:
$ rm ~/.inputrc $ vim ~/.ssh/environment LC_CTYPE=UTF-8 $ vim /etc/sshd_config ... PermitUserEnvironment yes ...
Перезапускать sshd не нужно. Захожу по ssh, и вижу, что переменная окружения LC_TYPE выставилась, и русские буквы работают.
Вот такие два метода решения проблемы я нашёл. Каким из них воспользоваться - выбирать вам. Мне нравится второй, но нужно знать и первый. Только что проделал трюк с PermitUserEnvironment на удалённом хосте с FreeBSD - и там тоже проблема с русскими буквами исчезла.
Update. Спасибо @Ivader за подсказку - более правильно вместо PermitUserEnvironment использовать AcceptEnv:
$ vim /etc/sshd_config AcceptEnv LANG LC_*
К сожалению, сейчас не могу попробовать этот рецепт на Mac OS X, но он должен работать.