Pull to refresh

Comments 103

Уж лучше PATH поправить, чем систем32 загаживать.
А чем Cygwin не устроил? Он предоставляет даже привычное дерево ФС.
Пробовал Cygwin, не понравилось, т.к. нужно тогда вседа использовать именно его шелл.
Остановился на GnuWin + Far.
Почему всегда-то? Все эти программы и в cmd работают, разве что с запуском символьных ссылок есть проблемы.
Если в PATH добавить, то могут быть проблемы из-за его find. ЕМНИП, Qt не соберется в таком случае.
+1 к Cygwin, все что надо есть, mintty в качестве терминала, шелл ставим любой, я настраивал zsh с плюшками, виндовому cmd даже и не снилось
А мне больше ConEmu нравится. Юниксовые утилиты конечно отдельно, тут чисто терминал.
Мне эта замечательная программа тоже очень понравилась. Тем, кто еще ее не попробовал, рекомендую прочитать этот топик: habrahabr.ru/post/164687/

Консолька не только имеет поддержку множества вкладок, но и отлично кастомизируется. Лично я настроил ее в стиле консоли из Quake, т.е. окно выезжает сверху экрана по нажатию «Ctrl + ~». На мой взгляд это не только эффектно выглядит, но и очень удобно в использовании. В качестве юниксовых утилит использую MSYS, который поставляется с MinGW.

Превьюшка:
глючит он ужасно и давно не поддерживается.
Кто не поддерживается? MSYS? Насколько я знаю, ведутся работы над MSYS2 в котором, в частности, юникод обещают.
ConEmu. Вы за веткой-то следите вообще?
Я ее только что прочитал. И не понятно, зачем вы бред пишете. Последний билд ConEmu был выложен 5 дней назад.
Ох я идиот, я с C2 перепутал…
Её запуск telnet уводит в ступор. И я, к несчастью, знаю, почему. На MSDN об этом ничего нет, и даже не пытайтесь искать.

На самом деле, терминал в windows — та ещё хрень. Недавно пришлось столкнуться с переадресацией консоли хоть куда-нибудь — выяснилось, что делать это можно по-хорошему только в анонимный пайп. А для анонимных пайпов не реализовано overlapped i\o — поэтому читать и писать можно только синхронно c помощью чудесной функции ReadFile.

Вы скажете — очевидно же, делай чтение в отдельном потоке! Но нифига — функция ReadFile не принимает НИКАКИХ параметров, касающихся таймаутов, а системные таймауты в случае чтения из потока не работают. Более того, ReadFile покорно ждет наполнения буфера, и #10#13 для неё — не аргумент для flush. Так что в выводе приходится отключать буферизацию. Но это не отменяет того, что ReadFile при ожидании ввода просто виснет.

Т.е. поток, зависший в readfile можно убить только через TerminateThread, и никаких тебе возможностей для корректного завершения — соответственно получаем memory leak в чистом виде.

Вы спросите — а почему нельзя грохнуть child process, чтобы readfile упал с broken pipe? Правильный ответ — он не упадёт, а будет висеть. При трассировке выяснилось, что там внутри есть WaitForSingleObject(hRead, INFINITE), соответственно при досрочной инвалидации hRead мы хрен чего дождемся. Эта проблема таинственным образом выскакивает, когда на один процесс порождено больше одного потока, перехватывающего stdi\o\err — readfile отпускает только после того, как прибиты все «перехваченные» дочерние процессы.

Таким образом, мы практически никак не можем завершить child process таким образом, чтобы потом нормально убраться в порожденном потоке. Но голь на выдумки хитра. Путём хитрой игры с хэндлами можно при вызове CreateProcess перенаправить stdi\o\err в три пары именованных пайпов — по одному на чтение\запись для stdin, stdout и stderr. Дальше мы можем делать с ними Overlapped i\o, а чтобы не грузить процессор в цикле ожидания — при ERROR_IO_PENDING использовать WaitForMultipleObjects для хэндлов всех шести именованных пайпов с timeout, например, в тысячу.

А дальше смотрим в WaitResult — и если там есть WAIT_TIMEOUT — проверяем существование процесса с PID из PROCESSINFORMATION, который мы заботливо сохранили после запуска CreateProcess. Ну и всякий там broken pipe тоже перехватить можно. Так что о том, что у нас что-то сломалось, приложение гарантированно узнает через одну секунду, которая пришла вторым параметром в WaitForMultipleObjects.

