Комментарии 103
Полная коллекция unxutils.sourceforge.net/
А чем Cygwin не устроил? Он предоставляет даже привычное дерево ФС.
Пробовал Cygwin, не понравилось, т.к. нужно тогда вседа использовать именно его шелл.
Остановился на GnuWin + Far.
Остановился на GnuWin + Far.
+1 к Cygwin, все что надо есть, mintty в качестве терминала, шелл ставим любой, я настраивал zsh с плюшками, виндовому cmd даже и не снилось
Мне эта замечательная программа тоже очень понравилась. Тем, кто еще ее не попробовал, рекомендую прочитать этот топик: habrahabr.ru/post/164687/
Консолька не только имеет поддержку множества вкладок, но и отлично кастомизируется. Лично я настроил ее в стиле консоли из Quake, т.е. окно выезжает сверху экрана по нажатию «Ctrl + ~». На мой взгляд это не только эффектно выглядит, но и очень удобно в использовании. В качестве юниксовых утилит использую MSYS, который поставляется с MinGW.
Превьюшка:

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

глючит он ужасно и давно не поддерживается.
Кто не поддерживается? MSYS? Насколько я знаю, ведутся работы над MSYS2 в котором, в частности, юникод обещают.
Её запуск 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 не в состоянии её корректно редиректнуть.
На самом деле, терминал в 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
— запускаем процесс через 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 подразумевает «все есть файлы» — поэтому и работа в этом плане проще.
Изначально она пошла со времен 3.11, после в 95/98/2000 тоже запускалась по MSDOS принципу.
А вот уже в новых ОС — весь этот фунционал был заменен через Console API.
В Linux есть псевдотерминалы — да и вообще UNIX-way подразумевает «все есть файлы» — поэтому и работа в этом плане проще.
И я тут ещё подумал — если из этой консоли будет запущен процесс, работающий с уже выделенной консолью напрямую через API (тот же Telnet), то его функции не будут похучены, и соответственно ничего мы не увидим.
Т.е. хучить придётся не конкретное приложение, а пилить system-wide hook, срабатывающий по дескриптору конкретной консоли.
Т.е. хучить придётся не конкретное приложение, а пилить system-wide hook, срабатывающий по дескриптору конкретной консоли.
если новые процессы не создают новые экземпляры консоли и пишут все в один дескриптор — то можно обойтись и одним хуком.
Да ничего подобного. Родительское приложение (в частности, cmd.exe) висит в WaitForSingleObject в ожидании окончания работы запущенного процесса (в частности, telnet.exe). В таком подвешенном состоянии оно знать не знает ни о каких чтениях\записях в дескриптор. А телнет, в свою очередь, штука интерактивная, и ждет ввода от юзера. В итоге в консоли тишина. Собственно, насколько я понимаю, именно это явление мы и наблюдаем при попытке запустить telnet в предложенном выше редиректоре.
Её запуск 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 курсор показывается как неактивный
За сlink спасибо, стандартный автокомплит ужасен.
установка mingw msys даст нормальный терминал с практически полным набором утилит
Чем PowerShell не угодил?
unix-way как-то ближе.
Чем? Не холивара ради, но если вы смотрели на PowerShell, и он чем-то не нравится, хотелось бы знать, чем именно.
тем, что он _слишком_ фичаст для шелла?
я с PowerShell слишком плохо знаком, чтоб судить о нем. PowerShell наверняка не уступает инструментам мира Unix по возможностям, но дело в том, что линуксовыми тулзами я уже умею пользоваться а PowerShell'у нужно будет учиться. Ну и чисто субъективно мне нравятся концепции лежащие в основе Unix-Way: все потоки данных — это текст, одна задача — одна программа и т.д.
Отношение к синтаксису — вещь субъективная. Хоть я и люблю .NET, но PowerShell банально не осилил.
Ну, хотя бы тем, что автокомплит в нём такой же дебильный, как и в cmd. Хоть он там и расширяемый, но такого же поведения, как в баше, добиться невозможно.
Пустой скрипт стартует 0.4 секунды. Например, команда
Есть немало случаев, когда такое неприемлемо. Например, пользовательские шаги построения проектов в Visual Studio, когда в солюшне десятки проектов. Visual Studio обычно строит проект быстрее чем за секунду (C++ или C#).
powerShell.exe "123"
На любой современной машине, в 64-битной оси.Есть немало случаев, когда такое неприемлемо. Например, пользовательские шаги построения проектов в Visual Studio, когда в солюшне десятки проектов. Visual Studio обычно строит проект быстрее чем за секунду (C++ или C#).
PowerShell это в первую очередь shell. Эмулятор терминала там очень незначительно отличается от cmd.
PowerShell же язык, а не функциональность самой консоли! Все её проблемы, такие как ненормальный копи-паст, автокомплит и т.п. остаются.
Есть ещё Windows Services for UNIX от Microsoft.
Увы, MS объявило его устаревшим и поддерживать не будет. Да и утилиты в комплекте там весьма далеки от современного дистрибутива linux.
О, Боже. Смотрите не поставьте это на РЕАЛЬНЫЙ сервис — если Вы читали README то должны понимать что установка этого пакета необратима + входит в конфликт со стандартным Windows окружением, ну и заодно пути для NTFS станут Case-Sentensive.
А на счет буфера обмена не пробовали пользоваться Shift+Insert?
Пробовали. Не работает
ну в родной виндовой консоли работает, а у вас написано обратное. а в остальном я просто запускаю bash.exe
Специально сейчас проверил под Server 2008, под XP и под Server 2003. Просто
Не работает.
Пожалуйста, попробуйте тоже на какой-нибудь свежеустановленной (виртуальной) машине. Затем объясните нам, как Вы получили такую ценную фичу.
cmd.exe
Не работает.
Пожалуйста, попробуйте тоже на какой-нибудь свежеустановленной (виртуальной) машине. Затем объясните нам, как Вы получили такую ценную фичу.
не работает, а очень бы хотелось
Сейчас cygwin стал очень хорошим и терминал в комплекте нормальный есть и некоторая интеграция с консольным виндовым софтом.
А unix'овские утилиты с выводом от windows'ских справляются?
cygwin:
ipconfig /all | grep IP
портит кодировку
cygwin:
ipconfig /all | grep IP
портит кодировку
С выводом от windows'ских утилит не справляются даже другие windows'ские, потому что часть работает в 866, а часть — в 1251.
А для unix'овских можно iconv использовать.
А для unix'овских можно iconv использовать.
Не выдумывайте, вывод идет в той кодировке, что указана. У меня это утф8 например.
Указана кем?
Попытка использования chcp
Вы знаете какой-то способ указать команде ipconfig кодировку?
Там ниже уже разобрались что в русской винде в части утилит текст захардкожен. Ну что я могу сказать? Не пользуйтесь локализациями, лол.
Понекрофилю тут, чтобы отобразилось правильно надо переключить в свойствах консоли шрифт с точечного на нормальный TrueType (при особом желании можно сделать прямо из командной строки, не используя диалог настроек).
Поставте утф8 везде и проблем не будет.
Где и как изменить кодировку, я так и не понял.
Про CygWin тут — cygwin.com/cygwin-ug-net/setup-locale.html
Для винды вам надо выполнить chcp 65001.
Для винды вам надо выполнить chcp 65001.
Спасибо автору за статью. Одно время сам хотел что то похожее написать, но руки не доходили )
Предпочитаю Mintty+MSYS+MinGW. По-моему, неплохое сочетание — обновляется, есть пакетный менеджер. Git, увы, только отдельно придется ставить.
Гм, а 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 /all | grep IP
Проблему со слешем можно обойти минусом (ipconfig -all | grep IP) а кодировка должна была отработать правильно.
Но однако оказалось, что ipconfig даже в родной консоли работает только в кодировке 866, а в 65001 не работает.
Бу-Га-Га, 20-летняя ось, а тупит как курсовик второкурсника!
Откуда в ipconfig 866?
Вот фрагмент hexdump-а того, что выдал
Первый символ в третей строке русская е и у нее код А5. Это кодировка cp866.
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Даже вроде бы работает в связке с ConEmu — очень неплохо. Спасибо за дельную утилиту.
Чтоб вставить текст из буфера обмена нужно тянуться к мышкеА я уже на автомате жму Alt-пробел, E, P. Намного быстрее выходит, чем мышью.
пользуюсь git Bash
А rm -rf C:\ сработает? А прозрачный фон сделать можно? :)
Я бы воздаржался от перезаписывания в папке System32 тем более что есть лучше вариант.
Просто добавьте к переменной PATH путь к распакованым утилитам.
Из скрипта это делается так PATH=%PATH%;«c:\unixutills\bin»
Просто добавьте к переменной PATH путь к распакованым утилитам.
Из скрипта это делается так PATH=%PATH%;«c:\unixutills\bin»
А умеет ли что-нибудь из всего этого работать с ssh по unix-way? Т.е. чтобы не надо было всякие окошки для создания сессии юзать, а можно было набрать «ssh user@server.com -p 2323» скажем. И чтобы можно было задать .ssh/config как в линуксах?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Переносим функциональность bash в cmd.exe