А дальше был секс с буферизацией и синхронизацией пайпов для ввода и вывода. Но это уже другая песня.

Таким нехитрым образом мы всего-то асинхронно перенаправили консоль. Задачка, для которой были тысячи готовых решений в интернетах в три строчки, на деле оказалась геморроем длиной в пару дней.

А мораль проста — держитесь от редиректоров виндоконсоли подальше. Она настолько крива, что никакими прямыми руками это не исправишь — где-нибудь, да вылезет косяк. Да что там говорить, даже собственный telnet-сервер от MS не в состоянии её корректно редиректнуть.
Даю подсказку, корректный редирект консоли можно сделать средством:
— запускаем процесс через CreateProcess
— получаем HANDLE процесса
— делаем инджект через Detours или другую библиотеку
— Список того что нужно хукать — msdn.microsoft.com/en-us/library/windows/desktop/ms682073%28v=vs.85%29.aspx

В этом случае Вы 100% сможете перехватить консоль почти любой программы.
Также обернуть вызовы этих функций в буферы :)
И не забывайте что хуки для x86/x64 будут разные — разника в call conversion
Была такая мысль, но стояла задача не эмулировать полноценную консоль, а просто перехватить вывод. Банальный редирект stdout, который в этих ваших линуксах на баше делается одним символом

Ну и навскидку через пайпы всё-таки попроще получилось. А что мешало майкрософту сделать консоль виртуальной, с подключаемым терминалом, для меня до сих пор загадка.
дело в том что MS и не планировала делать функционал консоли подобным образом.
Изначально она пошла со времен 3.11, после в 95/98/2000 тоже запускалась по MSDOS принципу.
А вот уже в новых ОС — весь этот фунционал был заменен через Console API.
В Linux есть псевдотерминалы — да и вообще UNIX-way подразумевает «все есть файлы» — поэтому и работа в этом плане проще.
И я тут ещё подумал — если из этой консоли будет запущен процесс, работающий с уже выделенной консолью напрямую через API (тот же Telnet), то его функции не будут похучены, и соответственно ничего мы не увидим.
Т.е. хучить придётся не конкретное приложение, а пилить system-wide hook, срабатывающий по дескриптору конкретной консоли.
если новые процессы не создают новые экземпляры консоли и пишут все в один дескриптор — то можно обойтись и одним хуком.
Да ничего подобного. Родительское приложение (в частности, cmd.exe) висит в WaitForSingleObject в ожидании окончания работы запущенного процесса (в частности, telnet.exe). В таком подвешенном состоянии оно знать не знает ни о каких чтениях\записях в дескриптор. А телнет, в свою очередь, штука интерактивная, и ждет ввода от юзера. В итоге в консоли тишина. Собственно, насколько я понимаю, именно это явление мы и наблюдаем при попытке запустить telnet в предложенном выше редиректоре.

Собственно Я описал Выше — если новое приложения запускает AllocConsole — то вот тогда оно не будет хорошо работать :)
Её запуск telnet уводит в ступор. И я, к несчастью, знаю, почему. На MSDN об этом ничего нет, и даже не пытайтесь искать.

Неправда. «Ступор» может возникать только в Win7 и только в том случае, если вы отказались включить инжекты. Включите флажок и telnet «внезапно» заработает в ConEmu.

Кстати, проблема не из-за ReadFile, тайматутов пайпов и прочего…
Это последствия глюка 7-ки работы с буферами (CreateConsoleScreenBuffer), кому интересно — могут почитать подробнее.
Я использую также ConEmu в связке с MinTTY + Cygwin. Получается практически полноценный линуксовый терминал с табами. А если нужен настоящий линукс, то открываю таб с автологином в виртуалку: META+N -> выпадает список тасков, выбираю ssh_local (в этом таске прописано: C:\Cygwin\bin\mintty.exe C:\Cygwin\bin\bash.exe -c «ssh user@localhost» ). В итоге сразу получаем таб в ConEmu с линуксовым окружением.
Только есть ещё маленький недостаток: при переключении на ConEmu фокус ввода получает само окно, а не таб. Соответственно в MinTTY курсор показывается как неактивный
Специально для таких как вы была сделана опция «Focus in child windows».
Эта опция у меня включена вообще-то, но эффекта нет, к сожалению.
Аааа, нашел. Чего раньше не жаловались?
Пока можно хоткей использовать «Set focus to child GUI application» (вкладка Keys & Macro)
Стеснялся. И так хорошая штука!

Хоткей попробовал: нужно каждый раз нажимать (это не удобно). Нашёл два тикета на code.google.com: 888 и 943. Они вроде бы как связаны с этой проблемой, но об опции в настройках ни слова.
Может создать там issue?
Спасибо! Уже скачал — работает шикарно!
установка mingw msys даст нормальный терминал с практически полным набором утилит
Я за время свою сборку уже собрал, а все началось с гита, потом к нему в bin переехали все утилиты которых не хватало (например wget)
Чем? Не холивара ради, но если вы смотрели на PowerShell, и он чем-то не нравится, хотелось бы знать, чем именно.
тем, что он _слишком_ фичаст для шелла?
Это, по-вашему, хорошая аналогия — сравнивать командную строку и графический загромождённый интерфейс? Вы неиспользуемые вами возможности каким суперменским зрением видите в командной строке?
я с PowerShell слишком плохо знаком, чтоб судить о нем. PowerShell наверняка не уступает инструментам мира Unix по возможностям, но дело в том, что линуксовыми тулзами я уже умею пользоваться а PowerShell'у нужно будет учиться. Ну и чисто субъективно мне нравятся концепции лежащие в основе Unix-Way: все потоки данных — это текст, одна задача — одна программа и т.д.
Ну основное отличие в том, что в PowerShell объекты, поэтому возможна запись типа (ls)[0].Name
В PS всё то же самое, только по пайпам объекты идут.
Отношение к синтаксису — вещь субъективная. Хоть я и люблю .NET, но PowerShell банально не осилил.
Судя по яростному минусованию некоторые считают неприличным даже спросить, я никак не ожидал.
Там всё очень просто, что там можно не осилить?
Я и не говорю, что сложно — банально не понравилось.
Ну, хотя бы тем, что автокомплит в нём такой же дебильный, как и в cmd. Хоть он там и расширяемый, но такого же поведения, как в баше, добиться невозможно.
Пустой скрипт стартует 0.4 секунды. Например, команда
powerShell.exe "123"
На любой современной машине, в 64-битной оси.

Есть немало случаев, когда такое неприемлемо. Например, пользовательские шаги построения проектов в Visual Studio, когда в солюшне десятки проектов. Visual Studio обычно строит проект быстрее чем за секунду (C++ или C#).
PowerShell это в первую очередь shell. Эмулятор терминала там очень незначительно отличается от cmd.
PowerShell же язык, а не функциональность самой консоли! Все её проблемы, такие как ненормальный копи-паст, автокомплит и т.п. остаются.
Увы, MS объявило его устаревшим и поддерживать не будет. Да и утилиты в комплекте там весьма далеки от современного дистрибутива linux.
Порты от бсди в порядке.
О, Боже. Смотрите не поставьте это на РЕАЛЬНЫЙ сервис — если Вы читали README то должны понимать что установка этого пакета необратима + входит в конфликт со стандартным Windows окружением, ну и заодно пути для NTFS станут Case-Sentensive.
А на счет буфера обмена не пробовали пользоваться Shift+Insert?
ну в родной виндовой консоли работает, а у вас написано обратное. а в остальном я просто запускаю bash.exe
Специально сейчас проверил под Server 2008, под XP и под Server 2003. Просто cmd.exe

Не работает.

Пожалуйста, попробуйте тоже на какой-нибудь свежеустановленной (виртуальной) машине. Затем объясните нам, как Вы получили такую ценную фичу.
И правда не работает, видимо большую часть времени сижу в консоли FAR а там работает, что то не подумал что это фишка FAR.
Без мышки будет работать только нажать Alt-Spase выбрать там Edit и Paste
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
не работает, а очень бы хотелось
Сам пользуюсь GnuWin. А есть ли какие-то преимущества у UnxUtils?
Сейчас cygwin стал очень хорошим и терминал в комплекте нормальный есть и некоторая интеграция с консольным виндовым софтом.
Пакетный менеджер у него неудобен весьма — ведь в этой роли у него инсталлятор, в mingw гораздо лучше.
Если вам не нравится графический менеджер, то есть cyg-apt.
Для себя использую связку ConEmu + PATH, содержащий путь к гиту (установлен у многих разработчиков и дистрибутив содержит множество Unix-утилит).
А unix'овские утилиты с выводом от windows'ских справляются?

cygwin:
ipconfig /all | grep IP

портит кодировку
С выводом от windows'ских утилит не справляются даже другие windows'ские, потому что часть работает в 866, а часть — в 1251.

А для unix'овских можно iconv использовать.
UFO just landed and posted this here
Не выдумывайте, вывод идет в той кодировке, что указана. У меня это утф8 например.
Указана кем?
Попытка использования chcp
Вы знаете какой-то способ указать команде ipconfig кодировку?
Там ниже уже разобрались что в русской винде в части утилит текст захардкожен. Ну что я могу сказать? Не пользуйтесь локализациями, лол.
Кстати, как правильно «захардкожен» или «захардкоден»?
Понекрофилю тут, чтобы отобразилось правильно надо переключить в свойствах консоли шрифт с точечного на нормальный TrueType (при особом желании можно сделать прямо из командной строки, не используя диалог настроек).
Поставте утф8 везде и проблем не будет.
Где и как изменить кодировку, я так и не понял.
Спасибо автору за статью. Одно время сам хотел что то похожее написать, но руки не доходили )
У clink есть какие-то преимущества перед TCC/LE, кроме опенсорсности?
Предпочитаю Mintty+MSYS+MinGW. По-моему, неплохое сочетание — обновляется, есть пакетный менеджер. Git, увы, только отдельно придется ставить.
UFO just landed and posted this here
Гм, а Git Bash рассматривали? из того что я юзаю основных команд там только find не было и он быстро ставится как mingw пакет.
Первая запись в хелпе С-@: set-mark
Поясните пожалуйста, что в данном контексте значит @?

Правильно ли я ожидаю что, эта комбинация должна будет переключить коммандную строку в режим выделения текста?
У меня MinGW (тот что с Git-ом идет) и mintty.exe (более-менее правильный терминал, можно даже мышкой менять размер окна), а еще в стартовом скрипте я вызываю chcp.com 65001 (и в настройках терминала стоит utf-8). Короче почти все что нужно работает как надо.

И вот я решил проверить как работает ipconfig /all | grep IP
Проблему со слешем можно обойти минусом (ipconfig -all | grep IP) а кодировка должна была отработать правильно.

Но однако оказалось, что ipconfig даже в родной консоли работает только в кодировке 866, а в 65001 не работает.

Бу-Га-Га, 20-летняя ось, а тупит как курсовик второкурсника!
Откуда в ipconfig 866?
Вот фрагмент hexdump-а того, что выдал ipconfig -all > tmp.txt

0140  74 20 61 64 61 70 74 65  72 20 91 a5 e2 a5 a2 ae  t adapte r Сетево
0150  a5 20 af ae a4 aa ab ee  e7 a5 ad a8 a5 20 42 6c  е подклю чение Bl
0160  75 65 74 6f 6f 74 68 3a  0d 0a 0d 0a 20 20 20 4d  uetooth: ....   M

Первый символ в третей строке русская е и у нее код А5. Это кодировка cp866.
ipconfig -all > tmp.txt вызывался из штатной консоли cmd.exe сразу после вызова chcp 65001
Клёва! Ни разу в жизни не видел русскую винду…
Чтоб вставить текст из буфера обмена нужно тянуться к мышке
А я уже на автомате жму Alt-пробел, E, P. Намного быстрее выходит, чем мышью.
А rm -rf C:\ сработает? А прозрачный фон сделать можно? :)
Я бы воздаржался от перезаписывания в папке System32 тем более что есть лучше вариант.
Просто добавьте к переменной PATH путь к распакованым утилитам.
Из скрипта это делается так PATH=%PATH%;«c:\unixutills\bin»
Хм, о каком скрипте речь?
Если о cmd, то там set в начале не хватает
А для bash проценты выглядят чужеродно
да я имею ввиду cmd. Да нужен set для скрипта.
А умеет ли что-нибудь из всего этого работать с ssh по unix-way? Т.е. чтобы не надо было всякие окошки для создания сессии юзать, а можно было набрать «ssh user@server.com -p 2323» скажем. И чтобы можно было задать .ssh/config как в линуксах?
Sign up to leave a comment.

Articles